Files
rely/lib/integrations/backend/models/backend_models.dart
T
2026-02-14 20:10:16 +01:00

291 lines
7.4 KiB
Dart

// ignore_for_file: invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart';
part 'backend_models.freezed.dart';
part 'backend_models.g.dart';
/// Supported authentication methods.
@JsonEnum(fieldRename: FieldRename.snake)
enum SignInMethod {
/// Email link based sign-in.
emailMagicLink,
/// Email/password sign-in.
password,
/// OIDC token based sign-in.
oidc,
}
/// Allowed change operation types.
@JsonEnum(alwaysCreate: true)
enum ChangeOperation {
/// Create or update entity state.
@JsonValue('upsert')
upsert,
/// Remove entity state.
@JsonValue('delete')
delete,
}
/// Action taken by user against a signal item.
@JsonEnum(alwaysCreate: true)
enum SignalAction {
/// Item was viewed.
viewed,
/// Item was dismissed.
dismissed,
/// Item was saved.
saved,
/// Item resulted in purchase.
purchased,
}
/// Upload category.
@JsonEnum(alwaysCreate: true)
enum UploadPurpose {
/// Avatar upload.
@JsonValue('avatar')
avatar,
/// Generic attachment upload.
@JsonValue('attachment')
attachment,
}
/// Request body for sign-in.
@freezed
abstract class SignInRequest with _$SignInRequest {
const factory SignInRequest({
required SignInMethod method,
String? email,
String? password,
String? idToken,
}) = _SignInRequest;
factory SignInRequest.fromJson(Map<String, dynamic> json) =>
_$SignInRequestFromJson(json);
}
/// User profile returned by backend.
@freezed
abstract class UserProfile with _$UserProfile {
const factory UserProfile({
required String id,
String? email,
String? displayName,
String? avatarFileId,
}) = _UserProfile;
factory UserProfile.fromJson(Map<String, dynamic> json) =>
_$UserProfileFromJson(json);
}
/// Auth session bundle used by gateway and token storage.
@freezed
abstract class AuthSession with _$AuthSession {
@JsonSerializable(explicitToJson: true)
const factory AuthSession({
required String accessToken,
required String refreshToken,
required DateTime expiresAt,
required UserProfile user,
}) = _AuthSession;
factory AuthSession.fromJson(Map<String, dynamic> json) =>
_$AuthSessionFromJson(json);
}
/// Refresh token request body.
@freezed
abstract class AuthRefreshRequest with _$AuthRefreshRequest {
const factory AuthRefreshRequest({required String refreshToken}) =
_AuthRefreshRequest;
factory AuthRefreshRequest.fromJson(Map<String, dynamic> json) =>
_$AuthRefreshRequestFromJson(json);
}
/// Refresh token response body.
@freezed
abstract class AuthRefreshResponse with _$AuthRefreshResponse {
const factory AuthRefreshResponse({
required String accessToken,
String? refreshToken,
required DateTime expiresAt,
}) = _AuthRefreshResponse;
factory AuthRefreshResponse.fromJson(Map<String, dynamic> json) =>
_$AuthRefreshResponseFromJson(json);
}
/// Generic envelope for offline-first change operations.
@freezed
abstract class ChangeEnvelope with _$ChangeEnvelope {
const factory ChangeEnvelope({
required int schemaVersion,
required String entityType,
required String entityId,
required ChangeOperation op,
required DateTime modifiedAt,
required String clientMutationId,
Map<String, dynamic>? payload,
}) = _ChangeEnvelope;
factory ChangeEnvelope.fromJson(Map<String, dynamic> json) =>
_$ChangeEnvelopeFromJson(json);
}
/// Push request for batched local changes.
@freezed
abstract class SyncPushRequest with _$SyncPushRequest {
@JsonSerializable(explicitToJson: true)
const factory SyncPushRequest({
required String deviceId,
String? cursor,
required List<ChangeEnvelope> changes,
required String idempotencyKey,
}) = _SyncPushRequest;
factory SyncPushRequest.fromJson(Map<String, dynamic> json) =>
_$SyncPushRequestFromJson(json);
}
/// Acknowledgement for an accepted mutation.
@freezed
abstract class MutationAck with _$MutationAck {
const factory MutationAck({
required String clientMutationId,
String? serverMutationId,
DateTime? acceptedAt,
}) = _MutationAck;
factory MutationAck.fromJson(Map<String, dynamic> json) =>
_$MutationAckFromJson(json);
}
/// Rejection detail for a mutation.
@freezed
abstract class MutationRejection with _$MutationRejection {
const factory MutationRejection({
required String clientMutationId,
required String code,
required String message,
}) = _MutationRejection;
factory MutationRejection.fromJson(Map<String, dynamic> json) =>
_$MutationRejectionFromJson(json);
}
/// Result body returned by sync push.
@freezed
abstract class SyncPushResult with _$SyncPushResult {
@JsonSerializable(explicitToJson: true)
const factory SyncPushResult({
required String cursor,
@Default(<MutationAck>[]) List<MutationAck> accepted,
@Default(<MutationRejection>[]) List<MutationRejection> rejected,
}) = _SyncPushResult;
factory SyncPushResult.fromJson(Map<String, dynamic> json) =>
_$SyncPushResultFromJson(json);
}
/// Result body returned by sync pull.
@freezed
abstract class SyncPullResult with _$SyncPullResult {
@JsonSerializable(explicitToJson: true)
const factory SyncPullResult({
required String cursor,
@Default(<ChangeEnvelope>[]) List<ChangeEnvelope> changes,
}) = _SyncPullResult;
factory SyncPullResult.fromJson(Map<String, dynamic> json) =>
_$SyncPullResultFromJson(json);
}
/// Signals feed item.
@freezed
abstract class SignalItem with _$SignalItem {
const factory SignalItem({
required String id,
required String type,
required String title,
String? description,
String? personId,
required DateTime createdAt,
Map<String, dynamic>? metadata,
}) = _SignalItem;
factory SignalItem.fromJson(Map<String, dynamic> json) =>
_$SignalItemFromJson(json);
}
/// Cursor-based signals response.
@freezed
abstract class SignalsFeed with _$SignalsFeed {
@JsonSerializable(explicitToJson: true)
const factory SignalsFeed({
String? cursor,
@Default(<SignalItem>[]) List<SignalItem> items,
}) = _SignalsFeed;
factory SignalsFeed.fromJson(Map<String, dynamic> json) =>
_$SignalsFeedFromJson(json);
}
/// Signal acknowledgement request body.
@freezed
abstract class SignalAckRequest with _$SignalAckRequest {
const factory SignalAckRequest({
required SignalAction action,
required DateTime at,
}) = _SignalAckRequest;
factory SignalAckRequest.fromJson(Map<String, dynamic> json) =>
_$SignalAckRequestFromJson(json);
}
/// Upload init request.
@freezed
abstract class UploadInitRequest with _$UploadInitRequest {
const factory UploadInitRequest({
required UploadPurpose purpose,
required String contentType,
required int sizeBytes,
}) = _UploadInitRequest;
factory UploadInitRequest.fromJson(Map<String, dynamic> json) =>
_$UploadInitRequestFromJson(json);
}
/// Upload init response.
@freezed
abstract class UploadInitResult with _$UploadInitResult {
const factory UploadInitResult({
required String uploadUrl,
required String fileId,
required DateTime expiresAt,
}) = _UploadInitResult;
factory UploadInitResult.fromJson(Map<String, dynamic> json) =>
_$UploadInitResultFromJson(json);
}
/// Download URL response.
@freezed
abstract class DownloadUrl with _$DownloadUrl {
const factory DownloadUrl({
required String downloadUrl,
required DateTime expiresAt,
}) = _DownloadUrl;
factory DownloadUrl.fromJson(Map<String, dynamic> json) =>
_$DownloadUrlFromJson(json);
}