feat(profile): advertise per-variant dictionary versions for offline preload

The Profile now carries dict_versions (game variant -> current dictionary
version), populated from the dictionary registry at the profileResponse
choke point, so an installed PWA can preload the matching dawg per enabled
variant off the existing cold-start profile request instead of adding a
round-trip for a rare feature.

Wire path: FBS DictVersion table + Profile.dict_versions (additive,
backward-compatible trailing field) -> backend dto/registry -> gateway
ProfileResp + FBS encoder -> client codec decode into a per-variant map on
model.Profile. Empty in a degenerate no-dictionary deployment; the mock
serves v1.3.0 for all three variants. Codec decode covered by a
bite-tested round-trip unit test.
This commit is contained in:
Ilia Denisov
2026-07-06 10:12:58 +02:00
parent 8349e222fc
commit a692024b4e
14 changed files with 321 additions and 2 deletions
+22
View File
@@ -712,6 +712,28 @@ describe('codec', () => {
expect(decodeProfile(b.asUint8Array()).variantPreferences).toEqual(['erudit_ru', 'scrabble_en']);
});
it('decodes the profile dictionary versions into a per-variant map', () => {
const b = new Builder(128);
const uid = b.createString('u-1');
const en = fb.DictVersion.createDictVersion(b, b.createString('scrabble_en'), b.createString('v1.3.0'));
const er = fb.DictVersion.createDictVersion(b, b.createString('erudit_ru'), b.createString('v1.2.0'));
const vec = fb.Profile.createDictVersionsVector(b, [en, er]);
fb.Profile.startProfile(b);
fb.Profile.addUserId(b, uid);
fb.Profile.addDictVersions(b, vec);
b.finish(fb.Profile.endProfile(b));
expect(decodeProfile(b.asUint8Array()).dictVersions).toEqual({ scrabble_en: 'v1.3.0', erudit_ru: 'v1.2.0' });
});
it('decodes an absent dict_versions vector to an empty map', () => {
const b = new Builder(64);
const uid = b.createString('u-1');
fb.Profile.startProfile(b);
fb.Profile.addUserId(b, uid);
b.finish(fb.Profile.endProfile(b));
expect(decodeProfile(b.asUint8Array()).dictVersions).toEqual({});
});
it('encodes the update-profile variant preferences', () => {
const buf = encodeUpdateProfile({
displayName: 'Kaya',