volleyballsimtypes 0.0.523 → 0.0.525

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 (79) hide show
  1. package/dist/cjs/src/api/index.d.ts +16 -0
  2. package/dist/cjs/src/data/init-models.js +35 -0
  3. package/dist/cjs/src/data/models/competition.d.ts +1 -1
  4. package/dist/cjs/src/data/models/competition.js +1 -1
  5. package/dist/cjs/src/data/models/index.d.ts +6 -0
  6. package/dist/cjs/src/data/models/index.js +6 -0
  7. package/dist/cjs/src/data/models/jersey-badge.d.ts +1 -1
  8. package/dist/cjs/src/data/models/jersey-badge.js +1 -1
  9. package/dist/cjs/src/data/models/match-input-snapshot.d.ts +19 -0
  10. package/dist/cjs/src/data/models/match-input-snapshot.js +34 -0
  11. package/dist/cjs/src/data/models/national-team-claim.d.ts +21 -0
  12. package/dist/cjs/src/data/models/national-team-claim.js +36 -0
  13. package/dist/cjs/src/data/models/national-team.d.ts +22 -0
  14. package/dist/cjs/src/data/models/national-team.js +31 -0
  15. package/dist/cjs/src/data/models/wnl-callup.d.ts +31 -0
  16. package/dist/cjs/src/data/models/wnl-callup.js +45 -0
  17. package/dist/cjs/src/data/models/wnl-season.d.ts +24 -0
  18. package/dist/cjs/src/data/models/wnl-season.js +34 -0
  19. package/dist/cjs/src/data/models/wnl-squad.d.ts +40 -0
  20. package/dist/cjs/src/data/models/wnl-squad.js +59 -0
  21. package/dist/cjs/src/service/match/index.d.ts +1 -0
  22. package/dist/cjs/src/service/match/index.js +8 -0
  23. package/dist/cjs/src/service/match/match-generator.d.ts +5 -1
  24. package/dist/cjs/src/service/match/match-generator.js +6 -4
  25. package/dist/cjs/src/service/notification/catalog/en.json +29 -0
  26. package/dist/cjs/src/service/notification/catalog/es.json +29 -0
  27. package/dist/cjs/src/service/notification/catalog/fr.json +29 -0
  28. package/dist/cjs/src/service/notification/catalog/it.json +29 -0
  29. package/dist/cjs/src/service/notification/catalog/pl.json +29 -0
  30. package/dist/cjs/src/service/notification/catalog/pt-BR.json +29 -0
  31. package/dist/cjs/src/service/notification/catalog/tr.json +29 -0
  32. package/dist/cjs/src/service/notification/notification-type.d.ts +1 -1
  33. package/dist/cjs/src/service/notification/notification-type.js +8 -1
  34. package/dist/cjs/src/service/notification/notification.test.js +18 -0
  35. package/dist/cjs/src/service/notification/payloads.d.ts +7 -1
  36. package/dist/cjs/src/service/notification/registry.d.ts +5 -1
  37. package/dist/cjs/src/service/notification/registry.js +90 -3
  38. package/dist/cjs/src/service/premium/premium-tier.d.ts +2 -0
  39. package/dist/cjs/src/service/premium/premium-tier.js +8 -1
  40. package/dist/esm/src/api/index.d.ts +16 -0
  41. package/dist/esm/src/data/init-models.js +36 -1
  42. package/dist/esm/src/data/models/competition.d.ts +1 -1
  43. package/dist/esm/src/data/models/competition.js +1 -1
  44. package/dist/esm/src/data/models/index.d.ts +6 -0
  45. package/dist/esm/src/data/models/index.js +6 -0
  46. package/dist/esm/src/data/models/jersey-badge.d.ts +1 -1
  47. package/dist/esm/src/data/models/jersey-badge.js +1 -1
  48. package/dist/esm/src/data/models/match-input-snapshot.d.ts +19 -0
  49. package/dist/esm/src/data/models/match-input-snapshot.js +30 -0
  50. package/dist/esm/src/data/models/national-team-claim.d.ts +21 -0
  51. package/dist/esm/src/data/models/national-team-claim.js +32 -0
  52. package/dist/esm/src/data/models/national-team.d.ts +22 -0
  53. package/dist/esm/src/data/models/national-team.js +27 -0
  54. package/dist/esm/src/data/models/wnl-callup.d.ts +31 -0
  55. package/dist/esm/src/data/models/wnl-callup.js +41 -0
  56. package/dist/esm/src/data/models/wnl-season.d.ts +24 -0
  57. package/dist/esm/src/data/models/wnl-season.js +30 -0
  58. package/dist/esm/src/data/models/wnl-squad.d.ts +40 -0
  59. package/dist/esm/src/data/models/wnl-squad.js +55 -0
  60. package/dist/esm/src/service/match/index.d.ts +1 -0
  61. package/dist/esm/src/service/match/index.js +3 -0
  62. package/dist/esm/src/service/match/match-generator.d.ts +5 -1
  63. package/dist/esm/src/service/match/match-generator.js +6 -4
  64. package/dist/esm/src/service/notification/catalog/en.json +29 -0
  65. package/dist/esm/src/service/notification/catalog/es.json +29 -0
  66. package/dist/esm/src/service/notification/catalog/fr.json +29 -0
  67. package/dist/esm/src/service/notification/catalog/it.json +29 -0
  68. package/dist/esm/src/service/notification/catalog/pl.json +29 -0
  69. package/dist/esm/src/service/notification/catalog/pt-BR.json +29 -0
  70. package/dist/esm/src/service/notification/catalog/tr.json +29 -0
  71. package/dist/esm/src/service/notification/notification-type.d.ts +1 -1
  72. package/dist/esm/src/service/notification/notification-type.js +8 -1
  73. package/dist/esm/src/service/notification/notification.test.js +19 -1
  74. package/dist/esm/src/service/notification/payloads.d.ts +7 -1
  75. package/dist/esm/src/service/notification/registry.d.ts +5 -1
  76. package/dist/esm/src/service/notification/registry.js +88 -3
  77. package/dist/esm/src/service/premium/premium-tier.d.ts +2 -0
  78. package/dist/esm/src/service/premium/premium-tier.js +6 -0
  79. package/package.json +1 -1
@@ -16,12 +16,14 @@ dayjs_1.default.extend(utc_1.default);
16
16
  const MATCH_SPACING_MINUTES = 30;
17
17
  // eslint-disable-next-line @typescript-eslint/no-extraneous-class
18
18
  class MatchGenerator {
19
- static generateMatches(teams, baseDate) {
19
+ static generateMatches(teams, baseDate, options = {}) {
20
+ const spacingMinutes = options.spacingMinutes ?? MATCH_SPACING_MINUTES;
21
+ const startHourUTC = options.startHourUTC ?? 0;
20
22
  const t = new Set(teams.map(x => x.id));
21
- // Anchor the first match to 00:00 UTC of the iteration's start day (Monday), so league rounds fall on the
23
+ // Anchor the first match to `startHourUTC`:00 UTC of the iteration's start day (Monday), so rounds fall on the
22
24
  // same wall-clock time everywhere regardless of the host timezone. startOf('day') in UTC avoids the
23
25
  // local-timezone roll the old startOf('hour') was exposed to on a fractional-hour-offset host.
24
- let date = dayjs_1.default.utc(baseDate).startOf('day');
26
+ let date = dayjs_1.default.utc(baseDate).startOf('day').add(startHourUTC, 'hour');
25
27
  if (t.size !== teams.length) {
26
28
  throw new Error('DUPLICATE_TEAMS');
27
29
  }
@@ -30,7 +32,7 @@ class MatchGenerator {
30
32
  }
31
33
  const nextDate = () => {
32
34
  const scheduledDate = date.toDate();
33
- date = date.add(MATCH_SPACING_MINUTES, 'minutes');
35
+ date = date.add(spacingMinutes, 'minutes');
34
36
  return scheduledDate;
35
37
  };
36
38
  // First leg: one pass of the round robin, matches laid out back to back in round order.
@@ -62,5 +62,34 @@
62
62
  "regionRelocation": {
63
63
  "title": "Your team is moving",
64
64
  "body": "Your team has been chosen to be moved to the new region: Kyorin. Nothing has changed in terms of the team you manage, your players or anything else."
65
+ },
66
+ "wnlCallupOpen": {
67
+ "title": "National call-up open",
68
+ "body": "The national call-up phase has begun! You have until {{date}} to select your team to participate in the next edition of the WNL."
69
+ },
70
+ "wnlCallupDeadline": {
71
+ "title": "Call-up deadline today",
72
+ "body": "The national call-up deadline is today. Make sure you have selected the players that will participate in the next edition of the WNL."
73
+ },
74
+ "wnlCallupClosed": {
75
+ "title": "National call-up closed",
76
+ "body": "The national call-up phase has ended. You can edit your line-up to prepare for the WNL starting next Monday!"
77
+ },
78
+ "wnlLeagueStart": {
79
+ "title": "WNL league started",
80
+ "body": "The WNL League phase has started!"
81
+ },
82
+ "wnlFinalsStart": {
83
+ "title": "WNL finals started",
84
+ "body": "The WNL finals have started!"
85
+ },
86
+ "wnlChampion": {
87
+ "title": "WNL champions crowned",
88
+ "body": "The WNL edition has ended. {{team}} are the WNL champions!",
89
+ "bodyUnnamed": "The WNL edition has ended. The champions have been crowned!"
90
+ },
91
+ "wnlPlayerCalledUp": {
92
+ "title": "Players called up",
93
+ "body": "One or more of your players have been called-up to their national team!"
65
94
  }
66
95
  }
@@ -62,5 +62,34 @@
62
62
  "regionRelocation": {
63
63
  "title": "Tu equipo se traslada",
64
64
  "body": "Tu equipo ha sido elegido para trasladarse a la nueva región: Kyorin. No cambia nada en cuanto al equipo que gestionas, tus jugadores ni nada más."
65
+ },
66
+ "wnlCallupOpen": {
67
+ "title": "Convocatoria nacional abierta",
68
+ "body": "¡La fase de convocatoria nacional ha comenzado! Tienes hasta el {{date}} para seleccionar tu equipo y participar en la próxima edición de la WNL."
69
+ },
70
+ "wnlCallupDeadline": {
71
+ "title": "La convocatoria cierra hoy",
72
+ "body": "El plazo de la convocatoria nacional termina hoy. Asegúrate de haber seleccionado a los jugadores que participarán en la próxima edición de la WNL."
73
+ },
74
+ "wnlCallupClosed": {
75
+ "title": "Convocatoria nacional cerrada",
76
+ "body": "La fase de convocatoria nacional ha terminado. ¡Puedes editar tu alineación para preparar la WNL que empieza el próximo lunes!"
77
+ },
78
+ "wnlLeagueStart": {
79
+ "title": "La liga WNL ha empezado",
80
+ "body": "¡La fase de liga de la WNL ha comenzado!"
81
+ },
82
+ "wnlFinalsStart": {
83
+ "title": "Las finales de la WNL han empezado",
84
+ "body": "¡Las finales de la WNL han comenzado!"
85
+ },
86
+ "wnlChampion": {
87
+ "title": "Campeones de la WNL",
88
+ "body": "La edición de la WNL ha terminado. ¡{{team}} son los campeones de la WNL!",
89
+ "bodyUnnamed": "La edición de la WNL ha terminado. ¡Ya hay campeones!"
90
+ },
91
+ "wnlPlayerCalledUp": {
92
+ "title": "Jugadores convocados",
93
+ "body": "¡Uno o más de tus jugadores han sido convocados por su selección nacional!"
65
94
  }
66
95
  }
@@ -62,5 +62,34 @@
62
62
  "regionRelocation": {
63
63
  "title": "Votre équipe déménage",
64
64
  "body": "Votre équipe a été choisie pour être transférée vers la nouvelle région : Kyorin. Rien ne change concernant l'équipe que vous gérez, vos joueurs ni quoi que ce soit d'autre."
65
+ },
66
+ "wnlCallupOpen": {
67
+ "title": "Convocation nationale ouverte",
68
+ "body": "La phase de convocation nationale a commencé ! Vous avez jusqu'au {{date}} pour sélectionner votre équipe et participer à la prochaine édition de la WNL."
69
+ },
70
+ "wnlCallupDeadline": {
71
+ "title": "La convocation se termine aujourd'hui",
72
+ "body": "La date limite de la convocation nationale est aujourd'hui. Assurez-vous d'avoir sélectionné les joueurs qui participeront à la prochaine édition de la WNL."
73
+ },
74
+ "wnlCallupClosed": {
75
+ "title": "Convocation nationale terminée",
76
+ "body": "La phase de convocation nationale est terminée. Vous pouvez modifier votre composition pour préparer la WNL qui commence lundi prochain !"
77
+ },
78
+ "wnlLeagueStart": {
79
+ "title": "La ligue WNL a commencé",
80
+ "body": "La phase de ligue de la WNL a commencé !"
81
+ },
82
+ "wnlFinalsStart": {
83
+ "title": "Les finales de la WNL ont commencé",
84
+ "body": "Les finales de la WNL ont commencé !"
85
+ },
86
+ "wnlChampion": {
87
+ "title": "Champions de la WNL",
88
+ "body": "L'édition de la WNL est terminée. {{team}} sont les champions de la WNL !",
89
+ "bodyUnnamed": "L'édition de la WNL est terminée. Les champions sont couronnés !"
90
+ },
91
+ "wnlPlayerCalledUp": {
92
+ "title": "Joueurs convoqués",
93
+ "body": "Un ou plusieurs de vos joueurs ont été convoqués par leur équipe nationale !"
65
94
  }
66
95
  }
@@ -62,5 +62,34 @@
62
62
  "regionRelocation": {
63
63
  "title": "La tua squadra si trasferisce",
64
64
  "body": "La tua squadra è stata scelta per essere spostata nella nuova regione: Kyorin. Non cambia nulla riguardo alla squadra che gestisci, ai tuoi giocatori o a qualsiasi altra cosa."
65
+ },
66
+ "wnlCallupOpen": {
67
+ "title": "Convocazione nazionale aperta",
68
+ "body": "La fase di convocazione nazionale è iniziata! Hai tempo fino al {{date}} per selezionare la tua squadra e partecipare alla prossima edizione della WNL."
69
+ },
70
+ "wnlCallupDeadline": {
71
+ "title": "La convocazione scade oggi",
72
+ "body": "Il termine della convocazione nazionale è oggi. Assicurati di aver selezionato i giocatori che parteciperanno alla prossima edizione della WNL."
73
+ },
74
+ "wnlCallupClosed": {
75
+ "title": "Convocazione nazionale chiusa",
76
+ "body": "La fase di convocazione nazionale è terminata. Puoi modificare la tua formazione per preparare la WNL che inizia lunedì prossimo!"
77
+ },
78
+ "wnlLeagueStart": {
79
+ "title": "La lega WNL è iniziata",
80
+ "body": "La fase di lega della WNL è iniziata!"
81
+ },
82
+ "wnlFinalsStart": {
83
+ "title": "Le finali della WNL sono iniziate",
84
+ "body": "Le finali della WNL sono iniziate!"
85
+ },
86
+ "wnlChampion": {
87
+ "title": "Campioni della WNL",
88
+ "body": "L'edizione della WNL è terminata. {{team}} sono i campioni della WNL!",
89
+ "bodyUnnamed": "L'edizione della WNL è terminata. I campioni sono stati incoronati!"
90
+ },
91
+ "wnlPlayerCalledUp": {
92
+ "title": "Giocatori convocati",
93
+ "body": "Uno o più dei tuoi giocatori sono stati convocati dalla loro nazionale!"
65
94
  }
66
95
  }
@@ -62,5 +62,34 @@
62
62
  "regionRelocation": {
63
63
  "title": "Twoja drużyna się przenosi",
64
64
  "body": "Twoja drużyna została wybrana do przeniesienia do nowego regionu: Kyorin. Nic się nie zmienia, jeśli chodzi o zarządzaną przez ciebie drużynę, twoich zawodników ani cokolwiek innego."
65
+ },
66
+ "wnlCallupOpen": {
67
+ "title": "Powołania do reprezentacji otwarte",
68
+ "body": "Faza powołań do reprezentacji rozpoczęła się! Masz czas do {{date}}, aby wybrać swoją drużynę do udziału w następnej edycji WNL."
69
+ },
70
+ "wnlCallupDeadline": {
71
+ "title": "Termin powołań mija dzisiaj",
72
+ "body": "Termin powołań do reprezentacji mija dzisiaj. Upewnij się, że wybrałeś zawodników, którzy wezmą udział w następnej edycji WNL."
73
+ },
74
+ "wnlCallupClosed": {
75
+ "title": "Powołania do reprezentacji zamknięte",
76
+ "body": "Faza powołań do reprezentacji zakończyła się. Możesz edytować swój skład, aby przygotować się do WNL, która zaczyna się w najbliższy poniedziałek!"
77
+ },
78
+ "wnlLeagueStart": {
79
+ "title": "Liga WNL rozpoczęta",
80
+ "body": "Faza ligowa WNL rozpoczęła się!"
81
+ },
82
+ "wnlFinalsStart": {
83
+ "title": "Finały WNL rozpoczęte",
84
+ "body": "Finały WNL rozpoczęły się!"
85
+ },
86
+ "wnlChampion": {
87
+ "title": "Mistrzowie WNL",
88
+ "body": "Edycja WNL zakończyła się. {{team}} to mistrzowie WNL!",
89
+ "bodyUnnamed": "Edycja WNL zakończyła się. Mistrzowie zostali wyłonieni!"
90
+ },
91
+ "wnlPlayerCalledUp": {
92
+ "title": "Zawodnicy powołani",
93
+ "body": "Co najmniej jeden z twoich zawodników został powołany do swojej reprezentacji!"
65
94
  }
66
95
  }
@@ -62,5 +62,34 @@
62
62
  "regionRelocation": {
63
63
  "title": "Seu time está mudando",
64
64
  "body": "Seu time foi escolhido para ser movido para a nova região: Kyorin. Nada muda em relação ao time que você gerencia, seus jogadores ou qualquer outra coisa."
65
+ },
66
+ "wnlCallupOpen": {
67
+ "title": "Convocação nacional aberta",
68
+ "body": "A fase de convocação nacional começou! Você tem até {{date}} para selecionar seu time e participar da próxima edição da WNL."
69
+ },
70
+ "wnlCallupDeadline": {
71
+ "title": "A convocação termina hoje",
72
+ "body": "O prazo da convocação nacional termina hoje. Verifique se você selecionou os jogadores que participarão da próxima edição da WNL."
73
+ },
74
+ "wnlCallupClosed": {
75
+ "title": "Convocação nacional encerrada",
76
+ "body": "A fase de convocação nacional terminou. Você pode editar sua escalação para se preparar para a WNL que começa na próxima segunda-feira!"
77
+ },
78
+ "wnlLeagueStart": {
79
+ "title": "A liga WNL começou",
80
+ "body": "A fase de liga da WNL começou!"
81
+ },
82
+ "wnlFinalsStart": {
83
+ "title": "As finais da WNL começaram",
84
+ "body": "As finais da WNL começaram!"
85
+ },
86
+ "wnlChampion": {
87
+ "title": "Campeões da WNL",
88
+ "body": "A edição da WNL terminou. {{team}} são os campeões da WNL!",
89
+ "bodyUnnamed": "A edição da WNL terminou. Os campeões foram coroados!"
90
+ },
91
+ "wnlPlayerCalledUp": {
92
+ "title": "Jogadores convocados",
93
+ "body": "Um ou mais dos seus jogadores foram convocados pela sua seleção nacional!"
65
94
  }
66
95
  }
@@ -62,5 +62,34 @@
62
62
  "regionRelocation": {
63
63
  "title": "Takımın taşınıyor",
64
64
  "body": "Takımın yeni bölgeye, Kyorin'e taşınmak üzere seçildi. Yönettiğin takım, oyuncuların ya da başka hiçbir şey açısından hiçbir şey değişmiyor."
65
+ },
66
+ "wnlCallupOpen": {
67
+ "title": "Milli takım kadro çağrısı açıldı",
68
+ "body": "Milli takım kadro çağrısı başladı! Bir sonraki WNL sezonuna katılacak takımını seçmek için {{date}} tarihine kadar vaktin var."
69
+ },
70
+ "wnlCallupDeadline": {
71
+ "title": "Kadro çağrısı bugün sona eriyor",
72
+ "body": "Milli takım kadro çağrısının son günü bugün. Bir sonraki WNL sezonunda oynayacak oyuncuları seçtiğinden emin ol."
73
+ },
74
+ "wnlCallupClosed": {
75
+ "title": "Kadro çağrısı kapandı",
76
+ "body": "Milli takım kadro çağrısı sona erdi. Önümüzdeki pazartesi başlayacak WNL için dizilişini düzenleyebilirsin!"
77
+ },
78
+ "wnlLeagueStart": {
79
+ "title": "WNL ligi başladı",
80
+ "body": "WNL lig aşaması başladı!"
81
+ },
82
+ "wnlFinalsStart": {
83
+ "title": "WNL finalleri başladı",
84
+ "body": "WNL finalleri başladı!"
85
+ },
86
+ "wnlChampion": {
87
+ "title": "WNL şampiyonları",
88
+ "body": "WNL sezonu sona erdi. {{team}} WNL şampiyonu oldu!",
89
+ "bodyUnnamed": "WNL sezonu sona erdi. Şampiyonlar belli oldu!"
90
+ },
91
+ "wnlPlayerCalledUp": {
92
+ "title": "Oyuncular milli takıma çağrıldı",
93
+ "body": "Bir veya daha fazla oyuncun milli takımına çağrıldı!"
65
94
  }
66
95
  }
@@ -1,4 +1,4 @@
1
- export declare const NOTIFICATION_TYPES: readonly ["MATCH_RESULT", "INJURY", "INJURY_RECOVERED", "SEASON_END", "GRANT_RECEIVED", "PROMOTION", "DAILY_LOGIN", "WELCOME", "COMPENSATION", "EVENT_REGISTRATION_OPEN", "EVENT_REGISTRATION_CLOSING", "EVENT_STARTED", "EVENT_FINAL_ROUND", "EVENT_FINISHED", "REGION_RELOCATION"];
1
+ export declare const NOTIFICATION_TYPES: readonly ["MATCH_RESULT", "INJURY", "INJURY_RECOVERED", "SEASON_END", "GRANT_RECEIVED", "PROMOTION", "DAILY_LOGIN", "WELCOME", "COMPENSATION", "EVENT_REGISTRATION_OPEN", "EVENT_REGISTRATION_CLOSING", "EVENT_STARTED", "EVENT_FINAL_ROUND", "EVENT_FINISHED", "REGION_RELOCATION", "WNL_CALLUP_OPEN", "WNL_CALLUP_DEADLINE", "WNL_CALLUP_CLOSED", "WNL_LEAGUE_START", "WNL_FINALS_START", "WNL_CHAMPION", "WNL_PLAYER_CALLED_UP"];
2
2
  export type NotificationType = typeof NOTIFICATION_TYPES[number];
3
3
  export declare const NOTIFICATION_LOCALES: readonly ["en", "es", "fr", "it", "pl", "pt-BR", "tr"];
4
4
  export type NotificationLocale = typeof NOTIFICATION_LOCALES[number];
@@ -22,7 +22,14 @@ exports.NOTIFICATION_TYPES = [
22
22
  'EVENT_STARTED',
23
23
  'EVENT_FINAL_ROUND',
24
24
  'EVENT_FINISHED',
25
- 'REGION_RELOCATION'
25
+ 'REGION_RELOCATION',
26
+ 'WNL_CALLUP_OPEN',
27
+ 'WNL_CALLUP_DEADLINE',
28
+ 'WNL_CALLUP_CLOSED',
29
+ 'WNL_LEAGUE_START',
30
+ 'WNL_FINALS_START',
31
+ 'WNL_CHAMPION',
32
+ 'WNL_PLAYER_CALLED_UP'
26
33
  ];
27
34
  // The 7 supported locales. Must stay in sync with the API VALID_LOCALES set and the UI src/locales/*.json.
28
35
  exports.NOTIFICATION_LOCALES = ['en', 'es', 'fr', 'it', 'pl', 'pt-BR', 'tr'];
@@ -145,4 +145,22 @@ function flattenStrings(node, prefix = '') {
145
145
  // disabling one type does not affect another
146
146
  (0, globals_1.expect)((0, notification_type_1.pushEnabledFor)({ MATCH_RESULT: false }, 'INJURY')).toBe(true);
147
147
  });
148
+ (0, globals_1.it)('groups the WNL types under the single WNL preference key', () => {
149
+ // Every WNL type resolves to the shared toggle; ungrouped types resolve to themselves.
150
+ for (const type of notification_type_1.NOTIFICATION_TYPES.filter((t) => t.startsWith('WNL_'))) {
151
+ (0, globals_1.expect)((0, registry_1.pushPrefKeyFor)(type)).toBe('WNL');
152
+ }
153
+ (0, globals_1.expect)((0, registry_1.pushPrefKeyFor)('MATCH_RESULT')).toBe('MATCH_RESULT');
154
+ (0, globals_1.expect)((0, registry_1.pushPrefKeyFor)('UNKNOWN_TYPE')).toBe('UNKNOWN_TYPE');
155
+ // The one WNL toggle gates every WNL type's push; individual WNL type keys are never consulted.
156
+ (0, globals_1.expect)((0, registry_1.pushEnabledForType)({ WNL: false }, 'WNL_CALLUP_OPEN')).toBe(false);
157
+ (0, globals_1.expect)((0, registry_1.pushEnabledForType)({ WNL: false }, 'WNL_CHAMPION')).toBe(false);
158
+ (0, globals_1.expect)((0, registry_1.pushEnabledForType)({}, 'WNL_CHAMPION')).toBe(true);
159
+ (0, globals_1.expect)((0, registry_1.pushEnabledForType)({ WNL_CHAMPION: false }, 'WNL_CHAMPION')).toBe(true);
160
+ (0, globals_1.expect)((0, registry_1.pushEnabledForType)({ MATCH_RESULT: false }, 'MATCH_RESULT')).toBe(false);
161
+ // The toggleable key set collapses the seven WNL types into one 'WNL' entry and keeps the rest per-type.
162
+ (0, globals_1.expect)(registry_1.PUSH_PREF_KEYS.filter((k) => k === 'WNL')).toHaveLength(1);
163
+ (0, globals_1.expect)(registry_1.PUSH_PREF_KEYS).not.toContain('WNL_CALLUP_OPEN');
164
+ (0, globals_1.expect)(registry_1.PUSH_PREF_KEYS).toContain('MATCH_RESULT');
165
+ });
148
166
  });
@@ -31,4 +31,10 @@ export interface PromotionPayload {
31
31
  teamId?: string;
32
32
  amount?: number;
33
33
  }
34
- export type NotificationPayload = MatchResultPayload | InjuryPayload | InjuryRecoveredPayload | SeasonEndPayload | PromotionPayload | Record<string, unknown>;
34
+ export interface WnlCallupOpenPayload {
35
+ deadline?: string;
36
+ }
37
+ export interface WnlChampionPayload {
38
+ team?: string;
39
+ }
40
+ export type NotificationPayload = MatchResultPayload | InjuryPayload | InjuryRecoveredPayload | SeasonEndPayload | PromotionPayload | WnlCallupOpenPayload | WnlChampionPayload | Record<string, unknown>;
@@ -1,7 +1,8 @@
1
- import { type NotificationType } from './notification-type';
1
+ import { type NotificationPreferences, type NotificationType } from './notification-type';
2
2
  export type CatalogKeyResolver = string | ((payload: Record<string, unknown>) => string);
3
3
  export interface NotificationDescriptor {
4
4
  emitsPush: boolean;
5
+ prefKey?: string;
5
6
  deepLink?: (payload: Record<string, unknown>) => string;
6
7
  pushTitleKey?: CatalogKeyResolver;
7
8
  pushBodyKey?: CatalogKeyResolver;
@@ -12,3 +13,6 @@ export interface NotificationDescriptor {
12
13
  }
13
14
  export declare const NOTIFICATION_REGISTRY: Record<NotificationType, NotificationDescriptor>;
14
15
  export declare const PUSH_NOTIFICATION_TYPES: NotificationType[];
16
+ export declare function pushPrefKeyFor(type: string): string;
17
+ export declare function pushEnabledForType(prefs: NotificationPreferences | null | undefined, type: string): boolean;
18
+ export declare const PUSH_PREF_KEYS: string[];
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PUSH_NOTIFICATION_TYPES = exports.NOTIFICATION_REGISTRY = void 0;
3
+ exports.PUSH_PREF_KEYS = exports.PUSH_NOTIFICATION_TYPES = exports.NOTIFICATION_REGISTRY = void 0;
4
+ exports.pushPrefKeyFor = pushPrefKeyFor;
5
+ exports.pushEnabledForType = pushEnabledForType;
4
6
  const notification_type_1 = require("./notification-type");
5
7
  function readString(value) {
6
8
  return typeof value === 'string' && value !== '' ? value : null;
@@ -171,9 +173,94 @@ exports.NOTIFICATION_REGISTRY = {
171
173
  pushBodyKey: 'regionRelocation.body',
172
174
  inAppMessageKey: 'regionRelocation.body',
173
175
  catalogKeys: ['regionRelocation.title', 'regionRelocation.body']
176
+ },
177
+ // World Nations League (owner 2026-08-28). All seven share the single 'WNL' preference toggle. The three callup
178
+ // types go to national team managers, LEAGUE_START/FINALS_START/CHAMPION are broadcast to every active user, and
179
+ // PLAYER_CALLED_UP goes to club owners with at least one player in a finalized squad.
180
+ WNL_CALLUP_OPEN: {
181
+ emitsPush: true,
182
+ prefKey: 'WNL',
183
+ deepLink: () => '/wnl/callup',
184
+ pushTitleKey: 'wnlCallupOpen.title',
185
+ pushBodyKey: 'wnlCallupOpen.body',
186
+ inAppMessageKey: 'wnlCallupOpen.body',
187
+ // The deadline arrives pre-formatted (locale-neutral 'YYYY-MM-DD HH:mm UTC') because the stored payload is
188
+ // shared by the push and the in-app bell and cannot be re-localised per render.
189
+ params: (p) => ({ date: readString(p.deadline) ?? '' }),
190
+ catalogKeys: ['wnlCallupOpen.title', 'wnlCallupOpen.body']
191
+ },
192
+ WNL_CALLUP_DEADLINE: {
193
+ emitsPush: true,
194
+ prefKey: 'WNL',
195
+ deepLink: () => '/wnl/callup',
196
+ pushTitleKey: 'wnlCallupDeadline.title',
197
+ pushBodyKey: 'wnlCallupDeadline.body',
198
+ inAppMessageKey: 'wnlCallupDeadline.body',
199
+ catalogKeys: ['wnlCallupDeadline.title', 'wnlCallupDeadline.body']
200
+ },
201
+ WNL_CALLUP_CLOSED: {
202
+ emitsPush: true,
203
+ prefKey: 'WNL',
204
+ deepLink: () => '/wnl/manage/lineup',
205
+ pushTitleKey: 'wnlCallupClosed.title',
206
+ pushBodyKey: 'wnlCallupClosed.body',
207
+ inAppMessageKey: 'wnlCallupClosed.body',
208
+ catalogKeys: ['wnlCallupClosed.title', 'wnlCallupClosed.body']
209
+ },
210
+ WNL_LEAGUE_START: {
211
+ emitsPush: true,
212
+ prefKey: 'WNL',
213
+ deepLink: () => '/wnl',
214
+ pushTitleKey: 'wnlLeagueStart.title',
215
+ pushBodyKey: 'wnlLeagueStart.body',
216
+ inAppMessageKey: 'wnlLeagueStart.body',
217
+ catalogKeys: ['wnlLeagueStart.title', 'wnlLeagueStart.body']
218
+ },
219
+ WNL_FINALS_START: {
220
+ emitsPush: true,
221
+ prefKey: 'WNL',
222
+ deepLink: () => '/wnl/finals',
223
+ pushTitleKey: 'wnlFinalsStart.title',
224
+ pushBodyKey: 'wnlFinalsStart.body',
225
+ inAppMessageKey: 'wnlFinalsStart.body',
226
+ catalogKeys: ['wnlFinalsStart.title', 'wnlFinalsStart.body']
227
+ },
228
+ WNL_CHAMPION: {
229
+ emitsPush: true,
230
+ prefKey: 'WNL',
231
+ deepLink: () => '/wnl/finals',
232
+ pushTitleKey: 'wnlChampion.title',
233
+ // A missing team name never renders a subjectless sentence (mirrors the MATCH_RESULT named/unnamed split).
234
+ pushBodyKey: (p) => readString(p.team) != null ? 'wnlChampion.body' : 'wnlChampion.bodyUnnamed',
235
+ inAppMessageKey: (p) => readString(p.team) != null ? 'wnlChampion.body' : 'wnlChampion.bodyUnnamed',
236
+ params: (p) => ({ team: readString(p.team) ?? '' }),
237
+ catalogKeys: ['wnlChampion.title', 'wnlChampion.body', 'wnlChampion.bodyUnnamed']
238
+ },
239
+ WNL_PLAYER_CALLED_UP: {
240
+ emitsPush: true,
241
+ prefKey: 'WNL',
242
+ deepLink: () => '/wnl/teams',
243
+ pushTitleKey: 'wnlPlayerCalledUp.title',
244
+ pushBodyKey: 'wnlPlayerCalledUp.body',
245
+ inAppMessageKey: 'wnlPlayerCalledUp.body',
246
+ catalogKeys: ['wnlPlayerCalledUp.title', 'wnlPlayerCalledUp.body']
174
247
  }
175
248
  };
176
249
  // The notification types that emit a mobile push (everything except COMPENSATION). Source of truth = each
177
- // descriptor's emitsPush, so this cannot drift. This is the user-toggleable set surfaced in the mobile app's
178
- // notification settings and validated by the API before persisting a preference.
250
+ // descriptor's emitsPush, so this cannot drift.
179
251
  exports.PUSH_NOTIFICATION_TYPES = notification_type_1.NOTIFICATION_TYPES.filter((type) => exports.NOTIFICATION_REGISTRY[type].emitsPush);
252
+ // The preference-map key a type's push toggle lives under: the descriptor's prefKey (group toggle) or the type
253
+ // itself. Unknown types resolve to themselves, mirroring pushEnabledFor's loose-string tolerance.
254
+ function pushPrefKeyFor(type) {
255
+ const descriptor = exports.NOTIFICATION_REGISTRY[type];
256
+ return descriptor?.prefKey ?? type;
257
+ }
258
+ // Group-aware push gate: like pushEnabledFor, but resolves the type's preference GROUP first, so muting the one
259
+ // 'WNL' toggle suppresses every WNL type's push. Senders (Sim/API insertNotification) use THIS, not pushEnabledFor.
260
+ function pushEnabledForType(prefs, type) {
261
+ return (0, notification_type_1.pushEnabledFor)(prefs, pushPrefKeyFor(type));
262
+ }
263
+ // The user-toggleable keys surfaced in the mobile app's notification settings and validated by the API before
264
+ // persisting a preference: one entry per DISTINCT pref key (individual types plus each group toggle once),
265
+ // in first-appearance order.
266
+ exports.PUSH_PREF_KEYS = [...new Set(exports.PUSH_NOTIFICATION_TYPES.map((type) => pushPrefKeyFor(type)))];
@@ -8,3 +8,5 @@ export declare const PREMIUM_TIERS: PremiumTierDef[];
8
8
  export declare const MAX_PREMIUM_TIER: number;
9
9
  export declare function premiumTierDef(tier: number): PremiumTierDef | undefined;
10
10
  export declare function hasTier(effectiveTier: number, required: number): boolean;
11
+ export declare const TIER_NATIONAL = 2;
12
+ export declare function canManageNationalTeam(effectiveTier: number): boolean;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MAX_PREMIUM_TIER = exports.PREMIUM_TIERS = exports.NO_PREMIUM = void 0;
3
+ exports.TIER_NATIONAL = exports.MAX_PREMIUM_TIER = exports.PREMIUM_TIERS = exports.NO_PREMIUM = void 0;
4
4
  exports.premiumTierDef = premiumTierDef;
5
5
  exports.hasTier = hasTier;
6
+ exports.canManageNationalTeam = canManageNationalTeam;
6
7
  // Hierarchical premium tiers (owner 2026-08-17): tier N grants everything below it, so a feature gate is just
7
8
  // `effectiveTier >= required`. Tiers are NUMERIC and code-defined here (the DB stores only the number), so adding a
8
9
  // tier needs no migration. Names/keys are display + gating helpers. Keep PREMIUM_TIERS ascending by tier. See
@@ -22,3 +23,9 @@ function premiumTierDef(tier) {
22
23
  function hasTier(effectiveTier, required) {
23
24
  return effectiveTier >= required;
24
25
  }
26
+ // Tier 2 (NATIONAL) unlocks World Cup / national-team management (claiming and managing a national team, the WNL
27
+ // callup, lineup and kit). Gate every national-team write on this.
28
+ exports.TIER_NATIONAL = 2;
29
+ function canManageNationalTeam(effectiveTier) {
30
+ return hasTier(effectiveTier, exports.TIER_NATIONAL);
31
+ }
@@ -70,6 +70,8 @@ export type ChampionBadgeSpec = {
70
70
  region: ChampionRegion;
71
71
  } | {
72
72
  type: 'wcc';
73
+ } | {
74
+ type: 'wnl';
73
75
  };
74
76
  export type Player = Omit<DataProps<_Player>, 'stats' | 'birthAge' | 'birthIteration' | 'declineProfile' | 'nickname' | 'injuryProneProfile' | 'injury'> & {
75
77
  -readonly [K in 'birthAge' | 'birthIteration']?: DataProps<_Player>[K];
@@ -83,6 +85,7 @@ export type Player = Omit<DataProps<_Player>, 'stats' | 'birthAge' | 'birthItera
83
85
  nickname?: string;
84
86
  jerseyConfig?: JerseyConfig;
85
87
  championBadge?: ChampionBadgeSpec;
88
+ nationalFlagAlpha2?: string;
86
89
  };
87
90
  export interface StartingLineup {
88
91
  [CourtPosition.LEFT_FRONT]: string;
@@ -189,6 +192,12 @@ export type Team = Omit<DataProps<_Team>, 'roster' | '_rating' | 'rating' | 'tac
189
192
  };
190
193
  nationalCountryName?: string;
191
194
  isEvent?: boolean;
195
+ isNational?: boolean;
196
+ nationalManager?: {
197
+ displayName: string;
198
+ teamId: string;
199
+ teamShortName: string;
200
+ };
192
201
  };
193
202
  export type Standing = DataProps<_Standing> & {
194
203
  position: number;
@@ -255,4 +264,11 @@ export type TotalBoxScore = Omit<DataProps<BoxScore>, 'misc' | 'playerId' | 'mat
255
264
  setsPlayed: number;
256
265
  matchesPlayed: number;
257
266
  };
267
+ national?: {
268
+ alpha2: string;
269
+ matchesPlayed: number;
270
+ matchesWon: number;
271
+ pointsPlayed: number;
272
+ pointsWon: number;
273
+ };
258
274
  };
@@ -1,4 +1,4 @@
1
- import { AuthIdentityModel, AuthSessionModel, AuthUserModel, BoxScoreModel, CoachModel, ScoutModel, PhysicianModel, PhysiotherapistModel, BoxScoreTotalsModel, CompetitionChampionModel, JerseyBadgeModel, CurrencyTransactionModel, GachaPityModel, GachaPullHistoryModel, WishlistModel, UserSettingsModel, UserAchievementsModel, UserDeviceTokenModel, BasePositionPresetModel, CompetitionMatchModel, CompetitionMVPModel, CompetitionModel, CompetitionStandingsMatchModel, CompetitionStandingsModel, CompetitionTeamsModel, CountryModel, DivisionModel, DivisionSeasonModel, IterationModel, LeagueModel, MatchModel, MatchRatingModel, MatchResultModel, MatchSetModel, PerformanceStatsModel, PlayerModel, PlayerImprovementLogModel, PlayerDeclineLogModel, PlayerTeamModel, RetiredPlayerModel, PromotionMatchModel, FriendlyModel, RegionQualifierModel, NationalCountryModel, RallyModel, TacticsModel, TeamJerseyModel, LineupPresetModel, MatchPresetModel, EventModel, EventCompetitionModel, EventSquadModel, EventPackModel, EventPackPlayerModel, EventResultModel, EventBotTeamModel, TeamModel, TeamReplacementModel, UserCurrencyModel, UserPlayerProgressModel, UserPullGrantModel, PremiumGrantModel, UserTeamModel, VPERModel, NotificationModel, AppConfigModel, LegacyTeamFlagModel } from './models';
1
+ import { AuthIdentityModel, AuthSessionModel, AuthUserModel, BoxScoreModel, CoachModel, ScoutModel, PhysicianModel, PhysiotherapistModel, BoxScoreTotalsModel, CompetitionChampionModel, JerseyBadgeModel, CurrencyTransactionModel, GachaPityModel, GachaPullHistoryModel, WishlistModel, UserSettingsModel, UserAchievementsModel, UserDeviceTokenModel, BasePositionPresetModel, CompetitionMatchModel, CompetitionMVPModel, CompetitionModel, CompetitionStandingsMatchModel, CompetitionStandingsModel, CompetitionTeamsModel, CountryModel, DivisionModel, DivisionSeasonModel, IterationModel, LeagueModel, MatchModel, MatchRatingModel, MatchResultModel, MatchSetModel, PerformanceStatsModel, PlayerModel, PlayerImprovementLogModel, PlayerDeclineLogModel, PlayerTeamModel, RetiredPlayerModel, PromotionMatchModel, FriendlyModel, RegionQualifierModel, NationalCountryModel, NationalTeamModel, NationalTeamClaimModel, WnlSquadModel, WnlCallupModel, WnlSeasonModel, RallyModel, MatchInputSnapshotModel, TacticsModel, TeamJerseyModel, LineupPresetModel, MatchPresetModel, EventModel, EventCompetitionModel, EventSquadModel, EventPackModel, EventPackPlayerModel, EventResultModel, EventBotTeamModel, TeamModel, TeamReplacementModel, UserCurrencyModel, UserPlayerProgressModel, UserPullGrantModel, PremiumGrantModel, UserTeamModel, VPERModel, NotificationModel, AppConfigModel, LegacyTeamFlagModel } from './models';
2
2
  export function initModels(sequelize) {
3
3
  const Coach = CoachModel.initModel(sequelize);
4
4
  const Scout = ScoutModel.initModel(sequelize);
@@ -58,10 +58,16 @@ export function initModels(sequelize) {
58
58
  const PlayerTeam = PlayerTeamModel.initModel(sequelize);
59
59
  const RetiredPlayer = RetiredPlayerModel.initModel(sequelize);
60
60
  const Rally = RallyModel.initModel(sequelize);
61
+ const MatchInputSnapshot = MatchInputSnapshotModel.initModel(sequelize);
61
62
  const PromotionMatch = PromotionMatchModel.initModel(sequelize);
62
63
  const Friendly = FriendlyModel.initModel(sequelize);
63
64
  const RegionQualifier = RegionQualifierModel.initModel(sequelize);
64
65
  const NationalCountry = NationalCountryModel.initModel(sequelize);
66
+ const NationalTeam = NationalTeamModel.initModel(sequelize);
67
+ const NationalTeamClaim = NationalTeamClaimModel.initModel(sequelize);
68
+ const WnlSquad = WnlSquadModel.initModel(sequelize);
69
+ const WnlCallup = WnlCallupModel.initModel(sequelize);
70
+ const WnlSeason = WnlSeasonModel.initModel(sequelize);
65
71
  const Team = TeamModel.initModel(sequelize);
66
72
  const TeamReplacement = TeamReplacementModel.initModel(sequelize);
67
73
  const LegacyTeamFlag = LegacyTeamFlagModel.initModel(sequelize);
@@ -159,6 +165,8 @@ export function initModels(sequelize) {
159
165
  Match.hasOne(CompetitionMatch, { as: 'CompetitionMatch', foreignKey: 'match_id' });
160
166
  Match.hasOne(MatchResult, { as: 'MatchResult', foreignKey: 'match_id' });
161
167
  Match.hasOne(Friendly, { as: 'Friendly', foreignKey: 'match_id' });
168
+ Match.hasOne(MatchInputSnapshot, { as: 'MatchInputSnapshot', foreignKey: 'match_id' });
169
+ MatchInputSnapshot.belongsTo(Match, { as: 'Match', foreignKey: 'match_id' });
162
170
  MatchResult.belongsTo(Match, { as: 'Match', foreignKey: 'match_id' });
163
171
  MatchResult.belongsTo(Team, { as: 'Winner', foreignKey: 'winner_team_id' });
164
172
  MatchRating.belongsTo(Match, { as: 'match', foreignKey: 'match_id' });
@@ -225,6 +233,28 @@ export function initModels(sequelize) {
225
233
  Competition.hasOne(NationalCountry, { as: 'NationalCountry', foreignKey: 'competition_id' });
226
234
  Country.hasMany(NationalCountry, { as: 'NationalCountries', foreignKey: 'country_id' });
227
235
  Iteration.hasMany(NationalCountry, { as: 'NationalCountries', foreignKey: 'iteration' });
236
+ // National teams (WNL). The registry maps a country to its permanent active=false national Team; the claim links a
237
+ // Tier-2 manager to it; per-edition squad + callup + season rows hang off the WNL league Competition.
238
+ NationalTeam.belongsTo(Country, { as: 'country', foreignKey: 'country_id' });
239
+ NationalTeam.belongsTo(Team, { as: 'team', foreignKey: 'team_id' });
240
+ Country.hasOne(NationalTeam, { as: 'NationalTeam', foreignKey: 'country_id' });
241
+ Team.hasOne(NationalTeam, { as: 'NationalTeam', foreignKey: 'team_id' });
242
+ NationalTeam.hasOne(NationalTeamClaim, { as: 'claim', foreignKey: 'country_id' });
243
+ NationalTeamClaim.belongsTo(NationalTeam, { as: 'nationalTeam', foreignKey: 'country_id' });
244
+ NationalTeamClaim.belongsTo(AuthUser, { as: 'user', foreignKey: 'user_id' });
245
+ AuthUser.hasOne(NationalTeamClaim, { as: 'NationalTeamClaim', foreignKey: 'user_id' });
246
+ WnlSquad.belongsTo(Competition, { as: 'competition', foreignKey: 'competition_id' });
247
+ WnlSquad.belongsTo(Country, { as: 'country', foreignKey: 'country_id' });
248
+ WnlSquad.belongsTo(Team, { as: 'team', foreignKey: 'team_id' });
249
+ WnlSquad.belongsTo(AuthUser, { as: 'manager', foreignKey: 'manager_user_id' });
250
+ Competition.hasMany(WnlSquad, { as: 'WnlSquads', foreignKey: 'competition_id' });
251
+ WnlCallup.belongsTo(Competition, { as: 'competition', foreignKey: 'competition_id' });
252
+ WnlCallup.belongsTo(Player, { as: 'player', foreignKey: 'player_id' });
253
+ WnlCallup.belongsTo(Country, { as: 'country', foreignKey: 'country_id' });
254
+ Competition.hasMany(WnlCallup, { as: 'WnlCallups', foreignKey: 'competition_id' });
255
+ WnlSeason.belongsTo(Competition, { as: 'competition', foreignKey: 'competition_id' });
256
+ WnlSeason.belongsTo(Competition, { as: 'finalsCompetition', foreignKey: 'finals_competition_id' });
257
+ Competition.hasOne(WnlSeason, { as: 'WnlSeason', foreignKey: 'competition_id' });
228
258
  VPER.belongsTo(Player, { as: 'Player', foreignKey: 'player_id' });
229
259
  VPER.belongsTo(Match, { as: 'Match', foreignKey: 'match_id' });
230
260
  Team.hasOne(Coach, { as: 'Coach', foreignKey: 'team_id' });
@@ -348,6 +378,11 @@ export function initModels(sequelize) {
348
378
  Friendly,
349
379
  RegionQualifier,
350
380
  NationalCountry,
381
+ NationalTeam,
382
+ NationalTeamClaim,
383
+ WnlSquad,
384
+ WnlCallup,
385
+ WnlSeason,
351
386
  Rally,
352
387
  Team,
353
388
  TeamReplacement,
@@ -21,7 +21,7 @@ export interface CompetitionAttributes {
21
21
  LowerPromotionMatches?: PromotionMatchAttributes[];
22
22
  }
23
23
  export type CompetitionPk = 'competition_id';
24
- export type CompetitionType = 'LEAGUE' | 'TOURNAMENT' | 'QUALIFIER' | 'NATIONAL' | 'EVENT';
24
+ export type CompetitionType = 'LEAGUE' | 'TOURNAMENT' | 'QUALIFIER' | 'NATIONAL' | 'EVENT' | 'WNL' | 'WNLF';
25
25
  export type CompetitionId = CompetitionModel[CompetitionPk];
26
26
  export type CompetitionCreationAttributes = CompetitionAttributes;
27
27
  export declare class CompetitionModel extends Model<CompetitionAttributes, CompetitionCreationAttributes> implements CompetitionAttributes {
@@ -18,7 +18,7 @@ export class CompetitionModel extends Model {
18
18
  }
19
19
  },
20
20
  type: {
21
- type: DataTypes.ENUM('LEAGUE', 'TOURNAMENT', 'QUALIFIER', 'NATIONAL', 'EVENT'),
21
+ type: DataTypes.ENUM('LEAGUE', 'TOURNAMENT', 'QUALIFIER', 'NATIONAL', 'EVENT', 'WNL', 'WNLF'),
22
22
  allowNull: false
23
23
  },
24
24
  status: {