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
@@ -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];
@@ -17,7 +17,14 @@ export const NOTIFICATION_TYPES = [
17
17
  'EVENT_STARTED',
18
18
  'EVENT_FINAL_ROUND',
19
19
  'EVENT_FINISHED',
20
- 'REGION_RELOCATION'
20
+ 'REGION_RELOCATION',
21
+ 'WNL_CALLUP_OPEN',
22
+ 'WNL_CALLUP_DEADLINE',
23
+ 'WNL_CALLUP_CLOSED',
24
+ 'WNL_LEAGUE_START',
25
+ 'WNL_FINALS_START',
26
+ 'WNL_CHAMPION',
27
+ 'WNL_PLAYER_CALLED_UP'
21
28
  ];
22
29
  // The 7 supported locales. Must stay in sync with the API VALID_LOCALES set and the UI src/locales/*.json.
23
30
  export const NOTIFICATION_LOCALES = ['en', 'es', 'fr', 'it', 'pl', 'pt-BR', 'tr'];
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from '@jest/globals';
2
2
  import { NOTIFICATION_TYPES, NOTIFICATION_LOCALES, pushEnabledFor } from './notification-type';
3
- import { NOTIFICATION_REGISTRY, PUSH_NOTIFICATION_TYPES } from './registry';
3
+ import { NOTIFICATION_REGISTRY, PUSH_NOTIFICATION_TYPES, PUSH_PREF_KEYS, pushEnabledForType, pushPrefKeyFor } from './registry';
4
4
  import { NOTIFICATION_CATALOG } from './catalog';
5
5
  import { renderPush, notificationPath, interpolate, translateNotification } from './render';
6
6
  function readNested(node, dotKey) {
@@ -143,4 +143,22 @@ describe('push preferences (PUSH_NOTIFICATION_TYPES + pushEnabledFor)', () => {
143
143
  // disabling one type does not affect another
144
144
  expect(pushEnabledFor({ MATCH_RESULT: false }, 'INJURY')).toBe(true);
145
145
  });
146
+ it('groups the WNL types under the single WNL preference key', () => {
147
+ // Every WNL type resolves to the shared toggle; ungrouped types resolve to themselves.
148
+ for (const type of NOTIFICATION_TYPES.filter((t) => t.startsWith('WNL_'))) {
149
+ expect(pushPrefKeyFor(type)).toBe('WNL');
150
+ }
151
+ expect(pushPrefKeyFor('MATCH_RESULT')).toBe('MATCH_RESULT');
152
+ expect(pushPrefKeyFor('UNKNOWN_TYPE')).toBe('UNKNOWN_TYPE');
153
+ // The one WNL toggle gates every WNL type's push; individual WNL type keys are never consulted.
154
+ expect(pushEnabledForType({ WNL: false }, 'WNL_CALLUP_OPEN')).toBe(false);
155
+ expect(pushEnabledForType({ WNL: false }, 'WNL_CHAMPION')).toBe(false);
156
+ expect(pushEnabledForType({}, 'WNL_CHAMPION')).toBe(true);
157
+ expect(pushEnabledForType({ WNL_CHAMPION: false }, 'WNL_CHAMPION')).toBe(true);
158
+ expect(pushEnabledForType({ MATCH_RESULT: false }, 'MATCH_RESULT')).toBe(false);
159
+ // The toggleable key set collapses the seven WNL types into one 'WNL' entry and keeps the rest per-type.
160
+ expect(PUSH_PREF_KEYS.filter((k) => k === 'WNL')).toHaveLength(1);
161
+ expect(PUSH_PREF_KEYS).not.toContain('WNL_CALLUP_OPEN');
162
+ expect(PUSH_PREF_KEYS).toContain('MATCH_RESULT');
163
+ });
146
164
  });
@@ -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,4 +1,4 @@
1
- import { NOTIFICATION_TYPES } from './notification-type';
1
+ import { NOTIFICATION_TYPES, pushEnabledFor } from './notification-type';
2
2
  function readString(value) {
3
3
  return typeof value === 'string' && value !== '' ? value : null;
4
4
  }
@@ -168,9 +168,94 @@ export const NOTIFICATION_REGISTRY = {
168
168
  pushBodyKey: 'regionRelocation.body',
169
169
  inAppMessageKey: 'regionRelocation.body',
170
170
  catalogKeys: ['regionRelocation.title', 'regionRelocation.body']
171
+ },
172
+ // World Nations League (owner 2026-08-28). All seven share the single 'WNL' preference toggle. The three callup
173
+ // types go to national team managers, LEAGUE_START/FINALS_START/CHAMPION are broadcast to every active user, and
174
+ // PLAYER_CALLED_UP goes to club owners with at least one player in a finalized squad.
175
+ WNL_CALLUP_OPEN: {
176
+ emitsPush: true,
177
+ prefKey: 'WNL',
178
+ deepLink: () => '/wnl/callup',
179
+ pushTitleKey: 'wnlCallupOpen.title',
180
+ pushBodyKey: 'wnlCallupOpen.body',
181
+ inAppMessageKey: 'wnlCallupOpen.body',
182
+ // The deadline arrives pre-formatted (locale-neutral 'YYYY-MM-DD HH:mm UTC') because the stored payload is
183
+ // shared by the push and the in-app bell and cannot be re-localised per render.
184
+ params: (p) => ({ date: readString(p.deadline) ?? '' }),
185
+ catalogKeys: ['wnlCallupOpen.title', 'wnlCallupOpen.body']
186
+ },
187
+ WNL_CALLUP_DEADLINE: {
188
+ emitsPush: true,
189
+ prefKey: 'WNL',
190
+ deepLink: () => '/wnl/callup',
191
+ pushTitleKey: 'wnlCallupDeadline.title',
192
+ pushBodyKey: 'wnlCallupDeadline.body',
193
+ inAppMessageKey: 'wnlCallupDeadline.body',
194
+ catalogKeys: ['wnlCallupDeadline.title', 'wnlCallupDeadline.body']
195
+ },
196
+ WNL_CALLUP_CLOSED: {
197
+ emitsPush: true,
198
+ prefKey: 'WNL',
199
+ deepLink: () => '/wnl/manage/lineup',
200
+ pushTitleKey: 'wnlCallupClosed.title',
201
+ pushBodyKey: 'wnlCallupClosed.body',
202
+ inAppMessageKey: 'wnlCallupClosed.body',
203
+ catalogKeys: ['wnlCallupClosed.title', 'wnlCallupClosed.body']
204
+ },
205
+ WNL_LEAGUE_START: {
206
+ emitsPush: true,
207
+ prefKey: 'WNL',
208
+ deepLink: () => '/wnl',
209
+ pushTitleKey: 'wnlLeagueStart.title',
210
+ pushBodyKey: 'wnlLeagueStart.body',
211
+ inAppMessageKey: 'wnlLeagueStart.body',
212
+ catalogKeys: ['wnlLeagueStart.title', 'wnlLeagueStart.body']
213
+ },
214
+ WNL_FINALS_START: {
215
+ emitsPush: true,
216
+ prefKey: 'WNL',
217
+ deepLink: () => '/wnl/finals',
218
+ pushTitleKey: 'wnlFinalsStart.title',
219
+ pushBodyKey: 'wnlFinalsStart.body',
220
+ inAppMessageKey: 'wnlFinalsStart.body',
221
+ catalogKeys: ['wnlFinalsStart.title', 'wnlFinalsStart.body']
222
+ },
223
+ WNL_CHAMPION: {
224
+ emitsPush: true,
225
+ prefKey: 'WNL',
226
+ deepLink: () => '/wnl/finals',
227
+ pushTitleKey: 'wnlChampion.title',
228
+ // A missing team name never renders a subjectless sentence (mirrors the MATCH_RESULT named/unnamed split).
229
+ pushBodyKey: (p) => readString(p.team) != null ? 'wnlChampion.body' : 'wnlChampion.bodyUnnamed',
230
+ inAppMessageKey: (p) => readString(p.team) != null ? 'wnlChampion.body' : 'wnlChampion.bodyUnnamed',
231
+ params: (p) => ({ team: readString(p.team) ?? '' }),
232
+ catalogKeys: ['wnlChampion.title', 'wnlChampion.body', 'wnlChampion.bodyUnnamed']
233
+ },
234
+ WNL_PLAYER_CALLED_UP: {
235
+ emitsPush: true,
236
+ prefKey: 'WNL',
237
+ deepLink: () => '/wnl/teams',
238
+ pushTitleKey: 'wnlPlayerCalledUp.title',
239
+ pushBodyKey: 'wnlPlayerCalledUp.body',
240
+ inAppMessageKey: 'wnlPlayerCalledUp.body',
241
+ catalogKeys: ['wnlPlayerCalledUp.title', 'wnlPlayerCalledUp.body']
171
242
  }
172
243
  };
173
244
  // The notification types that emit a mobile push (everything except COMPENSATION). Source of truth = each
174
- // descriptor's emitsPush, so this cannot drift. This is the user-toggleable set surfaced in the mobile app's
175
- // notification settings and validated by the API before persisting a preference.
245
+ // descriptor's emitsPush, so this cannot drift.
176
246
  export const PUSH_NOTIFICATION_TYPES = NOTIFICATION_TYPES.filter((type) => NOTIFICATION_REGISTRY[type].emitsPush);
247
+ // The preference-map key a type's push toggle lives under: the descriptor's prefKey (group toggle) or the type
248
+ // itself. Unknown types resolve to themselves, mirroring pushEnabledFor's loose-string tolerance.
249
+ export function pushPrefKeyFor(type) {
250
+ const descriptor = NOTIFICATION_REGISTRY[type];
251
+ return descriptor?.prefKey ?? type;
252
+ }
253
+ // Group-aware push gate: like pushEnabledFor, but resolves the type's preference GROUP first, so muting the one
254
+ // 'WNL' toggle suppresses every WNL type's push. Senders (Sim/API insertNotification) use THIS, not pushEnabledFor.
255
+ export function pushEnabledForType(prefs, type) {
256
+ return pushEnabledFor(prefs, pushPrefKeyFor(type));
257
+ }
258
+ // The user-toggleable keys surfaced in the mobile app's notification settings and validated by the API before
259
+ // persisting a preference: one entry per DISTINCT pref key (individual types plus each group toggle once),
260
+ // in first-appearance order.
261
+ export const PUSH_PREF_KEYS = [...new Set(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;
@@ -17,3 +17,9 @@ export function premiumTierDef(tier) {
17
17
  export function hasTier(effectiveTier, required) {
18
18
  return effectiveTier >= required;
19
19
  }
20
+ // Tier 2 (NATIONAL) unlocks World Cup / national-team management (claiming and managing a national team, the WNL
21
+ // callup, lineup and kit). Gate every national-team write on this.
22
+ export const TIER_NATIONAL = 2;
23
+ export function canManageNationalTeam(effectiveTier) {
24
+ return hasTier(effectiveTier, TIER_NATIONAL);
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.523",
3
+ "version": "0.0.525",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",