feat(server): dictionaries, loaded from files and searched

The server now holds dictionaries for everyone: `dictionary_entry` and
`dictionary_source`, reference data owned by no one, never synced. It
loads the dictionary files in its `dictionaries` folder at every start,
those whose SHA-256 changed: in the background, each source replaced in
one transaction, so searches meanwhile find the old entries; a file it
can't read is logged and left out. All of JMdict loads in under half a
minute. On an instance the folder is deploy/dictionaries, mounted
read-only (compose.yaml); the server's README says how.

DictionaryEndpoint (signed in): the dictionaries with their credits; a
search (exact key, exact loose key, key starting with the query, loose
key starting with it, each in the source's order; katakana as hiragana,
macrons written out), some 150-450 ms over all of JMdict; and the
entries with a label, counted and a page at a time (all JLPT N5 words).

The curator now keeps spellings that aren't quite right apart, as
`looseKeys` (romaji with long vowels typed once): "sushi" finds 寿司
before 数詞 (すうし).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-09 00:51:27 +02:00
commit 3013bc04b3
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
6 changed files with 16048 additions and 73 deletions

View file

@ -16,6 +16,10 @@ import 'package:halkyon_learn_client/src/protocol/asset/file_usage.dart'
as _iimptq0q;
import 'package:halkyon_learn_client/src/protocol/auth/device.dart'
as _ieqh4yr9;
import 'package:halkyon_learn_client/src/protocol/dictionary/dictionary_hit.dart'
as _iqbqiphu;
import 'package:halkyon_learn_client/src/protocol/dictionary/dictionary_source.dart'
as _i8vj64sp;
import 'package:halkyon_learn_client/src/protocol/instance/instance_info.dart'
as _i26u8vl4;
import 'package:http/http.dart' as _i85jenna;
@ -220,6 +224,82 @@ class EndpointGitHubUpgrade extends _isc.EndpointRef {
);
}
/// The dictionaries the instance holds, to look words up in and to take
/// words from by a label (all JLPT N5 words). Reference data: any signed-in
/// person may read all of it.
/// {@category Endpoint}
class EndpointDictionary extends _isc.EndpointRef {
EndpointDictionary(_isc.EndpointCaller caller) : super(caller);
@override
String get name => 'dictionary';
/// The dictionaries there are, with whose work they are.
_ida.Future<List<_i8vj64sp.DictionarySource>> dictionaries() =>
caller.callServerEndpoint<List<_i8vj64sp.DictionarySource>>(
'dictionary',
'dictionaries',
{},
);
/// The entries of the dictionary of [language] with meanings in
/// [glossLanguage] that [query] finds, best first: those with a key that
/// is the query, then a loose key that is (`sushi` for すうし), then a key
/// starting with it, then a loose key; each in the dictionary's order. At
/// most [limit] (30 unless given).
_ida.Future<List<_iqbqiphu.DictionaryHit>> search(
String language,
String glossLanguage,
String query, {
int? limit,
}) => caller.callServerEndpoint<List<_iqbqiphu.DictionaryHit>>(
'dictionary',
'search',
{
'language': language,
'glossLanguage': glossLanguage,
'query': query,
'limit': limit,
},
);
/// How many entries of the dictionary of [language] with meanings in
/// [glossLanguage] carry [label].
_ida.Future<int> countLabelled(
String language,
String glossLanguage,
String label,
) => caller.callServerEndpoint<int>(
'dictionary',
'countLabelled',
{
'language': language,
'glossLanguage': glossLanguage,
'label': label,
},
);
/// The entries that carry [label], in the dictionary's order: [limit] of
/// them (100 unless given, at most [maxPage]) after the first [offset].
_ida.Future<List<_iqbqiphu.DictionaryHit>> labelled(
String language,
String glossLanguage,
String label, {
int? offset,
int? limit,
}) => caller.callServerEndpoint<List<_iqbqiphu.DictionaryHit>>(
'dictionary',
'labelled',
{
'language': language,
'glossLanguage': glossLanguage,
'label': label,
'offset': offset,
'limit': limit,
},
);
}
/// What this instance offers. Public: the app asks before anyone is signed in.
/// {@category Endpoint}
class EndpointInstance extends _isc.EndpointRef {
@ -285,6 +365,7 @@ class Client extends _isc.ServerpodClientShared {
devices = EndpointDevices(this);
gitHubSignIn = EndpointGitHubSignIn(this);
gitHubUpgrade = EndpointGitHubUpgrade(this);
dictionary = EndpointDictionary(this);
instance = EndpointInstance(this);
modules = Modules(this);
}
@ -301,6 +382,8 @@ class Client extends _isc.ServerpodClientShared {
late final EndpointGitHubUpgrade gitHubUpgrade;
late final EndpointDictionary dictionary;
late final EndpointInstance instance;
late final Modules modules;
@ -313,6 +396,7 @@ class Client extends _isc.ServerpodClientShared {
'devices': devices,
'gitHubSignIn': gitHubSignIn,
'gitHubUpgrade': gitHubUpgrade,
'dictionary': dictionary,
'instance': instance,
};

View file

@ -0,0 +1,120 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: invalid_use_of_internal_member
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _isc;
/// Who made what a dictionary is drawn from, under which licence.
abstract class DictionaryCredit
implements _isc.SerializableModel, _isc.ProtocolSerialization {
DictionaryCredit._({
required this.name,
required this.by,
required this.license,
required this.url,
});
factory DictionaryCredit({
required String name,
required String by,
required String license,
required String url,
}) = _DictionaryCreditImpl;
factory DictionaryCredit.fromJson(Map<String, dynamic> jsonSerialization) {
return DictionaryCredit(
name: jsonSerialization['name'] as String,
by: jsonSerialization['by'] as String,
license: jsonSerialization['license'] as String,
url: jsonSerialization['url'] as String,
);
}
/// What it is (`JMdict`).
String name;
/// Who made it.
String by;
/// Its licence, an SPDX identifier.
String license;
/// Where it is described.
String url;
/// Returns a shallow copy of this [DictionaryCredit]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
DictionaryCredit copyWith({
String? name,
String? by,
String? license,
String? url,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'DictionaryCredit',
'name': name,
'by': by,
'license': license,
'url': url,
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'DictionaryCredit',
'name': name,
'by': by,
'license': license,
'url': url,
};
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _DictionaryCreditImpl extends DictionaryCredit {
_DictionaryCreditImpl({
required String name,
required String by,
required String license,
required String url,
}) : super._(
name: name,
by: by,
license: license,
url: url,
);
/// Returns a shallow copy of this [DictionaryCredit]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
DictionaryCredit copyWith({
String? name,
String? by,
String? license,
String? url,
}) {
return DictionaryCredit(
name: name ?? this.name,
by: by ?? this.by,
license: license ?? this.license,
url: url ?? this.url,
);
}
}

View file

@ -0,0 +1,234 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: invalid_use_of_internal_member
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _isc;
/// An entry of a dictionary the instance holds (JMdict, …): reference data for
/// everyone, owned by no one and never synced. The server loads it from a
/// dictionary file (dictionary_loader.dart; the format is the curator's README).
/// A card made from it copies what it needs and keeps the source and id only as
/// a soft reference, so loading a newer version never touches cards.
abstract class DictionaryEntry
implements _isc.SerializableModel, _isc.ProtocolSerialization {
DictionaryEntry._({
this.id,
required this.source,
required this.sourceId,
required this.language,
required this.glossLanguage,
required this.headword,
this.reading,
required this.rank,
required this.labels,
required this.searchKeys,
required this.looseKeys,
required this.entry,
});
factory DictionaryEntry({
int? id,
required String source,
required String sourceId,
required String language,
required String glossLanguage,
required String headword,
String? reading,
required int rank,
required String labels,
required String searchKeys,
required String looseKeys,
required String entry,
}) = _DictionaryEntryImpl;
factory DictionaryEntry.fromJson(Map<String, dynamic> jsonSerialization) {
return DictionaryEntry(
id: jsonSerialization['id'] as int?,
source: jsonSerialization['source'] as String,
sourceId: jsonSerialization['sourceId'] as String,
language: jsonSerialization['language'] as String,
glossLanguage: jsonSerialization['glossLanguage'] as String,
headword: jsonSerialization['headword'] as String,
reading: jsonSerialization['reading'] as String?,
rank: jsonSerialization['rank'] as int,
labels: jsonSerialization['labels'] as String,
searchKeys: jsonSerialization['searchKeys'] as String,
looseKeys: jsonSerialization['looseKeys'] as String,
entry: jsonSerialization['entry'] as String,
);
}
/// The database id, set if the object has been inserted into the
/// database or if it has been fetched from the database. Otherwise,
/// the id will be null.
int? id;
/// The source its file names (`jmdict`).
String source;
/// Its id in the source.
String sourceId;
/// The words' language, a BCP 47 tag (`ja`).
String language;
/// The meanings' language (`en`).
String glossLanguage;
/// How the word is shown.
String headword;
/// How it is read; null when the headword is its own reading.
String? reading;
/// Its order among the source's entries, lower first.
int rank;
/// Its labels between bars (`|common|jlpt:n5|`), for LIKE to find one.
String labels;
/// What a search matches, lower case, between bars
/// (`|食べる|たべる|taberu|eat|`).
String searchKeys;
/// What a search matches after every searchKeys match: spellings people
/// type that aren't quite right (`sushi` for すうし), between bars too.
String looseKeys;
/// The entry as cards take it: its JSON, as the file holds it.
String entry;
/// Returns a shallow copy of this [DictionaryEntry]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
DictionaryEntry copyWith({
int? id,
String? source,
String? sourceId,
String? language,
String? glossLanguage,
String? headword,
String? reading,
int? rank,
String? labels,
String? searchKeys,
String? looseKeys,
String? entry,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'DictionaryEntry',
if (id != null) 'id': id,
'source': source,
'sourceId': sourceId,
'language': language,
'glossLanguage': glossLanguage,
'headword': headword,
if (reading != null) 'reading': reading,
'rank': rank,
'labels': labels,
'searchKeys': searchKeys,
'looseKeys': looseKeys,
'entry': entry,
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'DictionaryEntry',
if (id != null) 'id': id,
'source': source,
'sourceId': sourceId,
'language': language,
'glossLanguage': glossLanguage,
'headword': headword,
if (reading != null) 'reading': reading,
'rank': rank,
'labels': labels,
'searchKeys': searchKeys,
'looseKeys': looseKeys,
'entry': entry,
};
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _Undefined {}
class _DictionaryEntryImpl extends DictionaryEntry {
_DictionaryEntryImpl({
int? id,
required String source,
required String sourceId,
required String language,
required String glossLanguage,
required String headword,
String? reading,
required int rank,
required String labels,
required String searchKeys,
required String looseKeys,
required String entry,
}) : super._(
id: id,
source: source,
sourceId: sourceId,
language: language,
glossLanguage: glossLanguage,
headword: headword,
reading: reading,
rank: rank,
labels: labels,
searchKeys: searchKeys,
looseKeys: looseKeys,
entry: entry,
);
/// Returns a shallow copy of this [DictionaryEntry]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
DictionaryEntry copyWith({
Object? id = _Undefined,
String? source,
String? sourceId,
String? language,
String? glossLanguage,
String? headword,
Object? reading = _Undefined,
int? rank,
String? labels,
String? searchKeys,
String? looseKeys,
String? entry,
}) {
return DictionaryEntry(
id: id is int? ? id : this.id,
source: source ?? this.source,
sourceId: sourceId ?? this.sourceId,
language: language ?? this.language,
glossLanguage: glossLanguage ?? this.glossLanguage,
headword: headword ?? this.headword,
reading: reading is String? ? reading : this.reading,
rank: rank ?? this.rank,
labels: labels ?? this.labels,
searchKeys: searchKeys ?? this.searchKeys,
looseKeys: looseKeys ?? this.looseKeys,
entry: entry ?? this.entry,
);
}
}

View file

@ -0,0 +1,151 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: invalid_use_of_internal_member
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:halkyon_learn_client/src/protocol/protocol.dart' as _itx5j3f5;
import 'package:serverpod_client/serverpod_client.dart' as _isc;
/// A dictionary entry as the app receives it: what it shows and turns into a
/// card, without what only the search needs.
abstract class DictionaryHit
implements _isc.SerializableModel, _isc.ProtocolSerialization {
DictionaryHit._({
required this.source,
required this.sourceId,
required this.headword,
this.reading,
required this.labels,
required this.entry,
});
factory DictionaryHit({
required String source,
required String sourceId,
required String headword,
String? reading,
required List<String> labels,
required String entry,
}) = _DictionaryHitImpl;
factory DictionaryHit.fromJson(Map<String, dynamic> jsonSerialization) {
return DictionaryHit(
source: jsonSerialization['source'] as String,
sourceId: jsonSerialization['sourceId'] as String,
headword: jsonSerialization['headword'] as String,
reading: jsonSerialization['reading'] as String?,
labels: _itx5j3f5.Protocol().deserialize<List<String>>(
jsonSerialization['labels'],
),
entry: jsonSerialization['entry'] as String,
);
}
/// The source and the entry's id in it: a card keeps them, to find the
/// word again and not to add it twice.
String source;
String sourceId;
String headword;
/// Null when the headword is its own reading.
String? reading;
/// `common`, `jlpt:n5`, …
List<String> labels;
/// The entry as cards take it, as JSON (the curator's README).
String entry;
/// Returns a shallow copy of this [DictionaryHit]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
DictionaryHit copyWith({
String? source,
String? sourceId,
String? headword,
String? reading,
List<String>? labels,
String? entry,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'DictionaryHit',
'source': source,
'sourceId': sourceId,
'headword': headword,
if (reading != null) 'reading': reading,
'labels': labels.toJson(),
'entry': entry,
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'DictionaryHit',
'source': source,
'sourceId': sourceId,
'headword': headword,
if (reading != null) 'reading': reading,
'labels': labels.toJson(),
'entry': entry,
};
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _Undefined {}
class _DictionaryHitImpl extends DictionaryHit {
_DictionaryHitImpl({
required String source,
required String sourceId,
required String headword,
String? reading,
required List<String> labels,
required String entry,
}) : super._(
source: source,
sourceId: sourceId,
headword: headword,
reading: reading,
labels: labels,
entry: entry,
);
/// Returns a shallow copy of this [DictionaryHit]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
DictionaryHit copyWith({
String? source,
String? sourceId,
String? headword,
Object? reading = _Undefined,
List<String>? labels,
String? entry,
}) {
return DictionaryHit(
source: source ?? this.source,
sourceId: sourceId ?? this.sourceId,
headword: headword ?? this.headword,
reading: reading is String? ? reading : this.reading,
labels: labels ?? this.labels.map((e0) => e0).toList(),
entry: entry ?? this.entry,
);
}
}

View file

@ -0,0 +1,223 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: invalid_use_of_internal_member
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:halkyon_learn_client/src/protocol/protocol.dart' as _itx5j3f5;
import 'package:serverpod_client/serverpod_client.dart' as _isc;
import '../dictionary/dictionary_credit.dart' as _it7o1p0g;
/// A dictionary the instance holds: one source in one meaning language, as
/// loaded from its file. The app lists the credits where it names its data
/// sources; the file's hash tells the loader whether it changed since.
abstract class DictionarySource
implements _isc.SerializableModel, _isc.ProtocolSerialization {
DictionarySource._({
this.id,
required this.source,
required this.sourceVersion,
required this.language,
required this.glossLanguage,
required this.license,
required this.credits,
required this.entryCount,
required this.fileName,
required this.fileHash,
required this.loadedAt,
});
factory DictionarySource({
int? id,
required String source,
required String sourceVersion,
required String language,
required String glossLanguage,
required String license,
required List<_it7o1p0g.DictionaryCredit> credits,
required int entryCount,
required String fileName,
required String fileHash,
required DateTime loadedAt,
}) = _DictionarySourceImpl;
factory DictionarySource.fromJson(Map<String, dynamic> jsonSerialization) {
return DictionarySource(
id: jsonSerialization['id'] as int?,
source: jsonSerialization['source'] as String,
sourceVersion: jsonSerialization['sourceVersion'] as String,
language: jsonSerialization['language'] as String,
glossLanguage: jsonSerialization['glossLanguage'] as String,
license: jsonSerialization['license'] as String,
credits: _itx5j3f5.Protocol()
.deserialize<List<_it7o1p0g.DictionaryCredit>>(
jsonSerialization['credits'],
),
entryCount: jsonSerialization['entryCount'] as int,
fileName: jsonSerialization['fileName'] as String,
fileHash: jsonSerialization['fileHash'] as String,
loadedAt: _isc.DateTimeJsonExtension.fromJson(
jsonSerialization['loadedAt'],
),
);
}
/// The database id, set if the object has been inserted into the
/// database or if it has been fetched from the database. Otherwise,
/// the id will be null.
int? id;
/// The source (`jmdict`).
String source;
/// Its version (`3.6.2 (2026-10-05)`).
String sourceVersion;
/// The words' language (`ja`).
String language;
/// The meanings' language (`en`).
String glossLanguage;
/// The data's licence, an SPDX identifier.
String license;
/// Everything it is drawn from.
List<_it7o1p0g.DictionaryCredit> credits;
/// How many entries it has.
int entryCount;
/// The file it was loaded from, and the file's SHA-256.
String fileName;
String fileHash;
/// When it was loaded, in UTC.
DateTime loadedAt;
/// Returns a shallow copy of this [DictionarySource]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
DictionarySource copyWith({
int? id,
String? source,
String? sourceVersion,
String? language,
String? glossLanguage,
String? license,
List<_it7o1p0g.DictionaryCredit>? credits,
int? entryCount,
String? fileName,
String? fileHash,
DateTime? loadedAt,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'DictionarySource',
if (id != null) 'id': id,
'source': source,
'sourceVersion': sourceVersion,
'language': language,
'glossLanguage': glossLanguage,
'license': license,
'credits': credits.toJson(valueToJson: (v) => v.toJson()),
'entryCount': entryCount,
'fileName': fileName,
'fileHash': fileHash,
'loadedAt': loadedAt.toJson(),
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'DictionarySource',
if (id != null) 'id': id,
'source': source,
'sourceVersion': sourceVersion,
'language': language,
'glossLanguage': glossLanguage,
'license': license,
'credits': credits.toJson(valueToJson: (v) => v.toJsonForProtocol()),
'entryCount': entryCount,
'fileName': fileName,
'fileHash': fileHash,
'loadedAt': loadedAt.toJson(),
};
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _Undefined {}
class _DictionarySourceImpl extends DictionarySource {
_DictionarySourceImpl({
int? id,
required String source,
required String sourceVersion,
required String language,
required String glossLanguage,
required String license,
required List<_it7o1p0g.DictionaryCredit> credits,
required int entryCount,
required String fileName,
required String fileHash,
required DateTime loadedAt,
}) : super._(
id: id,
source: source,
sourceVersion: sourceVersion,
language: language,
glossLanguage: glossLanguage,
license: license,
credits: credits,
entryCount: entryCount,
fileName: fileName,
fileHash: fileHash,
loadedAt: loadedAt,
);
/// Returns a shallow copy of this [DictionarySource]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
DictionarySource copyWith({
Object? id = _Undefined,
String? source,
String? sourceVersion,
String? language,
String? glossLanguage,
String? license,
List<_it7o1p0g.DictionaryCredit>? credits,
int? entryCount,
String? fileName,
String? fileHash,
DateTime? loadedAt,
}) {
return DictionarySource(
id: id is int? ? id : this.id,
source: source ?? this.source,
sourceVersion: sourceVersion ?? this.sourceVersion,
language: language ?? this.language,
glossLanguage: glossLanguage ?? this.glossLanguage,
license: license ?? this.license,
credits: credits ?? this.credits.map((e0) => e0.copyWith()).toList(),
entryCount: entryCount ?? this.entryCount,
fileName: fileName ?? this.fileName,
fileHash: fileHash ?? this.fileHash,
loadedAt: loadedAt ?? this.loadedAt,
);
}
}

View file

@ -13,6 +13,10 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:halkyon_learn_client/src/protocol/auth/device.dart'
as _ieqh4yr9;
import 'package:halkyon_learn_client/src/protocol/dictionary/dictionary_hit.dart'
as _iqbqiphu;
import 'package:halkyon_learn_client/src/protocol/dictionary/dictionary_source.dart'
as _i8vj64sp;
import 'package:serverpod_auth_core_client/serverpod_auth_core_client.dart'
as _iacc;
import 'package:serverpod_auth_idp_client/serverpod_auth_idp_client.dart'
@ -31,6 +35,10 @@ import 'auth/github_sign_in_refused_exception.dart' as _i0xfcu5n;
import 'card/card.dart' as _ipiw1cmx;
import 'card/card_revision.dart' as _ipbyuef1;
import 'common/not_found_exception.dart' as _i8oee73b;
import 'dictionary/dictionary_credit.dart' as _ii4hopsr;
import 'dictionary/dictionary_entry.dart' as _i4ipxv77;
import 'dictionary/dictionary_hit.dart' as _ivbh47kc;
import 'dictionary/dictionary_source.dart' as _ie12eb65;
import 'instance/instance_info.dart' as _iskrg2g3;
import 'learning_path/learning_path.dart' as _ivt5m868;
import 'learning_path/learning_path_answer.dart' as _iy9sv3bs;
@ -57,6 +65,10 @@ export 'auth/github_sign_in_refused_exception.dart';
export 'card/card.dart';
export 'card/card_revision.dart';
export 'common/not_found_exception.dart';
export 'dictionary/dictionary_credit.dart';
export 'dictionary/dictionary_entry.dart';
export 'dictionary/dictionary_hit.dart';
export 'dictionary/dictionary_source.dart';
export 'instance/instance_info.dart';
export 'learning_path/learning_path.dart';
export 'learning_path/learning_path_answer.dart';
@ -1993,6 +2005,18 @@ class Protocol extends _isd.DatabaseSerializationManager {
if (t == _i8oee73b.NotFoundException) {
return _i8oee73b.NotFoundException.fromJson(data) as T;
}
if (t == _ii4hopsr.DictionaryCredit) {
return _ii4hopsr.DictionaryCredit.fromJson(data) as T;
}
if (t == _i4ipxv77.DictionaryEntry) {
return _i4ipxv77.DictionaryEntry.fromJson(data) as T;
}
if (t == _ivbh47kc.DictionaryHit) {
return _ivbh47kc.DictionaryHit.fromJson(data) as T;
}
if (t == _ie12eb65.DictionarySource) {
return _ie12eb65.DictionarySource.fromJson(data) as T;
}
if (t == _iskrg2g3.InstanceInfo) {
return _iskrg2g3.InstanceInfo.fromJson(data) as T;
}
@ -2082,6 +2106,22 @@ class Protocol extends _isd.DatabaseSerializationManager {
return (data != null ? _i8oee73b.NotFoundException.fromJson(data) : null)
as T;
}
if (t == _isc.getType<_ii4hopsr.DictionaryCredit?>()) {
return (data != null ? _ii4hopsr.DictionaryCredit.fromJson(data) : null)
as T;
}
if (t == _isc.getType<_i4ipxv77.DictionaryEntry?>()) {
return (data != null ? _i4ipxv77.DictionaryEntry.fromJson(data) : null)
as T;
}
if (t == _isc.getType<_ivbh47kc.DictionaryHit?>()) {
return (data != null ? _ivbh47kc.DictionaryHit.fromJson(data) : null)
as T;
}
if (t == _isc.getType<_ie12eb65.DictionarySource?>()) {
return (data != null ? _ie12eb65.DictionarySource.fromJson(data) : null)
as T;
}
if (t == _isc.getType<_iskrg2g3.InstanceInfo?>()) {
return (data != null ? _iskrg2g3.InstanceInfo.fromJson(data) : null) as T;
}
@ -2141,12 +2181,33 @@ class Protocol extends _isd.DatabaseSerializationManager {
return (data as List).map((e) => deserialize<_isc.UuidValue>(e)).toList()
as T;
}
if (t == List<String>) {
return (data as List).map((e) => deserialize<String>(e)).toList() as T;
}
if (t == List<_ii4hopsr.DictionaryCredit>) {
return (data as List)
.map((e) => deserialize<_ii4hopsr.DictionaryCredit>(e))
.toList()
as T;
}
if (t == List<_ieqh4yr9.Device>) {
return (data as List)
.map((e) => deserialize<_ieqh4yr9.Device>(e))
.toList()
as T;
}
if (t == List<_i8vj64sp.DictionarySource>) {
return (data as List)
.map((e) => deserialize<_i8vj64sp.DictionarySource>(e))
.toList()
as T;
}
if (t == List<_iqbqiphu.DictionaryHit>) {
return (data as List)
.map((e) => deserialize<_iqbqiphu.DictionaryHit>(e))
.toList()
as T;
}
try {
return _iaic.Protocol().deserialize<T>(data, t);
} on _isc.DeserializationTypeNotFoundException catch (_) {}
@ -2171,6 +2232,10 @@ class Protocol extends _isd.DatabaseSerializationManager {
_ipiw1cmx.Card => 'Card',
_ipbyuef1.CardRevision => 'CardRevision',
_i8oee73b.NotFoundException => 'NotFoundException',
_ii4hopsr.DictionaryCredit => 'DictionaryCredit',
_i4ipxv77.DictionaryEntry => 'DictionaryEntry',
_ivbh47kc.DictionaryHit => 'DictionaryHit',
_ie12eb65.DictionarySource => 'DictionarySource',
_iskrg2g3.InstanceInfo => 'InstanceInfo',
_ivt5m868.LearningPath => 'LearningPath',
_iy9sv3bs.LearningPathAnswer => 'LearningPathAnswer',
@ -2224,6 +2289,14 @@ class Protocol extends _isd.DatabaseSerializationManager {
return 'CardRevision';
case _i8oee73b.NotFoundException():
return 'NotFoundException';
case _ii4hopsr.DictionaryCredit():
return 'DictionaryCredit';
case _i4ipxv77.DictionaryEntry():
return 'DictionaryEntry';
case _ivbh47kc.DictionaryHit():
return 'DictionaryHit';
case _ie12eb65.DictionarySource():
return 'DictionarySource';
case _iskrg2g3.InstanceInfo():
return 'InstanceInfo';
case _ivt5m868.LearningPath():
@ -2314,6 +2387,18 @@ class Protocol extends _isd.DatabaseSerializationManager {
if (dataClassName == 'NotFoundException') {
return deserialize<_i8oee73b.NotFoundException>(data['data']);
}
if (dataClassName == 'DictionaryCredit') {
return deserialize<_ii4hopsr.DictionaryCredit>(data['data']);
}
if (dataClassName == 'DictionaryEntry') {
return deserialize<_i4ipxv77.DictionaryEntry>(data['data']);
}
if (dataClassName == 'DictionaryHit') {
return deserialize<_ivbh47kc.DictionaryHit>(data['data']);
}
if (dataClassName == 'DictionarySource') {
return deserialize<_ie12eb65.DictionarySource>(data['data']);
}
if (dataClassName == 'InstanceInfo') {
return deserialize<_iskrg2g3.InstanceInfo>(data['data']);
}