halkyon_base: a Serverpod module for sign-in, accounts and instance basics
What every Halkyon server has, taken from Halkyon Learn's: anonymous, GitHub and email-code sign-in with their endpoints, an account's ways in and its deletion, the pruning of abandoned anonymous people, of sign-up attempts and of expired codes, and the instance's basics (the sign-in ways offered, the source link, the minimum app build, where people's data and its backups are). Endpoints sit under the nickname `base`. A host configures it in one place before its pod starts: its name for the mails, its source link, its minimum build, and hooks that delete its own data with a person. The tables keep Learn's names, columns and indexes, so a host moving onto the module migrates nothing but version rows. Server package under the SSPL, client under the AGPL, as Learn's are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
80fa7b9628
commit
af1de799f4
10 changed files with 17704 additions and 3 deletions
|
|
@ -0,0 +1,2 @@
|
|||
export 'src/protocol/protocol.dart';
|
||||
export 'package:serverpod_client/serverpod_client.dart';
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/* 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;
|
||||
|
||||
/// A code accepted: the address is now the signed-in person's (or already
|
||||
/// was), or it is another person's and [switchToken] signs in as them.
|
||||
abstract class EmailCodeAccepted
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
EmailCodeAccepted._({this.switchToken});
|
||||
|
||||
factory EmailCodeAccepted({String? switchToken}) = _EmailCodeAcceptedImpl;
|
||||
|
||||
factory EmailCodeAccepted.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return EmailCodeAccepted(
|
||||
switchToken: jsonSerialization['switchToken'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
/// Null when the address is the signed-in person's; else what signs in as
|
||||
/// the person who has it, once, within the code's 15 minutes
|
||||
/// (`EmailSignInEndpoint.signIn`).
|
||||
String? switchToken;
|
||||
|
||||
/// Returns a shallow copy of this [EmailCodeAccepted]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
EmailCodeAccepted copyWith({String? switchToken});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.EmailCodeAccepted',
|
||||
if (switchToken != null) 'switchToken': switchToken,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.EmailCodeAccepted',
|
||||
if (switchToken != null) 'switchToken': switchToken,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _Undefined {}
|
||||
|
||||
class _EmailCodeAcceptedImpl extends EmailCodeAccepted {
|
||||
_EmailCodeAcceptedImpl({String? switchToken})
|
||||
: super._(switchToken: switchToken);
|
||||
|
||||
/// Returns a shallow copy of this [EmailCodeAccepted]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
EmailCodeAccepted copyWith({Object? switchToken = _Undefined}) {
|
||||
return EmailCodeAccepted(
|
||||
switchToken: switchToken is String? ? switchToken : this.switchToken,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/* 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;
|
||||
|
||||
/// Why mailing a code, accepting it, or signing in with an email address
|
||||
/// was refused.
|
||||
enum EmailSignInRefusal implements _isc.SerializableModel {
|
||||
/// This instance has no email sign-in (no emailSignInPepper in its
|
||||
/// passwords, or no way to send mail).
|
||||
unavailable,
|
||||
|
||||
/// What was typed isn't an email address.
|
||||
notAnAddress,
|
||||
|
||||
/// Too many codes asked for, for this address or from this network, in
|
||||
/// the last hour.
|
||||
tooManyCodes,
|
||||
|
||||
/// The code is wrong.
|
||||
wrongCode,
|
||||
|
||||
/// The code was typed wrong too often; a new one is needed.
|
||||
tooManyTries,
|
||||
|
||||
/// The code is no longer valid: past its time, used, or replaced by a
|
||||
/// newer one.
|
||||
codeExpired,
|
||||
|
||||
/// The person already signs in with another address.
|
||||
otherAddressLinked,
|
||||
|
||||
/// The mail couldn't be sent; nothing was kept of the request.
|
||||
mailFailed;
|
||||
|
||||
static EmailSignInRefusal fromJson(String name) {
|
||||
switch (name) {
|
||||
case 'unavailable':
|
||||
return EmailSignInRefusal.unavailable;
|
||||
case 'notAnAddress':
|
||||
return EmailSignInRefusal.notAnAddress;
|
||||
case 'tooManyCodes':
|
||||
return EmailSignInRefusal.tooManyCodes;
|
||||
case 'wrongCode':
|
||||
return EmailSignInRefusal.wrongCode;
|
||||
case 'tooManyTries':
|
||||
return EmailSignInRefusal.tooManyTries;
|
||||
case 'codeExpired':
|
||||
return EmailSignInRefusal.codeExpired;
|
||||
case 'otherAddressLinked':
|
||||
return EmailSignInRefusal.otherAddressLinked;
|
||||
case 'mailFailed':
|
||||
return EmailSignInRefusal.mailFailed;
|
||||
default:
|
||||
throw ArgumentError(
|
||||
'Value "$name" cannot be converted to "EmailSignInRefusal"',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toJson() => name;
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/* 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;
|
||||
import '../auth/email_sign_in_refusal.dart' as _in9x16lz;
|
||||
|
||||
/// Mailing a code, accepting it, or signing in with an email address was
|
||||
/// refused; nothing changed.
|
||||
abstract class EmailSignInRefusedException
|
||||
implements
|
||||
_isc.SerializableException,
|
||||
_isc.SerializableModel,
|
||||
_isc.ProtocolSerialization {
|
||||
EmailSignInRefusedException._({required this.reason});
|
||||
|
||||
factory EmailSignInRefusedException({
|
||||
required _in9x16lz.EmailSignInRefusal reason,
|
||||
}) = _EmailSignInRefusedExceptionImpl;
|
||||
|
||||
factory EmailSignInRefusedException.fromJson(
|
||||
Map<String, dynamic> jsonSerialization,
|
||||
) {
|
||||
return EmailSignInRefusedException(
|
||||
reason: _in9x16lz.EmailSignInRefusal.fromJson(
|
||||
(jsonSerialization['reason'] as String),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Why it was refused.
|
||||
_in9x16lz.EmailSignInRefusal reason;
|
||||
|
||||
/// Returns a shallow copy of this [EmailSignInRefusedException]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
EmailSignInRefusedException copyWith({_in9x16lz.EmailSignInRefusal? reason});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.EmailSignInRefusedException',
|
||||
'reason': reason.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.EmailSignInRefusedException',
|
||||
'reason': reason.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'EmailSignInRefusedException(reason: $reason)';
|
||||
}
|
||||
}
|
||||
|
||||
class _EmailSignInRefusedExceptionImpl extends EmailSignInRefusedException {
|
||||
_EmailSignInRefusedExceptionImpl({
|
||||
required _in9x16lz.EmailSignInRefusal reason,
|
||||
}) : super._(reason: reason);
|
||||
|
||||
/// Returns a shallow copy of this [EmailSignInRefusedException]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
EmailSignInRefusedException copyWith({_in9x16lz.EmailSignInRefusal? reason}) {
|
||||
return EmailSignInRefusedException(reason: reason ?? this.reason);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/* 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;
|
||||
|
||||
/// Why signing in with GitHub, or linking a GitHub account, was refused.
|
||||
enum GitHubSignInRefusal implements _isc.SerializableModel {
|
||||
/// This instance has no GitHub OAuth app (no githubClientId and
|
||||
/// githubClientSecret in its passwords).
|
||||
unavailable,
|
||||
|
||||
/// The GitHub account already belongs to another person.
|
||||
takenByAnotherPerson,
|
||||
|
||||
/// The person already has a different GitHub account.
|
||||
otherGitHubAccountLinked,
|
||||
|
||||
/// No person has this GitHub account; only linking one creates it.
|
||||
unknownAccount;
|
||||
|
||||
static GitHubSignInRefusal fromJson(String name) {
|
||||
switch (name) {
|
||||
case 'unavailable':
|
||||
return GitHubSignInRefusal.unavailable;
|
||||
case 'takenByAnotherPerson':
|
||||
return GitHubSignInRefusal.takenByAnotherPerson;
|
||||
case 'otherGitHubAccountLinked':
|
||||
return GitHubSignInRefusal.otherGitHubAccountLinked;
|
||||
case 'unknownAccount':
|
||||
return GitHubSignInRefusal.unknownAccount;
|
||||
default:
|
||||
throw ArgumentError(
|
||||
'Value "$name" cannot be converted to "GitHubSignInRefusal"',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toJson() => name;
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/* 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;
|
||||
import '../auth/github_sign_in_refusal.dart' as _irgbwy1y;
|
||||
|
||||
/// Signing in with GitHub, or linking a GitHub account, was refused; nothing
|
||||
/// changed.
|
||||
abstract class GitHubSignInRefusedException
|
||||
implements
|
||||
_isc.SerializableException,
|
||||
_isc.SerializableModel,
|
||||
_isc.ProtocolSerialization {
|
||||
GitHubSignInRefusedException._({required this.reason});
|
||||
|
||||
factory GitHubSignInRefusedException({
|
||||
required _irgbwy1y.GitHubSignInRefusal reason,
|
||||
}) = _GitHubSignInRefusedExceptionImpl;
|
||||
|
||||
factory GitHubSignInRefusedException.fromJson(
|
||||
Map<String, dynamic> jsonSerialization,
|
||||
) {
|
||||
return GitHubSignInRefusedException(
|
||||
reason: _irgbwy1y.GitHubSignInRefusal.fromJson(
|
||||
(jsonSerialization['reason'] as String),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Why it was refused.
|
||||
_irgbwy1y.GitHubSignInRefusal reason;
|
||||
|
||||
/// Returns a shallow copy of this [GitHubSignInRefusedException]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
GitHubSignInRefusedException copyWith({
|
||||
_irgbwy1y.GitHubSignInRefusal? reason,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.GitHubSignInRefusedException',
|
||||
'reason': reason.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.GitHubSignInRefusedException',
|
||||
'reason': reason.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GitHubSignInRefusedException(reason: $reason)';
|
||||
}
|
||||
}
|
||||
|
||||
class _GitHubSignInRefusedExceptionImpl extends GitHubSignInRefusedException {
|
||||
_GitHubSignInRefusedExceptionImpl({
|
||||
required _irgbwy1y.GitHubSignInRefusal reason,
|
||||
}) : super._(reason: reason);
|
||||
|
||||
/// Returns a shallow copy of this [GitHubSignInRefusedException]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
GitHubSignInRefusedException copyWith({
|
||||
_irgbwy1y.GitHubSignInRefusal? reason,
|
||||
}) {
|
||||
return GitHubSignInRefusedException(reason: reason ?? this.reason);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/* 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;
|
||||
|
||||
/// The ways a person signs in, besides an anonymous account's session.
|
||||
abstract class SignInWays
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
SignInWays._({
|
||||
required this.gitHub,
|
||||
required this.email,
|
||||
});
|
||||
|
||||
factory SignInWays({
|
||||
required bool gitHub,
|
||||
required bool email,
|
||||
}) = _SignInWaysImpl;
|
||||
|
||||
factory SignInWays.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return SignInWays(
|
||||
gitHub: _isc.BoolJsonExtension.fromJson(jsonSerialization['gitHub']),
|
||||
email: _isc.BoolJsonExtension.fromJson(jsonSerialization['email']),
|
||||
);
|
||||
}
|
||||
|
||||
bool gitHub;
|
||||
|
||||
bool email;
|
||||
|
||||
/// Returns a shallow copy of this [SignInWays]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
SignInWays copyWith({
|
||||
bool? gitHub,
|
||||
bool? email,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.SignInWays',
|
||||
'gitHub': gitHub,
|
||||
'email': email,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.SignInWays',
|
||||
'gitHub': gitHub,
|
||||
'email': email,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _SignInWaysImpl extends SignInWays {
|
||||
_SignInWaysImpl({
|
||||
required bool gitHub,
|
||||
required bool email,
|
||||
}) : super._(
|
||||
gitHub: gitHub,
|
||||
email: email,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [SignInWays]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
SignInWays copyWith({
|
||||
bool? gitHub,
|
||||
bool? email,
|
||||
}) {
|
||||
return SignInWays(
|
||||
gitHub: gitHub ?? this.gitHub,
|
||||
email: email ?? this.email,
|
||||
);
|
||||
}
|
||||
}
|
||||
247
packages/halkyon_base_client/lib/src/protocol/client.dart
Normal file
247
packages/halkyon_base_client/lib/src/protocol/client.dart
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/* 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 'dart:async' as _ida;
|
||||
import 'package:halkyon_base_client/src/protocol/auth/email_code_accepted.dart'
|
||||
as _ioeosfv3;
|
||||
import 'package:halkyon_base_client/src/protocol/auth/sign_in_ways.dart'
|
||||
as _ifld8s4r;
|
||||
import 'package:halkyon_base_client/src/protocol/instance/instance_basics.dart'
|
||||
as _isnyur2i;
|
||||
import 'package:serverpod_auth_core_client/serverpod_auth_core_client.dart'
|
||||
as _iacc;
|
||||
import 'package:serverpod_auth_idp_client/serverpod_auth_idp_client.dart'
|
||||
as _iaic;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
|
||||
/// The signed-in person's account.
|
||||
/// {@category Endpoint}
|
||||
class EndpointAccount extends _isc.EndpointRef {
|
||||
EndpointAccount(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.account';
|
||||
|
||||
/// Deletes the caller with everything they have (see [deletePerson]). The
|
||||
/// app also calls it when an anonymous account is given up (decided
|
||||
/// 2026-09-30). Their other devices learn at once that their sessions
|
||||
/// ended.
|
||||
_ida.Future<void> delete() => caller.callServerEndpoint<void>(
|
||||
'halkyon_base.account',
|
||||
'delete',
|
||||
{},
|
||||
);
|
||||
|
||||
/// How the caller signs in besides their sessions: with GitHub, with an
|
||||
/// email address, both, or neither (anonymous).
|
||||
_ida.Future<_ifld8s4r.SignInWays> signInWays() =>
|
||||
caller.callServerEndpoint<_ifld8s4r.SignInWays>(
|
||||
'halkyon_base.account',
|
||||
'signInWays',
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
/// Signs people in anonymously; the app calls it on first launch. Creating an
|
||||
/// account is rate-limited per IP address (see `auth_config.dart`).
|
||||
/// {@category Endpoint}
|
||||
class EndpointAnonymousIdp extends _iaic.EndpointAnonymousIdpBase {
|
||||
EndpointAnonymousIdp(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.anonymousIdp';
|
||||
|
||||
/// Creates a new anonymous account and returns its session.
|
||||
///
|
||||
/// Invokes the [AnonymousIdp.beforeAnonymousAccount] callback if configured,
|
||||
/// which may prevent account creation if the endpoint is protected.
|
||||
@override
|
||||
_ida.Future<_iacc.AuthSuccess> login({String? token}) =>
|
||||
caller.callServerEndpoint<_iacc.AuthSuccess>(
|
||||
'halkyon_base.anonymousIdp',
|
||||
'login',
|
||||
{'token': token},
|
||||
);
|
||||
}
|
||||
|
||||
/// Signing in with an email address, by a code mailed to it:
|
||||
/// the way to keep an anonymous account, as linking GitHub is, and a second
|
||||
/// way in for someone who signs in with GitHub. Signed in only, as every
|
||||
/// device is from its first start.
|
||||
/// {@category Endpoint}
|
||||
class EndpointEmailCode extends _isc.EndpointRef {
|
||||
EndpointEmailCode(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.emailCode';
|
||||
|
||||
/// Mails a code to [address], worded in [language] (`en`, `de`), and
|
||||
/// returns the request it answers; refusals as in [sendSignInCode].
|
||||
_ida.Future<_isc.UuidValue> sendCode({
|
||||
required String address,
|
||||
required String language,
|
||||
}) => caller.callServerEndpoint<_isc.UuidValue>(
|
||||
'halkyon_base.emailCode',
|
||||
'sendCode',
|
||||
{
|
||||
'address': address,
|
||||
'language': language,
|
||||
},
|
||||
);
|
||||
|
||||
/// Accepts [code] for [request]: the address becomes the caller's unless
|
||||
/// it is another person's, whose token then signs in as them
|
||||
/// (`EmailSignInEndpoint.signIn`); refusals as in [acceptSignInCode].
|
||||
_ida.Future<_ioeosfv3.EmailCodeAccepted> verifyCode({
|
||||
required _isc.UuidValue request,
|
||||
required String code,
|
||||
}) => caller.callServerEndpoint<_ioeosfv3.EmailCodeAccepted>(
|
||||
'halkyon_base.emailCode',
|
||||
'verifyCode',
|
||||
{
|
||||
'request': request,
|
||||
'code': code,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Signs in the person whose address a mailed code proved, when the device
|
||||
/// switches to them. Called without a session: Serverpod issues no session
|
||||
/// for another person inside a signed-in call.
|
||||
/// {@category Endpoint}
|
||||
class EndpointEmailSignIn extends _isc.EndpointRef {
|
||||
EndpointEmailSignIn(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.emailSignIn';
|
||||
|
||||
/// A session for the person [switchToken] names; refusals as in
|
||||
/// [signInWithEmail].
|
||||
_ida.Future<_iacc.AuthSuccess> signIn({required String switchToken}) =>
|
||||
caller.callServerEndpoint<_iacc.AuthSuccess>(
|
||||
'halkyon_base.emailSignIn',
|
||||
'signIn',
|
||||
{'switchToken': switchToken},
|
||||
);
|
||||
}
|
||||
|
||||
/// Signs in the person who already has a GitHub account, e.g. when they switch
|
||||
/// to it on another device. Called without a session: Serverpod issues no
|
||||
/// session for another person inside a signed-in call.
|
||||
/// {@category Endpoint}
|
||||
class EndpointGitHubSignIn extends _isc.EndpointRef {
|
||||
EndpointGitHubSignIn(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.gitHubSignIn';
|
||||
|
||||
/// A session for the person with the GitHub account that [code] proves;
|
||||
/// refusals as in [signInWithGitHubAccount].
|
||||
_ida.Future<_iacc.AuthSuccess> signIn({
|
||||
required String code,
|
||||
required String codeVerifier,
|
||||
required String redirectUri,
|
||||
}) => caller.callServerEndpoint<_iacc.AuthSuccess>(
|
||||
'halkyon_base.gitHubSignIn',
|
||||
'signIn',
|
||||
{
|
||||
'code': code,
|
||||
'codeVerifier': codeVerifier,
|
||||
'redirectUri': redirectUri,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Links a GitHub account to the signed-in person: the lossless upgrade from
|
||||
/// an anonymous account. The person and everything they have stay
|
||||
/// where they are; only the way they sign in changes.
|
||||
/// {@category Endpoint}
|
||||
class EndpointGitHubUpgrade extends _isc.EndpointRef {
|
||||
EndpointGitHubUpgrade(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.gitHubUpgrade';
|
||||
|
||||
/// Links the GitHub account that [code] proves to the caller; refusals as in
|
||||
/// [linkGitHubAccount].
|
||||
_ida.Future<void> upgrade({
|
||||
required String code,
|
||||
required String codeVerifier,
|
||||
required String redirectUri,
|
||||
}) => caller.callServerEndpoint<void>(
|
||||
'halkyon_base.gitHubUpgrade',
|
||||
'upgrade',
|
||||
{
|
||||
'code': code,
|
||||
'codeVerifier': codeVerifier,
|
||||
'redirectUri': redirectUri,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// What every Halkyon instance tells its apps. Public: an app asks before
|
||||
/// anyone is signed in.
|
||||
/// {@category Endpoint}
|
||||
class EndpointInstance extends _isc.EndpointRef {
|
||||
EndpointInstance(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'halkyon_base.instance';
|
||||
|
||||
/// This instance's basics: GitHub sign-in only with the operator's OAuth
|
||||
/// app, email sign-in only where it can mail codes, where its source is,
|
||||
/// the oldest app build it works with, and where it keeps people's data
|
||||
/// and its backups.
|
||||
_ida.Future<_isnyur2i.InstanceBasics> basics() =>
|
||||
caller.callServerEndpoint<_isnyur2i.InstanceBasics>(
|
||||
'halkyon_base.instance',
|
||||
'basics',
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
class Caller extends _isc.ModuleEndpointCaller {
|
||||
Caller(_isc.ServerpodClientShared client) : super(client) {
|
||||
account = EndpointAccount(this);
|
||||
anonymousIdp = EndpointAnonymousIdp(this);
|
||||
emailCode = EndpointEmailCode(this);
|
||||
emailSignIn = EndpointEmailSignIn(this);
|
||||
gitHubSignIn = EndpointGitHubSignIn(this);
|
||||
gitHubUpgrade = EndpointGitHubUpgrade(this);
|
||||
instance = EndpointInstance(this);
|
||||
}
|
||||
|
||||
late final EndpointAccount account;
|
||||
|
||||
late final EndpointAnonymousIdp anonymousIdp;
|
||||
|
||||
late final EndpointEmailCode emailCode;
|
||||
|
||||
late final EndpointEmailSignIn emailSignIn;
|
||||
|
||||
late final EndpointGitHubSignIn gitHubSignIn;
|
||||
|
||||
late final EndpointGitHubUpgrade gitHubUpgrade;
|
||||
|
||||
late final EndpointInstance instance;
|
||||
|
||||
@override
|
||||
Map<String, _isc.EndpointRef> get endpointRefLookup => {
|
||||
'halkyon_base.account': account,
|
||||
'halkyon_base.anonymousIdp': anonymousIdp,
|
||||
'halkyon_base.emailCode': emailCode,
|
||||
'halkyon_base.emailSignIn': emailSignIn,
|
||||
'halkyon_base.gitHubSignIn': gitHubSignIn,
|
||||
'halkyon_base.gitHubUpgrade': gitHubUpgrade,
|
||||
'halkyon_base.instance': instance,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/* 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;
|
||||
|
||||
/// What every Halkyon instance tells its apps, to anyone, before anyone signs
|
||||
/// in: how people sign in here, where the source of what it runs is, the
|
||||
/// oldest app build it works with, and where it keeps people's data. Every
|
||||
/// instance is run by someone else, with its own configuration.
|
||||
abstract class InstanceBasics
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
InstanceBasics._({
|
||||
this.gitHubClientId,
|
||||
required this.emailSignIn,
|
||||
required this.sourceCodeUrl,
|
||||
required this.minimumAppBuild,
|
||||
this.dataLocation,
|
||||
this.backupLocation,
|
||||
});
|
||||
|
||||
factory InstanceBasics({
|
||||
String? gitHubClientId,
|
||||
required bool emailSignIn,
|
||||
required String sourceCodeUrl,
|
||||
required int minimumAppBuild,
|
||||
String? dataLocation,
|
||||
String? backupLocation,
|
||||
}) = _InstanceBasicsImpl;
|
||||
|
||||
factory InstanceBasics.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return InstanceBasics(
|
||||
gitHubClientId: jsonSerialization['gitHubClientId'] as String?,
|
||||
emailSignIn: _isc.BoolJsonExtension.fromJson(
|
||||
jsonSerialization['emailSignIn'],
|
||||
),
|
||||
sourceCodeUrl: jsonSerialization['sourceCodeUrl'] as String,
|
||||
minimumAppBuild: jsonSerialization['minimumAppBuild'] as int,
|
||||
dataLocation: jsonSerialization['dataLocation'] as String?,
|
||||
backupLocation: jsonSerialization['backupLocation'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
/// The client ID of this instance's GitHub OAuth app, or null when GitHub
|
||||
/// sign-in is off here.
|
||||
String? gitHubClientId;
|
||||
|
||||
/// Whether people can sign in with an email address here: a code mailed
|
||||
/// to it.
|
||||
bool emailSignIn;
|
||||
|
||||
/// Where the source of what this instance runs is; the licences require
|
||||
/// offering it to the people who use it.
|
||||
String sourceCodeUrl;
|
||||
|
||||
/// The oldest build of the app (the number after `+` in its version) this
|
||||
/// server still works with; older apps ask to be updated.
|
||||
int minimumAppBuild;
|
||||
|
||||
/// Where this instance keeps people's data, as its operator says
|
||||
/// (DATA_LOCATION): a country's code (ISO 3166-1 alpha-2, `CH`) or `EU`;
|
||||
/// where the disks are, not which law governs. Null where the operator
|
||||
/// says nothing.
|
||||
String? dataLocation;
|
||||
|
||||
/// Where it keeps its backups (BACKUP_LOCATION): as [dataLocation], or
|
||||
/// `none` where it keeps none. Null where the operator says nothing.
|
||||
String? backupLocation;
|
||||
|
||||
/// Returns a shallow copy of this [InstanceBasics]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
InstanceBasics copyWith({
|
||||
String? gitHubClientId,
|
||||
bool? emailSignIn,
|
||||
String? sourceCodeUrl,
|
||||
int? minimumAppBuild,
|
||||
String? dataLocation,
|
||||
String? backupLocation,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.InstanceBasics',
|
||||
if (gitHubClientId != null) 'gitHubClientId': gitHubClientId,
|
||||
'emailSignIn': emailSignIn,
|
||||
'sourceCodeUrl': sourceCodeUrl,
|
||||
'minimumAppBuild': minimumAppBuild,
|
||||
if (dataLocation != null) 'dataLocation': dataLocation,
|
||||
if (backupLocation != null) 'backupLocation': backupLocation,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'halkyon_base.InstanceBasics',
|
||||
if (gitHubClientId != null) 'gitHubClientId': gitHubClientId,
|
||||
'emailSignIn': emailSignIn,
|
||||
'sourceCodeUrl': sourceCodeUrl,
|
||||
'minimumAppBuild': minimumAppBuild,
|
||||
if (dataLocation != null) 'dataLocation': dataLocation,
|
||||
if (backupLocation != null) 'backupLocation': backupLocation,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _Undefined {}
|
||||
|
||||
class _InstanceBasicsImpl extends InstanceBasics {
|
||||
_InstanceBasicsImpl({
|
||||
String? gitHubClientId,
|
||||
required bool emailSignIn,
|
||||
required String sourceCodeUrl,
|
||||
required int minimumAppBuild,
|
||||
String? dataLocation,
|
||||
String? backupLocation,
|
||||
}) : super._(
|
||||
gitHubClientId: gitHubClientId,
|
||||
emailSignIn: emailSignIn,
|
||||
sourceCodeUrl: sourceCodeUrl,
|
||||
minimumAppBuild: minimumAppBuild,
|
||||
dataLocation: dataLocation,
|
||||
backupLocation: backupLocation,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [InstanceBasics]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
InstanceBasics copyWith({
|
||||
Object? gitHubClientId = _Undefined,
|
||||
bool? emailSignIn,
|
||||
String? sourceCodeUrl,
|
||||
int? minimumAppBuild,
|
||||
Object? dataLocation = _Undefined,
|
||||
Object? backupLocation = _Undefined,
|
||||
}) {
|
||||
return InstanceBasics(
|
||||
gitHubClientId: gitHubClientId is String?
|
||||
? gitHubClientId
|
||||
: this.gitHubClientId,
|
||||
emailSignIn: emailSignIn ?? this.emailSignIn,
|
||||
sourceCodeUrl: sourceCodeUrl ?? this.sourceCodeUrl,
|
||||
minimumAppBuild: minimumAppBuild ?? this.minimumAppBuild,
|
||||
dataLocation: dataLocation is String? ? dataLocation : this.dataLocation,
|
||||
backupLocation: backupLocation is String?
|
||||
? backupLocation
|
||||
: this.backupLocation,
|
||||
);
|
||||
}
|
||||
}
|
||||
296
packages/halkyon_base_client/lib/src/protocol/protocol.dart
Normal file
296
packages/halkyon_base_client/lib/src/protocol/protocol.dart
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
/* 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: dead_code, unnecessary_type_check
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod_auth_core_client/serverpod_auth_core_client.dart'
|
||||
as _iacc;
|
||||
import 'package:serverpod_auth_idp_client/serverpod_auth_idp_client.dart'
|
||||
as _iaic;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import 'auth/email_code_accepted.dart' as _iys46ui1;
|
||||
import 'auth/email_sign_in_refusal.dart' as _ieyvcag1;
|
||||
import 'auth/email_sign_in_refused_exception.dart' as _iztfgag5;
|
||||
import 'auth/github_sign_in_refusal.dart' as _ir1gd9p5;
|
||||
import 'auth/github_sign_in_refused_exception.dart' as _i0xfcu5n;
|
||||
import 'auth/sign_in_ways.dart' as _ie6tbh85;
|
||||
import 'instance/instance_basics.dart' as _i8jixqx6;
|
||||
export 'auth/email_code_accepted.dart';
|
||||
export 'auth/email_sign_in_refusal.dart';
|
||||
export 'auth/email_sign_in_refused_exception.dart';
|
||||
export 'auth/github_sign_in_refusal.dart';
|
||||
export 'auth/github_sign_in_refused_exception.dart';
|
||||
export 'auth/sign_in_ways.dart';
|
||||
export 'instance/instance_basics.dart';
|
||||
export 'client.dart';
|
||||
|
||||
class Protocol extends _isc.SerializationManager {
|
||||
Protocol._();
|
||||
|
||||
factory Protocol() => _instance;
|
||||
|
||||
static final Protocol _instance = Protocol._();
|
||||
|
||||
final Set<_isc.SerializationManager> _hostProtocols = {};
|
||||
|
||||
void registerHostProtocol(
|
||||
String projectName,
|
||||
_isc.SerializationManager protocol,
|
||||
) {
|
||||
_hostProtocols.add(protocol);
|
||||
}
|
||||
|
||||
static String? getClassNameFromObjectJson(dynamic data) {
|
||||
if (data is! Map) return null;
|
||||
final className = data['__className__'] as String?;
|
||||
if (className == null) return null;
|
||||
if (!className.startsWith('halkyon_base.')) return className;
|
||||
return className.substring(13);
|
||||
}
|
||||
|
||||
@override
|
||||
T deserialize<T>(
|
||||
dynamic data, [
|
||||
Type? t,
|
||||
]) {
|
||||
t ??= T;
|
||||
|
||||
final dataClassName = getClassNameFromObjectJson(data);
|
||||
if (dataClassName != null && dataClassName != getClassNameForType(t)) {
|
||||
try {
|
||||
return deserializeByClassName({
|
||||
'className': dataClassName,
|
||||
'data': data,
|
||||
});
|
||||
} on _isc.DeserializationClassNameNotFoundException catch (_) {
|
||||
// If the className is not recognized (e.g., older client receiving
|
||||
// data with a new subtype), fall back to deserializing without the
|
||||
// className, using the expected type T.
|
||||
}
|
||||
}
|
||||
|
||||
if (t == _iys46ui1.EmailCodeAccepted) {
|
||||
return _iys46ui1.EmailCodeAccepted.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ieyvcag1.EmailSignInRefusal) {
|
||||
return _ieyvcag1.EmailSignInRefusal.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iztfgag5.EmailSignInRefusedException) {
|
||||
return _iztfgag5.EmailSignInRefusedException.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ir1gd9p5.GitHubSignInRefusal) {
|
||||
return _ir1gd9p5.GitHubSignInRefusal.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i0xfcu5n.GitHubSignInRefusedException) {
|
||||
return _i0xfcu5n.GitHubSignInRefusedException.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ie6tbh85.SignInWays) {
|
||||
return _ie6tbh85.SignInWays.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i8jixqx6.InstanceBasics) {
|
||||
return _i8jixqx6.InstanceBasics.fromJson(data) as T;
|
||||
}
|
||||
if (t == _isc.getType<_iys46ui1.EmailCodeAccepted?>()) {
|
||||
return (data != null ? _iys46ui1.EmailCodeAccepted.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ieyvcag1.EmailSignInRefusal?>()) {
|
||||
return (data != null ? _ieyvcag1.EmailSignInRefusal.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_iztfgag5.EmailSignInRefusedException?>()) {
|
||||
return (data != null
|
||||
? _iztfgag5.EmailSignInRefusedException.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ir1gd9p5.GitHubSignInRefusal?>()) {
|
||||
return (data != null
|
||||
? _ir1gd9p5.GitHubSignInRefusal.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i0xfcu5n.GitHubSignInRefusedException?>()) {
|
||||
return (data != null
|
||||
? _i0xfcu5n.GitHubSignInRefusedException.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ie6tbh85.SignInWays?>()) {
|
||||
return (data != null ? _ie6tbh85.SignInWays.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_i8jixqx6.InstanceBasics?>()) {
|
||||
return (data != null ? _i8jixqx6.InstanceBasics.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
try {
|
||||
return _iaic.Protocol().deserialize<T>(data, t);
|
||||
} on _isc.DeserializationTypeNotFoundException catch (_) {}
|
||||
try {
|
||||
return _iacc.Protocol().deserialize<T>(data, t);
|
||||
} on _isc.DeserializationTypeNotFoundException catch (_) {}
|
||||
return super.deserialize<T>(data, t);
|
||||
}
|
||||
|
||||
static String? getClassNameForType(Type type) {
|
||||
return switch (type) {
|
||||
_iys46ui1.EmailCodeAccepted => 'EmailCodeAccepted',
|
||||
_ieyvcag1.EmailSignInRefusal => 'EmailSignInRefusal',
|
||||
_iztfgag5.EmailSignInRefusedException => 'EmailSignInRefusedException',
|
||||
_ir1gd9p5.GitHubSignInRefusal => 'GitHubSignInRefusal',
|
||||
_i0xfcu5n.GitHubSignInRefusedException => 'GitHubSignInRefusedException',
|
||||
_ie6tbh85.SignInWays => 'SignInWays',
|
||||
_i8jixqx6.InstanceBasics => 'InstanceBasics',
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String? getClassNameForObject(Object? data) {
|
||||
String? className = super.getClassNameForObject(data);
|
||||
if (className != null) return className;
|
||||
|
||||
if (data is Map<String, dynamic> && data['__className__'] is String) {
|
||||
return (data['__className__'] as String).replaceFirst(
|
||||
'halkyon_base.',
|
||||
'',
|
||||
);
|
||||
}
|
||||
|
||||
switch (data) {
|
||||
case _iys46ui1.EmailCodeAccepted():
|
||||
return 'EmailCodeAccepted';
|
||||
case _ieyvcag1.EmailSignInRefusal():
|
||||
return 'EmailSignInRefusal';
|
||||
case _iztfgag5.EmailSignInRefusedException():
|
||||
return 'EmailSignInRefusedException';
|
||||
case _ir1gd9p5.GitHubSignInRefusal():
|
||||
return 'GitHubSignInRefusal';
|
||||
case _i0xfcu5n.GitHubSignInRefusedException():
|
||||
return 'GitHubSignInRefusedException';
|
||||
case _ie6tbh85.SignInWays():
|
||||
return 'SignInWays';
|
||||
case _i8jixqx6.InstanceBasics():
|
||||
return 'InstanceBasics';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic deserializeByClassName(Map<String, dynamic> data) {
|
||||
var dataClassName = data['className'];
|
||||
if (dataClassName is! String) {
|
||||
return super.deserializeByClassName(data);
|
||||
}
|
||||
if (dataClassName == 'EmailCodeAccepted') {
|
||||
return deserialize<_iys46ui1.EmailCodeAccepted>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'EmailSignInRefusal') {
|
||||
return deserialize<_ieyvcag1.EmailSignInRefusal>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'EmailSignInRefusedException') {
|
||||
return deserialize<_iztfgag5.EmailSignInRefusedException>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'GitHubSignInRefusal') {
|
||||
return deserialize<_ir1gd9p5.GitHubSignInRefusal>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'GitHubSignInRefusedException') {
|
||||
return deserialize<_i0xfcu5n.GitHubSignInRefusedException>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'SignInWays') {
|
||||
return deserialize<_ie6tbh85.SignInWays>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'InstanceBasics') {
|
||||
return deserialize<_i8jixqx6.InstanceBasics>(data['data']);
|
||||
}
|
||||
return super.deserializeByClassName(data);
|
||||
}
|
||||
|
||||
@override
|
||||
Object? dynamicFieldToJson(
|
||||
Object? object, {
|
||||
bool forProtocol = false,
|
||||
}) {
|
||||
if ((object is List || object is Set || object is Map) ||
|
||||
getClassNameForObject(object) != null) {
|
||||
return super.dynamicFieldToJson(object, forProtocol: forProtocol);
|
||||
}
|
||||
for (final protocol in _hostProtocols) {
|
||||
final className = protocol.getClassNameForObject(object);
|
||||
if (className == null) continue;
|
||||
final host = protocol.getModuleName();
|
||||
final wrapped = {
|
||||
'className': className.contains('.') ? className : '$host.$className',
|
||||
'data': object,
|
||||
};
|
||||
return forProtocol
|
||||
? _isc.SerializationManager.toEncodableForProtocol(wrapped)
|
||||
: _isc.SerializationManager.toEncodable(wrapped);
|
||||
}
|
||||
return super.dynamicFieldToJson(object, forProtocol: forProtocol);
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic deserializeDynamicFieldValue(Object? value) {
|
||||
if (value == null) return null;
|
||||
if (value is! Map<String, dynamic> || value['className'] is! String) {
|
||||
throw FormatException(
|
||||
'Dynamic fields are encoded as a Map with className and data, but got '
|
||||
'${value.runtimeType} instead.',
|
||||
);
|
||||
}
|
||||
final className = value['className'] as String;
|
||||
for (final protocol in _hostProtocols) {
|
||||
final host = protocol.getModuleName();
|
||||
final hostPrefix = '$host.';
|
||||
if (className.startsWith(hostPrefix)) {
|
||||
final strippedClassName = className.substring(hostPrefix.length);
|
||||
if (strippedClassName.contains('.')) {
|
||||
throw FormatException(
|
||||
'Dynamic field className must not use multiple prefixes: $className',
|
||||
);
|
||||
}
|
||||
final hostData = Map<String, dynamic>.from(value);
|
||||
hostData['className'] = strippedClassName;
|
||||
return protocol.deserializeByClassName(hostData);
|
||||
}
|
||||
}
|
||||
if (className.contains('.')) {
|
||||
for (final protocol in _hostProtocols) {
|
||||
try {
|
||||
return protocol.deserializeByClassName(value);
|
||||
} on _isc.DeserializationClassNameNotFoundException catch (_) {}
|
||||
}
|
||||
}
|
||||
return deserializeByClassName(value);
|
||||
}
|
||||
|
||||
@override
|
||||
String getModuleName() => 'halkyon_base';
|
||||
|
||||
/// Maps any `Record`s known to this [Protocol] to their JSON representation
|
||||
///
|
||||
/// Throws in case the record type is not known.
|
||||
///
|
||||
/// This method will return `null` (only) for `null` inputs.
|
||||
Map<String, dynamic>? mapRecordToJson(Record? record) {
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return _iaic.Protocol().mapRecordToJson(record);
|
||||
} catch (_) {}
|
||||
try {
|
||||
return _iacc.Protocol().mapRecordToJson(record);
|
||||
} catch (_) {}
|
||||
throw Exception('Unsupported record type ${record.runtimeType}');
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue