volleyballsimtypes 0.0.459 → 0.0.463
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/cjs/src/api/index.d.ts +2 -0
- package/dist/cjs/src/data/init-models.js +13 -0
- package/dist/cjs/src/data/models/index.d.ts +2 -0
- package/dist/cjs/src/data/models/index.js +2 -0
- package/dist/cjs/src/data/models/match-preset.d.ts +28 -0
- package/dist/cjs/src/data/models/match-preset.js +65 -0
- package/dist/cjs/src/data/models/match.d.ts +2 -1
- package/dist/cjs/src/data/models/user-device-token.d.ts +23 -0
- package/dist/cjs/src/data/models/user-device-token.js +65 -0
- package/dist/cjs/src/data/transformers/division.js +1 -1
- package/dist/cjs/src/data/transformers/match-preset-override.test.d.ts +1 -0
- package/dist/cjs/src/data/transformers/match-preset-override.test.js +275 -0
- package/dist/cjs/src/data/transformers/match.d.ts +2 -1
- package/dist/cjs/src/data/transformers/match.js +15 -3
- package/dist/cjs/src/data/transformers/qualifier.js +1 -1
- package/dist/cjs/src/data/transformers/season.js +1 -1
- package/dist/cjs/src/data/transformers/tactics.d.ts +3 -2
- package/dist/cjs/src/data/transformers/tactics.js +36 -0
- package/dist/cjs/src/data/transformers/tactics.test.js +61 -0
- package/dist/cjs/src/data/transformers/team.d.ts +7 -1
- package/dist/cjs/src/data/transformers/team.js +22 -4
- package/dist/cjs/src/data/transformers/tournament.js +1 -1
- package/dist/cjs/src/service/team/schemas/tactics.z.test.js +115 -0
- package/dist/esm/src/api/index.d.ts +2 -0
- package/dist/esm/src/data/init-models.js +14 -1
- package/dist/esm/src/data/models/index.d.ts +2 -0
- package/dist/esm/src/data/models/index.js +2 -0
- package/dist/esm/src/data/models/match-preset.d.ts +28 -0
- package/dist/esm/src/data/models/match-preset.js +61 -0
- package/dist/esm/src/data/models/match.d.ts +2 -1
- package/dist/esm/src/data/models/user-device-token.d.ts +23 -0
- package/dist/esm/src/data/models/user-device-token.js +61 -0
- package/dist/esm/src/data/transformers/division.js +1 -1
- package/dist/esm/src/data/transformers/match-preset-override.test.d.ts +1 -0
- package/dist/esm/src/data/transformers/match-preset-override.test.js +273 -0
- package/dist/esm/src/data/transformers/match.d.ts +2 -1
- package/dist/esm/src/data/transformers/match.js +15 -3
- package/dist/esm/src/data/transformers/qualifier.js +1 -1
- package/dist/esm/src/data/transformers/season.js +1 -1
- package/dist/esm/src/data/transformers/tactics.d.ts +3 -2
- package/dist/esm/src/data/transformers/tactics.js +36 -1
- package/dist/esm/src/data/transformers/tactics.test.js +63 -2
- package/dist/esm/src/data/transformers/team.d.ts +7 -1
- package/dist/esm/src/data/transformers/team.js +20 -5
- package/dist/esm/src/data/transformers/tournament.js +1 -1
- package/dist/esm/src/service/team/schemas/tactics.z.test.js +115 -0
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { TacticsAttributes, TacticsModel } from '../models';
|
|
|
2
2
|
import { Player, Tactics } from '../../service';
|
|
3
3
|
import type { Tactics as ApiTactics } from '../../api';
|
|
4
4
|
declare function transformToAttributes(tactics: Tactics, teamId: string): TacticsAttributes;
|
|
5
|
-
declare function transformToObject(model:
|
|
5
|
+
declare function transformToObject(model: TacticsAttributes, roster: Player[]): Tactics;
|
|
6
6
|
declare function tacticsColumnsToApiDto(model: TacticsModel): ApiTactics;
|
|
7
|
-
|
|
7
|
+
declare function apiTacticsConfigToAttributes(config: ApiTactics, teamId: string): TacticsAttributes;
|
|
8
|
+
export { transformToObject as transformToTactics, transformToAttributes as transformFromTactics, tacticsColumnsToApiDto, apiTacticsConfigToAttributes as apiTacticsConfigToTacticsAttributes };
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.transformToTactics = transformToObject;
|
|
4
4
|
exports.transformFromTactics = transformToAttributes;
|
|
5
5
|
exports.tacticsColumnsToApiDto = tacticsColumnsToApiDto;
|
|
6
|
+
exports.apiTacticsConfigToTacticsAttributes = apiTacticsConfigToAttributes;
|
|
6
7
|
const service_1 = require("../../service");
|
|
7
8
|
// Back-compat: new rows persist `mode`; rows written before the mode change persist `isPinchServer` (+ a
|
|
8
9
|
// 'NEVER' fatigueBand for the old "never fatigue-sub" state). Derive the mode so existing data keeps working
|
|
@@ -89,6 +90,8 @@ function transformToAttributes(tactics, teamId) {
|
|
|
89
90
|
})))
|
|
90
91
|
};
|
|
91
92
|
}
|
|
93
|
+
// Accepts TacticsAttributes (not just TacticsModel) so a per-match preset's config, shaped as column data by
|
|
94
|
+
// apiTacticsConfigToTacticsAttributes below, can be hydrated through the exact same validation/healing path.
|
|
92
95
|
function transformToObject(model, roster) {
|
|
93
96
|
const lineup = transformToLineup(model.lineup, roster);
|
|
94
97
|
// A second libero is only valid as a RESERVE: it needs a starting libero (LIBERO_ZONE), the L2 player must be
|
|
@@ -224,3 +227,36 @@ function tacticsColumnsToApiDto(model) {
|
|
|
224
227
|
offensivePreferenceSets: model.offensive_preference_sets
|
|
225
228
|
};
|
|
226
229
|
}
|
|
230
|
+
// Inverse of tacticsColumnsToApiDto: shape a preset's stored API config (camelCase, player ids) as
|
|
231
|
+
// TacticsAttributes-shaped column data so transformToTactics can hydrate it against a roster through the
|
|
232
|
+
// exact same validation/healing path as the Tactics row. Only the top-level keys need renaming -- the jsonb
|
|
233
|
+
// sub-objects (designated subs, libero sub, preferences, system sets) are stored camelCase in both shapes.
|
|
234
|
+
// Deliberately NOT mirroring writeTacticsRow's null-clears-column rule: nothing is being UPDATEd here, so
|
|
235
|
+
// absent optionals simply stay undefined.
|
|
236
|
+
function apiTacticsConfigToAttributes(config, teamId) {
|
|
237
|
+
return {
|
|
238
|
+
team_id: teamId,
|
|
239
|
+
lineup: {
|
|
240
|
+
[service_1.CourtPosition.LIBERO_ZONE]: config.lineup[service_1.CourtPosition.LIBERO_ZONE],
|
|
241
|
+
[service_1.CourtPosition.LEFT_BACK]: config.lineup[service_1.CourtPosition.LEFT_BACK],
|
|
242
|
+
[service_1.CourtPosition.LEFT_FRONT]: config.lineup[service_1.CourtPosition.LEFT_FRONT],
|
|
243
|
+
[service_1.CourtPosition.MIDDLE_BACK]: config.lineup[service_1.CourtPosition.MIDDLE_BACK],
|
|
244
|
+
[service_1.CourtPosition.MIDDLE_FRONT]: config.lineup[service_1.CourtPosition.MIDDLE_FRONT],
|
|
245
|
+
[service_1.CourtPosition.RIGHT_BACK]: config.lineup[service_1.CourtPosition.RIGHT_BACK],
|
|
246
|
+
[service_1.CourtPosition.RIGHT_FRONT]: config.lineup[service_1.CourtPosition.RIGHT_FRONT],
|
|
247
|
+
bench: config.lineup.bench
|
|
248
|
+
},
|
|
249
|
+
libero_replacements: config.liberoReplacements,
|
|
250
|
+
receive_rotation_offset: config.receiveRotationOffset,
|
|
251
|
+
designated_subs: config.designatedSubs,
|
|
252
|
+
substitution_band: config.substitutionBand,
|
|
253
|
+
second_libero: config.secondLibero,
|
|
254
|
+
libero_sub: config.liberoSub,
|
|
255
|
+
libero_replacement_sets: config.liberoReplacementSets,
|
|
256
|
+
rotation_system: config.rotationSystem,
|
|
257
|
+
designated_setters: config.designatedSetters,
|
|
258
|
+
offensive_preferences: config.offensivePreferences,
|
|
259
|
+
system_sets: config.systemSets,
|
|
260
|
+
offensive_preference_sets: config.offensivePreferenceSets
|
|
261
|
+
};
|
|
262
|
+
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const globals_1 = require("@jest/globals");
|
|
4
4
|
const tactics_1 = require("./tactics");
|
|
5
5
|
const service_1 = require("../../service");
|
|
6
|
+
const test_helpers_1 = require("../../service/test-helpers");
|
|
6
7
|
// Minimal TacticsModel-shaped object; cast through unknown since the transformer only reads columns.
|
|
7
8
|
function makeTactics(designatedSubs) {
|
|
8
9
|
return {
|
|
@@ -77,4 +78,64 @@ function makeTactics(designatedSubs) {
|
|
|
77
78
|
(0, globals_1.expect)(dto.secondLibero).toBe('reserve1');
|
|
78
79
|
(0, globals_1.expect)(dto.liberoSub).toEqual({ mode: 'FATIGUE' });
|
|
79
80
|
});
|
|
81
|
+
(0, globals_1.it)('passes per-set tactics columns through to the API DTO shape', () => {
|
|
82
|
+
const model = makeTactics([]);
|
|
83
|
+
model.system_sets = [{ rotationSystem: service_1.RotationSystemEnum.FIVE_ONE, designatedSetters: ['lf'] }];
|
|
84
|
+
model.offensive_preference_sets = [[{ rotation: 1, order: ['rf', 'mf'] }]];
|
|
85
|
+
const dto = (0, tactics_1.tacticsColumnsToApiDto)(model);
|
|
86
|
+
(0, globals_1.expect)(dto.systemSets).toEqual([{ rotationSystem: '5-1', designatedSetters: ['lf'] }]);
|
|
87
|
+
(0, globals_1.expect)(dto.offensivePreferenceSets).toEqual([[{ rotation: 1, order: ['rf', 'mf'] }]]);
|
|
88
|
+
});
|
|
89
|
+
(0, globals_1.it)('leaves the per-set DTO fields undefined when the columns are absent', () => {
|
|
90
|
+
const dto = (0, tactics_1.tacticsColumnsToApiDto)(makeTactics([]));
|
|
91
|
+
(0, globals_1.expect)(dto.systemSets).toBeUndefined();
|
|
92
|
+
(0, globals_1.expect)(dto.offensivePreferenceSets).toBeUndefined();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
(0, globals_1.describe)('per-set tactics — service <-> row round-trip', () => {
|
|
96
|
+
const country = (0, test_helpers_1.makeCountry)();
|
|
97
|
+
const p1 = (0, test_helpers_1.makePlayer)(country);
|
|
98
|
+
const p2 = (0, test_helpers_1.makePlayer)(country);
|
|
99
|
+
const p3 = (0, test_helpers_1.makePlayer)(country);
|
|
100
|
+
const p4 = (0, test_helpers_1.makePlayer)(country);
|
|
101
|
+
const p5 = (0, test_helpers_1.makePlayer)(country);
|
|
102
|
+
const p6 = (0, test_helpers_1.makePlayer)(country);
|
|
103
|
+
const roster = [p1, p2, p3, p4, p5, p6];
|
|
104
|
+
const tactics = service_1.Tactics.create({
|
|
105
|
+
lineup: { 4: p4, 3: p3, 2: p2, 5: p5, 6: p6, 1: p1, bench: [] },
|
|
106
|
+
liberoReplacements: [],
|
|
107
|
+
systemSets: [
|
|
108
|
+
{ rotationSystem: service_1.RotationSystemEnum.FIVE_ONE, designatedSetters: [p1] },
|
|
109
|
+
{ rotationSystem: service_1.RotationSystemEnum.SIX_ZERO, designatedSetters: [] }
|
|
110
|
+
],
|
|
111
|
+
offensivePreferenceSets: [[{ rotation: 1, order: [p2, p3] }]]
|
|
112
|
+
});
|
|
113
|
+
(0, globals_1.it)('transformFromTactics writes the per-set overrides as id-based jsonb columns', () => {
|
|
114
|
+
const attrs = (0, tactics_1.transformFromTactics)(tactics, 'team-1');
|
|
115
|
+
(0, globals_1.expect)(attrs.system_sets).toEqual([
|
|
116
|
+
{ rotationSystem: '5-1', designatedSetters: [p1.id] },
|
|
117
|
+
{ rotationSystem: '6-0', designatedSetters: [] }
|
|
118
|
+
]);
|
|
119
|
+
(0, globals_1.expect)(attrs.offensive_preference_sets).toEqual([[{ rotation: 1, order: [p2.id, p3.id] }]]);
|
|
120
|
+
});
|
|
121
|
+
(0, globals_1.it)('transformToTactics resolves the stored ids back to roster players', () => {
|
|
122
|
+
const attrs = (0, tactics_1.transformFromTactics)(tactics, 'team-1');
|
|
123
|
+
const back = (0, tactics_1.transformToTactics)(attrs, roster);
|
|
124
|
+
(0, globals_1.expect)(back.systemSets?.[0].rotationSystem).toBe(service_1.RotationSystemEnum.FIVE_ONE);
|
|
125
|
+
(0, globals_1.expect)(back.systemSets?.[0].designatedSetters[0].id).toBe(p1.id);
|
|
126
|
+
(0, globals_1.expect)(back.systemSets?.[1].designatedSetters).toEqual([]);
|
|
127
|
+
(0, globals_1.expect)(back.offensivePreferenceSets?.[0][0].order.map(p => p.id)).toEqual([p2.id, p3.id]);
|
|
128
|
+
});
|
|
129
|
+
(0, globals_1.it)('omits the per-set columns entirely for an all-sets config', () => {
|
|
130
|
+
const flat = service_1.Tactics.create({
|
|
131
|
+
lineup: { 4: p4, 3: p3, 2: p2, 5: p5, 6: p6, 1: p1, bench: [] },
|
|
132
|
+
liberoReplacements: []
|
|
133
|
+
});
|
|
134
|
+
const attrs = (0, tactics_1.transformFromTactics)(flat, 'team-1');
|
|
135
|
+
(0, globals_1.expect)(attrs.system_sets).toBeUndefined();
|
|
136
|
+
(0, globals_1.expect)(attrs.offensive_preference_sets).toBeUndefined();
|
|
137
|
+
const back = (0, tactics_1.transformToTactics)(attrs, roster);
|
|
138
|
+
(0, globals_1.expect)(back.systemSets).toBeUndefined();
|
|
139
|
+
(0, globals_1.expect)(back.offensivePreferenceSets).toBeUndefined();
|
|
140
|
+
});
|
|
80
141
|
});
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Team } from '../../service';
|
|
2
2
|
import { TeamAttributes, TeamModel } from '../models';
|
|
3
|
+
import type { Tactics as ApiTactics } from '../../api';
|
|
4
|
+
export interface MatchTacticsOverride {
|
|
5
|
+
presetId: string;
|
|
6
|
+
config: ApiTactics;
|
|
7
|
+
onFallback?: (presetId: string, err: unknown) => void;
|
|
8
|
+
}
|
|
3
9
|
declare function transformToAttributes(team: Team): TeamAttributes;
|
|
4
|
-
declare function transformToObject(model: TeamModel, currentIteration?: number): Team;
|
|
10
|
+
declare function transformToObject(model: TeamModel, currentIteration?: number, tacticsOverride?: MatchTacticsOverride): Team;
|
|
5
11
|
export { transformToObject as transformToTeam, transformToAttributes as transformFromTeam };
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.transformToTeam = transformToObject;
|
|
4
7
|
exports.transformFromTeam = transformToAttributes;
|
|
5
8
|
const service_1 = require("../../service");
|
|
6
9
|
const _1 = require(".");
|
|
10
|
+
const logger_1 = __importDefault(require("../../logger"));
|
|
7
11
|
function transformToAttributes(team) {
|
|
8
12
|
return {
|
|
9
13
|
team_id: team.id,
|
|
@@ -16,11 +20,25 @@ function transformToAttributes(team) {
|
|
|
16
20
|
division_id: team.divisionId
|
|
17
21
|
};
|
|
18
22
|
}
|
|
19
|
-
function transformToObject(model, currentIteration) {
|
|
23
|
+
function transformToObject(model, currentIteration, tacticsOverride) {
|
|
20
24
|
const roster = (model.PlayerTeams ?? []).map((pt) => (0, _1.transformToPlayer)(pt.player, currentIteration));
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
let tactics;
|
|
26
|
+
if (tacticsOverride != null && roster.length > 0) {
|
|
27
|
+
try {
|
|
28
|
+
tactics = (0, _1.transformToTactics)((0, _1.apiTacticsConfigToTacticsAttributes)(tacticsOverride.config, model.team_id), roster);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
if (tacticsOverride.onFallback != null)
|
|
32
|
+
tacticsOverride.onFallback(tacticsOverride.presetId, err);
|
|
33
|
+
else
|
|
34
|
+
logger_1.default.warn(`MATCH_PRESET_FALLBACK: team=${model.team_id} preset=${tacticsOverride.presetId} failed to hydrate; using active tactics`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (tactics == null) {
|
|
38
|
+
tactics = model.tactics != null && roster.length > 0
|
|
39
|
+
? (0, _1.transformToTactics)(model.tactics, roster)
|
|
40
|
+
: undefined;
|
|
41
|
+
}
|
|
24
42
|
return service_1.Team.create({
|
|
25
43
|
id: model.team_id,
|
|
26
44
|
name: model.name,
|
|
@@ -45,7 +45,7 @@ function transformToObject(model) {
|
|
|
45
45
|
id: model.competition_id,
|
|
46
46
|
iteration: (0, _1.transformToIteration)(model.Iteration),
|
|
47
47
|
matches: (model.CompetitionMatches ?? []).map(_1.transformToTournamentMatch),
|
|
48
|
-
teams: (0, _1.sortTeamsByCompetitionIndex)(model.Teams ?? []).map(_1.transformToTeam),
|
|
48
|
+
teams: (0, _1.sortTeamsByCompetitionIndex)(model.Teams ?? []).map(team => (0, _1.transformToTeam)(team)),
|
|
49
49
|
status: model.status,
|
|
50
50
|
champion
|
|
51
51
|
});
|
|
@@ -69,3 +69,118 @@ const test_helpers_1 = require("../../test-helpers");
|
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
|
+
(0, globals_1.describe)('TacticsInputSchema — per-set tactics (systemSets / offensivePreferenceSets)', () => {
|
|
73
|
+
const country = (0, test_helpers_1.makeCountry)();
|
|
74
|
+
const p1 = (0, test_helpers_1.makePlayer)(country);
|
|
75
|
+
const p2 = (0, test_helpers_1.makePlayer)(country);
|
|
76
|
+
const p3 = (0, test_helpers_1.makePlayer)(country);
|
|
77
|
+
const p4 = (0, test_helpers_1.makePlayer)(country);
|
|
78
|
+
const p5 = (0, test_helpers_1.makePlayer)(country);
|
|
79
|
+
const p6 = (0, test_helpers_1.makePlayer)(country);
|
|
80
|
+
const reserve = (0, test_helpers_1.makePlayer)(country);
|
|
81
|
+
// Minimal valid flat input (6-0 default: no setters, no preferences). Zone layout: p1@1, p2@2, p3@3,
|
|
82
|
+
// p4@4, p5@5, p6@6 — opposite slot pairs (3 apart) are (1,4), (2,5), (3,6).
|
|
83
|
+
function baseInput(overrides = {}) {
|
|
84
|
+
return {
|
|
85
|
+
lineup: { 4: p4, 3: p3, 2: p2, 5: p5, 6: p6, 1: p1, bench: [] },
|
|
86
|
+
liberoReplacements: [],
|
|
87
|
+
...overrides
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
(0, globals_1.it)('accepts valid per-set overrides for both scopes', () => {
|
|
91
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
92
|
+
systemSets: [
|
|
93
|
+
{ rotationSystem: '5-1', designatedSetters: [p1] },
|
|
94
|
+
{ rotationSystem: '6-0', designatedSetters: [] },
|
|
95
|
+
{ rotationSystem: '4-2', designatedSetters: [p1, p4] }
|
|
96
|
+
],
|
|
97
|
+
offensivePreferenceSets: [
|
|
98
|
+
[{ rotation: 1, order: [p2, p3] }],
|
|
99
|
+
[]
|
|
100
|
+
]
|
|
101
|
+
}));
|
|
102
|
+
(0, globals_1.expect)(res.success).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
(0, globals_1.it)('carries the per-set fields through Tactics.create parsing', () => {
|
|
105
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
106
|
+
systemSets: [{ rotationSystem: '5-1', designatedSetters: [p1] }],
|
|
107
|
+
offensivePreferenceSets: [[{ rotation: 2, order: [p3] }]]
|
|
108
|
+
}));
|
|
109
|
+
(0, globals_1.expect)(res.success).toBe(true);
|
|
110
|
+
if (res.success) {
|
|
111
|
+
(0, globals_1.expect)(res.data.systemSets?.[0].rotationSystem).toBe('5-1');
|
|
112
|
+
(0, globals_1.expect)(res.data.systemSets?.[0].designatedSetters[0].id).toBe(p1.id);
|
|
113
|
+
(0, globals_1.expect)(res.data.offensivePreferenceSets?.[0][0]).toMatchObject({ rotation: 2 });
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
(0, globals_1.it)('rejects more than 5 per-set entries', () => {
|
|
117
|
+
const entry = { rotationSystem: '6-0', designatedSetters: [] };
|
|
118
|
+
(0, globals_1.expect)(tactics_z_1.TacticsInputSchema.safeParse(baseInput({ systemSets: Array.from({ length: 6 }, () => entry) })).success).toBe(false);
|
|
119
|
+
(0, globals_1.expect)(tactics_z_1.TacticsInputSchema.safeParse(baseInput({ offensivePreferenceSets: Array.from({ length: 6 }, () => []) })).success).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
(0, globals_1.it)('rejects a set entry whose setter count does not match its system (5-1 with none)', () => {
|
|
122
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
123
|
+
systemSets: [{ rotationSystem: '5-1', designatedSetters: [] }]
|
|
124
|
+
}));
|
|
125
|
+
(0, globals_1.expect)(res.success).toBe(false);
|
|
126
|
+
if (!res.success) {
|
|
127
|
+
const issue = res.error.issues.find(i => i.message === 'DESIGNATED_SETTERS_COUNT_5-1_EXPECTED_1');
|
|
128
|
+
(0, globals_1.expect)(issue?.path).toEqual(['systemSets', 0]);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
(0, globals_1.it)('rejects a set entry whose setter is not a court starter', () => {
|
|
132
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
133
|
+
systemSets: [
|
|
134
|
+
{ rotationSystem: '6-0', designatedSetters: [] },
|
|
135
|
+
{ rotationSystem: '5-1', designatedSetters: [reserve] }
|
|
136
|
+
]
|
|
137
|
+
}));
|
|
138
|
+
(0, globals_1.expect)(res.success).toBe(false);
|
|
139
|
+
if (!res.success) {
|
|
140
|
+
const issue = res.error.issues.find(i => i.message === 'DESIGNATED_SETTER_NOT_A_STARTER');
|
|
141
|
+
(0, globals_1.expect)(issue?.path).toEqual(['systemSets', 1]);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
(0, globals_1.it)('rejects a 4-2 set entry whose setters are not in opposite slots', () => {
|
|
145
|
+
// p1@1 and p2@2 are adjacent (not 3 apart), so the 4-2 pair rule fails for that set entry.
|
|
146
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
147
|
+
systemSets: [{ rotationSystem: '4-2', designatedSetters: [p1, p2] }]
|
|
148
|
+
}));
|
|
149
|
+
(0, globals_1.expect)(res.success).toBe(false);
|
|
150
|
+
if (!res.success) {
|
|
151
|
+
(0, globals_1.expect)(res.error.issues.some(i => i.message === 'DESIGNATED_SETTERS_NOT_IN_OPPOSITE_SLOTS')).toBe(true);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
(0, globals_1.it)('rejects a per-set preferences list with a duplicate rotation', () => {
|
|
155
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
156
|
+
offensivePreferenceSets: [[{ rotation: 1, order: [p2] }, { rotation: 1, order: [p3] }]]
|
|
157
|
+
}));
|
|
158
|
+
(0, globals_1.expect)(res.success).toBe(false);
|
|
159
|
+
if (!res.success) {
|
|
160
|
+
const issue = res.error.issues.find(i => i.message === 'OFFENSIVE_PREFERENCE_DUPLICATE_ROTATION');
|
|
161
|
+
(0, globals_1.expect)(issue?.path).toEqual(['offensivePreferenceSets', 0]);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
(0, globals_1.it)('rejects a per-set preferences order that lists a non-starter', () => {
|
|
165
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
166
|
+
offensivePreferenceSets: [[{ rotation: 1, order: [reserve] }]]
|
|
167
|
+
}));
|
|
168
|
+
(0, globals_1.expect)(res.success).toBe(false);
|
|
169
|
+
if (!res.success) {
|
|
170
|
+
(0, globals_1.expect)(res.error.issues.some(i => i.message === 'OFFENSIVE_PREFERENCE_ATTACKER_NOT_A_STARTER')).toBe(true);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
(0, globals_1.it)('still validates the flat fields when per-set overrides are present', () => {
|
|
174
|
+
// Flat 5-1 with no setter is invalid even though every set entry is valid.
|
|
175
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
176
|
+
rotationSystem: '5-1',
|
|
177
|
+
designatedSetters: [],
|
|
178
|
+
systemSets: [{ rotationSystem: '6-0', designatedSetters: [] }]
|
|
179
|
+
}));
|
|
180
|
+
(0, globals_1.expect)(res.success).toBe(false);
|
|
181
|
+
if (!res.success) {
|
|
182
|
+
const issue = res.error.issues.find(i => i.message === 'DESIGNATED_SETTERS_COUNT_5-1_EXPECTED_1');
|
|
183
|
+
(0, globals_1.expect)(issue?.path).toEqual(['designatedSetters']);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -49,6 +49,7 @@ export type Match = Omit<DataProps<_Match>, 'sets' | 'homeTeam' | 'awayTeam' | '
|
|
|
49
49
|
awayForm?: MatchForm[];
|
|
50
50
|
isFriendly?: boolean;
|
|
51
51
|
detailUnavailable?: boolean;
|
|
52
|
+
selectedPresetId?: string;
|
|
52
53
|
};
|
|
53
54
|
export type RallyEvent = DataProps<_RallyEvent> & {
|
|
54
55
|
teamId?: string;
|
|
@@ -128,6 +129,7 @@ export interface ApiLineupPreset {
|
|
|
128
129
|
orderIndex: number;
|
|
129
130
|
config: Tactics;
|
|
130
131
|
}
|
|
132
|
+
export type ApiLineupPresetSummary = Omit<ApiLineupPreset, 'config'>;
|
|
131
133
|
export type Team = Omit<DataProps<_Team>, 'roster' | '_rating' | 'rating' | 'tactics'> & {
|
|
132
134
|
roster: Player[];
|
|
133
135
|
rating: {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { AuthIdentityModel, AuthSessionModel, AuthUserModel, BoxScoreModel, CoachModel, ScoutModel, BoxScoreTotalsModel, CompetitionChampionModel, CurrencyTransactionModel, GachaPityModel, GachaPullHistoryModel, WishlistModel, UserSettingsModel, 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, LineupPresetModel, TeamModel, TeamReplacementModel, UserCurrencyModel, UserPlayerProgressModel, UserPullGrantModel, UserTeamModel, VPERModel, NotificationModel, AppConfigModel, LegacyTeamFlagModel } from './models';
|
|
1
|
+
import { AuthIdentityModel, AuthSessionModel, AuthUserModel, BoxScoreModel, CoachModel, ScoutModel, BoxScoreTotalsModel, CompetitionChampionModel, CurrencyTransactionModel, GachaPityModel, GachaPullHistoryModel, WishlistModel, UserSettingsModel, UserDeviceTokenModel, 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, LineupPresetModel, MatchPresetModel, TeamModel, TeamReplacementModel, UserCurrencyModel, UserPlayerProgressModel, UserPullGrantModel, 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);
|
|
5
5
|
const CurrencyTransaction = CurrencyTransactionModel.initModel(sequelize);
|
|
6
6
|
const Tactics = TacticsModel.initModel(sequelize);
|
|
7
7
|
const LineupPreset = LineupPresetModel.initModel(sequelize);
|
|
8
|
+
const MatchPreset = MatchPresetModel.initModel(sequelize);
|
|
8
9
|
const AuthUser = AuthUserModel.initModel(sequelize);
|
|
9
10
|
const UserCurrency = UserCurrencyModel.initModel(sequelize);
|
|
10
11
|
const UserPlayerProgress = UserPlayerProgressModel.initModel(sequelize);
|
|
@@ -13,6 +14,7 @@ export function initModels(sequelize) {
|
|
|
13
14
|
const UserPullGrant = UserPullGrantModel.initModel(sequelize);
|
|
14
15
|
const Wishlist = WishlistModel.initModel(sequelize);
|
|
15
16
|
const UserSettings = UserSettingsModel.initModel(sequelize);
|
|
17
|
+
const UserDeviceToken = UserDeviceTokenModel.initModel(sequelize);
|
|
16
18
|
const Notification = NotificationModel.initModel(sequelize);
|
|
17
19
|
const AuthIdentity = AuthIdentityModel.initModel(sequelize);
|
|
18
20
|
const AuthSession = AuthSessionModel.initModel(sequelize);
|
|
@@ -60,7 +62,9 @@ export function initModels(sequelize) {
|
|
|
60
62
|
AuthUser.hasOne(GachaPity, { as: 'GachaPity', foreignKey: 'user_id' });
|
|
61
63
|
AuthUser.hasOne(Wishlist, { as: 'Wishlist', foreignKey: 'user_id' });
|
|
62
64
|
AuthUser.hasOne(UserSettings, { as: 'UserSettings', foreignKey: 'user_id' });
|
|
65
|
+
AuthUser.hasMany(UserDeviceToken, { as: 'UserDeviceTokens', foreignKey: 'user_id' });
|
|
63
66
|
AuthUser.hasMany(Notification, { as: 'Notifications', foreignKey: 'user_id' });
|
|
67
|
+
UserDeviceToken.belongsTo(AuthUser, { as: 'user', foreignKey: 'user_id' });
|
|
64
68
|
Notification.belongsTo(AuthUser, { as: 'user', foreignKey: 'user_id' });
|
|
65
69
|
AuthUser.hasMany(GachaPullHistory, { as: 'GachaPullHistory', foreignKey: 'user_id' });
|
|
66
70
|
AuthUser.hasMany(UserPullGrant, { as: 'UserPullGrants', foreignKey: 'user_id' });
|
|
@@ -209,6 +213,13 @@ export function initModels(sequelize) {
|
|
|
209
213
|
// simulator's team loads are unchanged (it reads the active config from the mirrored Tactics row).
|
|
210
214
|
Team.hasMany(LineupPreset, { as: 'lineupPresets', foreignKey: 'team_id' });
|
|
211
215
|
LineupPreset.belongsTo(Team, { as: 'team', foreignKey: 'team_id' });
|
|
216
|
+
// Per-match preset choices. Deliberately NOT part of any default scope: only the simulator's match query
|
|
217
|
+
// loads MatchPresets, so every other transformToMatch caller stays on the active-tactics path.
|
|
218
|
+
Match.hasMany(MatchPreset, { as: 'MatchPresets', foreignKey: 'match_id' });
|
|
219
|
+
MatchPreset.belongsTo(Match, { as: 'match', foreignKey: 'match_id' });
|
|
220
|
+
MatchPreset.belongsTo(Team, { as: 'team', foreignKey: 'team_id' });
|
|
221
|
+
MatchPreset.belongsTo(LineupPreset, { as: 'preset', foreignKey: 'preset_id' });
|
|
222
|
+
LineupPreset.hasMany(MatchPreset, { as: 'MatchPresets', foreignKey: 'preset_id' });
|
|
212
223
|
Team.belongsTo(Country, { as: 'country', foreignKey: 'country_id' });
|
|
213
224
|
Team.belongsToMany(Competition, {
|
|
214
225
|
as: 'Competitions',
|
|
@@ -283,6 +294,7 @@ export function initModels(sequelize) {
|
|
|
283
294
|
TeamReplacement,
|
|
284
295
|
Tactics,
|
|
285
296
|
LineupPreset,
|
|
297
|
+
MatchPreset,
|
|
286
298
|
UserTeam,
|
|
287
299
|
UserCurrency,
|
|
288
300
|
UserPlayerProgress,
|
|
@@ -291,6 +303,7 @@ export function initModels(sequelize) {
|
|
|
291
303
|
UserPullGrant,
|
|
292
304
|
Wishlist,
|
|
293
305
|
UserSettings,
|
|
306
|
+
UserDeviceToken,
|
|
294
307
|
Notification,
|
|
295
308
|
Coach,
|
|
296
309
|
Scout,
|
|
@@ -36,6 +36,7 @@ export * from './team';
|
|
|
36
36
|
export * from './team-replacement';
|
|
37
37
|
export * from './tactics';
|
|
38
38
|
export * from './lineup-preset';
|
|
39
|
+
export * from './match-preset';
|
|
39
40
|
export * from './user-currency';
|
|
40
41
|
export * from './user-player-progress';
|
|
41
42
|
export * from './gacha-pity';
|
|
@@ -44,6 +45,7 @@ export * from './wishlist';
|
|
|
44
45
|
export * from './currency-transaction';
|
|
45
46
|
export * from './user-pull-grant';
|
|
46
47
|
export * from './user-settings';
|
|
48
|
+
export * from './user-device-token';
|
|
47
49
|
export * from './notification';
|
|
48
50
|
export * from './vper';
|
|
49
51
|
export * from './views';
|
|
@@ -36,6 +36,7 @@ export * from './team';
|
|
|
36
36
|
export * from './team-replacement';
|
|
37
37
|
export * from './tactics';
|
|
38
38
|
export * from './lineup-preset';
|
|
39
|
+
export * from './match-preset';
|
|
39
40
|
export * from './user-currency';
|
|
40
41
|
export * from './user-player-progress';
|
|
41
42
|
export * from './gacha-pity';
|
|
@@ -44,6 +45,7 @@ export * from './wishlist';
|
|
|
44
45
|
export * from './currency-transaction';
|
|
45
46
|
export * from './user-pull-grant';
|
|
46
47
|
export * from './user-settings';
|
|
48
|
+
export * from './user-device-token';
|
|
47
49
|
export * from './notification';
|
|
48
50
|
export * from './vper';
|
|
49
51
|
export * from './views';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as Sequelize from 'sequelize';
|
|
2
|
+
import { Model } from 'sequelize';
|
|
3
|
+
import { LineupPresetId, LineupPresetModel, MatchId, MatchModel, TeamId, TeamModel } from '.';
|
|
4
|
+
export interface MatchPresetAttributes {
|
|
5
|
+
match_id: string;
|
|
6
|
+
team_id: string;
|
|
7
|
+
preset_id: string;
|
|
8
|
+
}
|
|
9
|
+
export type MatchPresetPk = 'match_id' | 'team_id';
|
|
10
|
+
export type MatchPresetCreationAttributes = MatchPresetAttributes;
|
|
11
|
+
export declare class MatchPresetModel extends Model<MatchPresetAttributes, MatchPresetCreationAttributes> implements MatchPresetAttributes {
|
|
12
|
+
match_id: string;
|
|
13
|
+
team_id: string;
|
|
14
|
+
preset_id: string;
|
|
15
|
+
match: MatchModel;
|
|
16
|
+
getMatch: Sequelize.BelongsToGetAssociationMixin<MatchModel>;
|
|
17
|
+
setMatch: Sequelize.BelongsToSetAssociationMixin<MatchModel, MatchId>;
|
|
18
|
+
createMatch: Sequelize.BelongsToCreateAssociationMixin<MatchModel>;
|
|
19
|
+
team: TeamModel;
|
|
20
|
+
getTeam: Sequelize.BelongsToGetAssociationMixin<TeamModel>;
|
|
21
|
+
setTeam: Sequelize.BelongsToSetAssociationMixin<TeamModel, TeamId>;
|
|
22
|
+
createTeam: Sequelize.BelongsToCreateAssociationMixin<TeamModel>;
|
|
23
|
+
preset: LineupPresetModel;
|
|
24
|
+
getPreset: Sequelize.BelongsToGetAssociationMixin<LineupPresetModel>;
|
|
25
|
+
setPreset: Sequelize.BelongsToSetAssociationMixin<LineupPresetModel, LineupPresetId>;
|
|
26
|
+
createPreset: Sequelize.BelongsToCreateAssociationMixin<LineupPresetModel>;
|
|
27
|
+
static initModel(sequelize: Sequelize.Sequelize): typeof MatchPresetModel;
|
|
28
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DataTypes, Model } from 'sequelize';
|
|
2
|
+
export class MatchPresetModel extends Model {
|
|
3
|
+
static initModel(sequelize) {
|
|
4
|
+
return MatchPresetModel.init({
|
|
5
|
+
match_id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
allowNull: false,
|
|
8
|
+
primaryKey: true,
|
|
9
|
+
references: {
|
|
10
|
+
model: 'Match',
|
|
11
|
+
key: 'match_id'
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
team_id: {
|
|
15
|
+
type: DataTypes.UUID,
|
|
16
|
+
allowNull: false,
|
|
17
|
+
primaryKey: true,
|
|
18
|
+
references: {
|
|
19
|
+
model: 'Team',
|
|
20
|
+
key: 'team_id'
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
preset_id: {
|
|
24
|
+
type: DataTypes.UUID,
|
|
25
|
+
allowNull: false,
|
|
26
|
+
references: {
|
|
27
|
+
model: 'LineupPreset',
|
|
28
|
+
key: 'preset_id'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}, {
|
|
32
|
+
sequelize,
|
|
33
|
+
tableName: 'MatchPreset',
|
|
34
|
+
schema: 'public',
|
|
35
|
+
timestamps: false,
|
|
36
|
+
indexes: [
|
|
37
|
+
{
|
|
38
|
+
name: 'MatchPreset_pk',
|
|
39
|
+
unique: true,
|
|
40
|
+
fields: [
|
|
41
|
+
{ name: 'match_id' },
|
|
42
|
+
{ name: 'team_id' }
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'MatchPreset_team_id_idx',
|
|
47
|
+
fields: [
|
|
48
|
+
{ name: 'team_id' }
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
// Keeps the LineupPreset ON DELETE CASCADE cheap.
|
|
53
|
+
name: 'MatchPreset_preset_id_idx',
|
|
54
|
+
fields: [
|
|
55
|
+
{ name: 'preset_id' }
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Sequelize from 'sequelize';
|
|
2
2
|
import { Model } from 'sequelize';
|
|
3
3
|
import { Status } from '../common';
|
|
4
|
-
import { CompetitionMatchId, CompetitionMatchModel, MatchRatingId, MatchRatingModel, MatchResultId, MatchResultModel, MatchSetAttributes, MatchSetId, MatchSetModel, VPERAttributes, VPERId, VPERModel, TeamId, TeamModel } from '.';
|
|
4
|
+
import { CompetitionMatchId, CompetitionMatchModel, MatchRatingId, MatchRatingModel, MatchResultId, MatchResultModel, MatchPresetModel, MatchSetAttributes, MatchSetId, MatchSetModel, VPERAttributes, VPERId, VPERModel, TeamId, TeamModel } from '.';
|
|
5
5
|
import { MatchRallyAggregates } from '../../service';
|
|
6
6
|
export interface MatchAttributes {
|
|
7
7
|
match_id: string;
|
|
@@ -59,6 +59,7 @@ export declare class MatchModel extends Model<MatchAttributes, MatchCreationAttr
|
|
|
59
59
|
hasVPER: Sequelize.HasManyHasAssociationMixin<VPERModel, VPERId>;
|
|
60
60
|
hasVPERs: Sequelize.HasManyHasAssociationsMixin<VPERModel, VPERId>;
|
|
61
61
|
countVPERs: Sequelize.HasManyCountAssociationsMixin;
|
|
62
|
+
MatchPresets?: MatchPresetModel[];
|
|
62
63
|
MatchSets: MatchSetModel[];
|
|
63
64
|
getMatchSets: Sequelize.HasManyGetAssociationsMixin<MatchSetModel>;
|
|
64
65
|
setMatchSets: Sequelize.HasManySetAssociationsMixin<MatchSetModel, MatchSetId>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as Sequelize from 'sequelize';
|
|
2
|
+
import { Model, Optional } from 'sequelize';
|
|
3
|
+
export interface UserDeviceTokenAttributes {
|
|
4
|
+
user_device_token_id: string;
|
|
5
|
+
user_id: string;
|
|
6
|
+
device_token: string;
|
|
7
|
+
platform: string;
|
|
8
|
+
created_at?: Date;
|
|
9
|
+
updated_at?: Date;
|
|
10
|
+
}
|
|
11
|
+
export type UserDeviceTokenPk = 'user_device_token_id';
|
|
12
|
+
export type UserDeviceTokenId = UserDeviceTokenModel[UserDeviceTokenPk];
|
|
13
|
+
export type UserDeviceTokenOptionalAttributes = 'user_device_token_id' | 'platform' | 'created_at' | 'updated_at';
|
|
14
|
+
export type UserDeviceTokenCreationAttributes = Optional<UserDeviceTokenAttributes, UserDeviceTokenOptionalAttributes>;
|
|
15
|
+
export declare class UserDeviceTokenModel extends Model<UserDeviceTokenAttributes, UserDeviceTokenCreationAttributes> implements UserDeviceTokenAttributes {
|
|
16
|
+
user_device_token_id: string;
|
|
17
|
+
user_id: string;
|
|
18
|
+
device_token: string;
|
|
19
|
+
platform: string;
|
|
20
|
+
created_at?: Date;
|
|
21
|
+
updated_at?: Date;
|
|
22
|
+
static initModel(sequelize: Sequelize.Sequelize): typeof UserDeviceTokenModel;
|
|
23
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DataTypes, Model } from 'sequelize';
|
|
2
|
+
export class UserDeviceTokenModel extends Model {
|
|
3
|
+
static initModel(sequelize) {
|
|
4
|
+
return UserDeviceTokenModel.init({
|
|
5
|
+
user_device_token_id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
allowNull: false,
|
|
8
|
+
primaryKey: true,
|
|
9
|
+
defaultValue: DataTypes.UUIDV4
|
|
10
|
+
},
|
|
11
|
+
user_id: {
|
|
12
|
+
type: DataTypes.UUID,
|
|
13
|
+
allowNull: false,
|
|
14
|
+
references: {
|
|
15
|
+
model: 'AuthUser',
|
|
16
|
+
key: 'user_id'
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
device_token: {
|
|
20
|
+
type: DataTypes.TEXT,
|
|
21
|
+
allowNull: false
|
|
22
|
+
},
|
|
23
|
+
platform: {
|
|
24
|
+
type: DataTypes.TEXT,
|
|
25
|
+
allowNull: false,
|
|
26
|
+
defaultValue: 'android'
|
|
27
|
+
},
|
|
28
|
+
created_at: {
|
|
29
|
+
type: DataTypes.DATE,
|
|
30
|
+
allowNull: false,
|
|
31
|
+
defaultValue: DataTypes.NOW
|
|
32
|
+
},
|
|
33
|
+
updated_at: {
|
|
34
|
+
type: DataTypes.DATE,
|
|
35
|
+
allowNull: false,
|
|
36
|
+
defaultValue: DataTypes.NOW
|
|
37
|
+
}
|
|
38
|
+
}, {
|
|
39
|
+
sequelize,
|
|
40
|
+
tableName: 'UserDeviceToken',
|
|
41
|
+
schema: 'public',
|
|
42
|
+
timestamps: false,
|
|
43
|
+
indexes: [
|
|
44
|
+
{
|
|
45
|
+
name: 'UserDeviceToken_pk',
|
|
46
|
+
unique: true,
|
|
47
|
+
fields: [{ name: 'user_device_token_id' }]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'UserDeviceToken_user_id_device_token_uq',
|
|
51
|
+
unique: true,
|
|
52
|
+
fields: [{ name: 'user_id' }, { name: 'device_token' }]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'UserDeviceToken_user_id_idx',
|
|
56
|
+
fields: [{ name: 'user_id' }]
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -23,7 +23,7 @@ function transformToObject(model) {
|
|
|
23
23
|
subdivision: model.subdivision,
|
|
24
24
|
leagueId: model.league_id,
|
|
25
25
|
seasons: (model.DivisionSeasons ?? []).map((ds) => transformToSeason(ds.competition)),
|
|
26
|
-
teams: model.Teams != null ? model.Teams.map(transformToTeam) : undefined
|
|
26
|
+
teams: model.Teams != null ? model.Teams.map(team => transformToTeam(team)) : undefined
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
export { transformToObject as transformToDivision, transformToAttributes as transformFromDivision };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|