volleyballsimtypes 0.0.487 → 0.0.488

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.
@@ -10,6 +10,7 @@ export interface UserSettingsAttributes {
10
10
  user_id: string;
11
11
  auto_dismiss: AutoDismissSettings;
12
12
  locale: string | null;
13
+ notifications: Record<string, boolean>;
13
14
  }
14
15
  export type UserSettingsPk = 'user_id';
15
16
  export type UserSettingsId = UserSettingsModel[UserSettingsPk];
@@ -18,6 +19,7 @@ export declare class UserSettingsModel extends Model<UserSettingsAttributes, Use
18
19
  user_id: string;
19
20
  auto_dismiss: AutoDismissSettings;
20
21
  locale: string | null;
22
+ notifications: Record<string, boolean>;
21
23
  user: AuthUserModel;
22
24
  getUser: Sequelize.BelongsToGetAssociationMixin<AuthUserModel>;
23
25
  setUser: Sequelize.BelongsToSetAssociationMixin<AuthUserModel, AuthUserId>;
@@ -23,6 +23,11 @@ class UserSettingsModel extends sequelize_1.Model {
23
23
  type: sequelize_1.DataTypes.STRING(8),
24
24
  allowNull: true,
25
25
  defaultValue: null
26
+ },
27
+ notifications: {
28
+ type: sequelize_1.DataTypes.JSONB,
29
+ allowNull: false,
30
+ defaultValue: {}
26
31
  }
27
32
  }, {
28
33
  sequelize,
@@ -4,3 +4,5 @@ export declare const NOTIFICATION_LOCALES: readonly ["en", "es", "fr", "it", "pl
4
4
  export type NotificationLocale = typeof NOTIFICATION_LOCALES[number];
5
5
  export declare const DEFAULT_NOTIFICATION_LOCALE: NotificationLocale;
6
6
  export declare function normalizeNotificationLocale(locale: string | null | undefined): NotificationLocale;
7
+ export type NotificationPreferences = Record<string, boolean>;
8
+ export declare function pushEnabledFor(prefs: NotificationPreferences | null | undefined, type: string): boolean;
@@ -6,6 +6,7 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.DEFAULT_NOTIFICATION_LOCALE = exports.NOTIFICATION_LOCALES = exports.NOTIFICATION_TYPES = void 0;
8
8
  exports.normalizeNotificationLocale = normalizeNotificationLocale;
9
+ exports.pushEnabledFor = pushEnabledFor;
9
10
  exports.NOTIFICATION_TYPES = [
10
11
  'MATCH_RESULT',
11
12
  'INJURY',
@@ -28,3 +29,8 @@ function normalizeNotificationLocale(locale) {
28
29
  }
29
30
  return exports.DEFAULT_NOTIFICATION_LOCALE;
30
31
  }
32
+ // Whether `type`'s mobile push should be sent for a user with these preferences (absent/true = send, false = suppress).
33
+ // Accepts a plain string like renderPush so a loose/unknown type still resolves (unknown = enabled).
34
+ function pushEnabledFor(prefs, type) {
35
+ return prefs?.[type] !== false;
36
+ }
@@ -126,3 +126,21 @@ function flattenStrings(node, prefix = '') {
126
126
  (0, globals_1.expect)((0, render_1.notificationPath)('COMPENSATION', {})).toBe('/');
127
127
  });
128
128
  });
129
+ (0, globals_1.describe)('push preferences (PUSH_NOTIFICATION_TYPES + pushEnabledFor)', () => {
130
+ (0, globals_1.it)('is exactly the emitsPush types, COMPENSATION excluded', () => {
131
+ (0, globals_1.expect)([...registry_1.PUSH_NOTIFICATION_TYPES].sort((a, b) => a.localeCompare(b)))
132
+ .toEqual(notification_type_1.NOTIFICATION_TYPES.filter((t) => registry_1.NOTIFICATION_REGISTRY[t].emitsPush).sort((a, b) => a.localeCompare(b)));
133
+ (0, globals_1.expect)(registry_1.PUSH_NOTIFICATION_TYPES).not.toContain('COMPENSATION');
134
+ (0, globals_1.expect)(registry_1.PUSH_NOTIFICATION_TYPES).toContain('MATCH_RESULT');
135
+ (0, globals_1.expect)(registry_1.PUSH_NOTIFICATION_TYPES).toHaveLength(8);
136
+ });
137
+ (0, globals_1.it)('is opt-out: absent / null / empty / true all enable, only explicit false suppresses', () => {
138
+ (0, globals_1.expect)((0, notification_type_1.pushEnabledFor)(undefined, 'MATCH_RESULT')).toBe(true);
139
+ (0, globals_1.expect)((0, notification_type_1.pushEnabledFor)(null, 'MATCH_RESULT')).toBe(true);
140
+ (0, globals_1.expect)((0, notification_type_1.pushEnabledFor)({}, 'MATCH_RESULT')).toBe(true);
141
+ (0, globals_1.expect)((0, notification_type_1.pushEnabledFor)({ MATCH_RESULT: true }, 'MATCH_RESULT')).toBe(true);
142
+ (0, globals_1.expect)((0, notification_type_1.pushEnabledFor)({ MATCH_RESULT: false }, 'MATCH_RESULT')).toBe(false);
143
+ // disabling one type does not affect another
144
+ (0, globals_1.expect)((0, notification_type_1.pushEnabledFor)({ MATCH_RESULT: false }, 'INJURY')).toBe(true);
145
+ });
146
+ });
@@ -11,3 +11,4 @@ export interface NotificationDescriptor {
11
11
  catalogKeys: string[];
12
12
  }
13
13
  export declare const NOTIFICATION_REGISTRY: Record<NotificationType, NotificationDescriptor>;
14
+ export declare const PUSH_NOTIFICATION_TYPES: NotificationType[];
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NOTIFICATION_REGISTRY = void 0;
3
+ exports.PUSH_NOTIFICATION_TYPES = exports.NOTIFICATION_REGISTRY = void 0;
4
+ const notification_type_1 = require("./notification-type");
4
5
  function readString(value) {
5
6
  return typeof value === 'string' && value !== '' ? value : null;
6
7
  }
@@ -110,3 +111,7 @@ exports.NOTIFICATION_REGISTRY = {
110
111
  catalogKeys: []
111
112
  }
112
113
  };
114
+ // The notification types that emit a mobile push (everything except COMPENSATION). Source of truth = each
115
+ // descriptor's emitsPush, so this cannot drift. This is the user-toggleable set surfaced in the mobile app's
116
+ // notification settings and validated by the API before persisting a preference.
117
+ exports.PUSH_NOTIFICATION_TYPES = notification_type_1.NOTIFICATION_TYPES.filter((type) => exports.NOTIFICATION_REGISTRY[type].emitsPush);
@@ -10,6 +10,7 @@ export interface UserSettingsAttributes {
10
10
  user_id: string;
11
11
  auto_dismiss: AutoDismissSettings;
12
12
  locale: string | null;
13
+ notifications: Record<string, boolean>;
13
14
  }
14
15
  export type UserSettingsPk = 'user_id';
15
16
  export type UserSettingsId = UserSettingsModel[UserSettingsPk];
@@ -18,6 +19,7 @@ export declare class UserSettingsModel extends Model<UserSettingsAttributes, Use
18
19
  user_id: string;
19
20
  auto_dismiss: AutoDismissSettings;
20
21
  locale: string | null;
22
+ notifications: Record<string, boolean>;
21
23
  user: AuthUserModel;
22
24
  getUser: Sequelize.BelongsToGetAssociationMixin<AuthUserModel>;
23
25
  setUser: Sequelize.BelongsToSetAssociationMixin<AuthUserModel, AuthUserId>;
@@ -20,6 +20,11 @@ export class UserSettingsModel extends Model {
20
20
  type: DataTypes.STRING(8),
21
21
  allowNull: true,
22
22
  defaultValue: null
23
+ },
24
+ notifications: {
25
+ type: DataTypes.JSONB,
26
+ allowNull: false,
27
+ defaultValue: {}
23
28
  }
24
29
  }, {
25
30
  sequelize,
@@ -4,3 +4,5 @@ export declare const NOTIFICATION_LOCALES: readonly ["en", "es", "fr", "it", "pl
4
4
  export type NotificationLocale = typeof NOTIFICATION_LOCALES[number];
5
5
  export declare const DEFAULT_NOTIFICATION_LOCALE: NotificationLocale;
6
6
  export declare function normalizeNotificationLocale(locale: string | null | undefined): NotificationLocale;
7
+ export type NotificationPreferences = Record<string, boolean>;
8
+ export declare function pushEnabledFor(prefs: NotificationPreferences | null | undefined, type: string): boolean;
@@ -24,3 +24,8 @@ export function normalizeNotificationLocale(locale) {
24
24
  }
25
25
  return DEFAULT_NOTIFICATION_LOCALE;
26
26
  }
27
+ // Whether `type`'s mobile push should be sent for a user with these preferences (absent/true = send, false = suppress).
28
+ // Accepts a plain string like renderPush so a loose/unknown type still resolves (unknown = enabled).
29
+ export function pushEnabledFor(prefs, type) {
30
+ return prefs?.[type] !== false;
31
+ }
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from '@jest/globals';
2
- import { NOTIFICATION_TYPES, NOTIFICATION_LOCALES } from './notification-type';
3
- import { NOTIFICATION_REGISTRY } from './registry';
2
+ import { NOTIFICATION_TYPES, NOTIFICATION_LOCALES, pushEnabledFor } from './notification-type';
3
+ import { NOTIFICATION_REGISTRY, PUSH_NOTIFICATION_TYPES } from './registry';
4
4
  import { NOTIFICATION_CATALOG } from './catalog';
5
5
  import { renderPush, notificationPath, interpolate, translateNotification } from './render';
6
6
  function readNested(node, dotKey) {
@@ -124,3 +124,21 @@ describe('translateNotification + interpolate + notificationPath', () => {
124
124
  expect(notificationPath('COMPENSATION', {})).toBe('/');
125
125
  });
126
126
  });
127
+ describe('push preferences (PUSH_NOTIFICATION_TYPES + pushEnabledFor)', () => {
128
+ it('is exactly the emitsPush types, COMPENSATION excluded', () => {
129
+ expect([...PUSH_NOTIFICATION_TYPES].sort((a, b) => a.localeCompare(b)))
130
+ .toEqual(NOTIFICATION_TYPES.filter((t) => NOTIFICATION_REGISTRY[t].emitsPush).sort((a, b) => a.localeCompare(b)));
131
+ expect(PUSH_NOTIFICATION_TYPES).not.toContain('COMPENSATION');
132
+ expect(PUSH_NOTIFICATION_TYPES).toContain('MATCH_RESULT');
133
+ expect(PUSH_NOTIFICATION_TYPES).toHaveLength(8);
134
+ });
135
+ it('is opt-out: absent / null / empty / true all enable, only explicit false suppresses', () => {
136
+ expect(pushEnabledFor(undefined, 'MATCH_RESULT')).toBe(true);
137
+ expect(pushEnabledFor(null, 'MATCH_RESULT')).toBe(true);
138
+ expect(pushEnabledFor({}, 'MATCH_RESULT')).toBe(true);
139
+ expect(pushEnabledFor({ MATCH_RESULT: true }, 'MATCH_RESULT')).toBe(true);
140
+ expect(pushEnabledFor({ MATCH_RESULT: false }, 'MATCH_RESULT')).toBe(false);
141
+ // disabling one type does not affect another
142
+ expect(pushEnabledFor({ MATCH_RESULT: false }, 'INJURY')).toBe(true);
143
+ });
144
+ });
@@ -11,3 +11,4 @@ export interface NotificationDescriptor {
11
11
  catalogKeys: string[];
12
12
  }
13
13
  export declare const NOTIFICATION_REGISTRY: Record<NotificationType, NotificationDescriptor>;
14
+ export declare const PUSH_NOTIFICATION_TYPES: NotificationType[];
@@ -1,3 +1,4 @@
1
+ import { NOTIFICATION_TYPES } from './notification-type';
1
2
  function readString(value) {
2
3
  return typeof value === 'string' && value !== '' ? value : null;
3
4
  }
@@ -107,3 +108,7 @@ export const NOTIFICATION_REGISTRY = {
107
108
  catalogKeys: []
108
109
  }
109
110
  };
111
+ // The notification types that emit a mobile push (everything except COMPENSATION). Source of truth = each
112
+ // descriptor's emitsPush, so this cannot drift. This is the user-toggleable set surfaced in the mobile app's
113
+ // notification settings and validated by the API before persisting a preference.
114
+ export const PUSH_NOTIFICATION_TYPES = NOTIFICATION_TYPES.filter((type) => NOTIFICATION_REGISTRY[type].emitsPush);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.487",
3
+ "version": "0.0.488",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",