refactor user repo with helpers. better api validation etc.

This commit is contained in:
Jean Jacques Avril 2025-01-01 19:58:19 +00:00
parent 8559b1c44e
commit 4d52186d21
No known key found for this signature in database
23 changed files with 1802 additions and 237 deletions

View File

@ -1,5 +1,5 @@
import 'package:backend_dart/domain/entities/user.dart'; import 'package:backend_dart/domain/entities/user.dart';
import 'package:backend_dart/domain/interface/database.dart'; import 'package:backend_dart/domain/data/database.dart';
import 'package:backend_dart/domain/interface/error.dart'; import 'package:backend_dart/domain/interface/error.dart';
import 'package:backend_dart/domain/repository/user_repository.dart'; import 'package:backend_dart/domain/repository/user_repository.dart';
import 'package:fpdart/fpdart.dart'; import 'package:fpdart/fpdart.dart';
@ -9,7 +9,7 @@ class UserRepositoryImpl implements UserRepository {
UserRepositoryImpl(this.database); UserRepositoryImpl(this.database);
@override @override
TaskEither<IError, User> create(User user) { TaskEither<IError, User> create(UserCreate user) {
return database.users return database.users
.generateId() .generateId()
.map( .map(
@ -29,7 +29,7 @@ class UserRepositoryImpl implements UserRepository {
} }
@override @override
TaskEither<IError, User> update(User user) { TaskEither<IError, User> update(UserUpdate user) {
return database.users.update(user); return database.users.update(user);
} }

View File

@ -6,15 +6,39 @@ part 'user_dto.g.dart';
@freezed @freezed
class UserDto with _$UserDto { class UserDto with _$UserDto {
const factory UserDto({ const factory UserDto({
String? id, required String id,
String? name, required String name,
String? email, required String email,
String? password,
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt, DateTime? updatedAt,
}) = _UserDto; }) = _UserDto;
/// JSON-Serialisierung /// JSON-Serialisierung
factory UserDto.fromJson(Map<String, dynamic> json) => factory UserDto.fromJson(Map<String, dynamic> json) => _$UserDtoFromJson(json);
_$UserDtoFromJson(json); }
@freezed
class UserCreateDto with _$UserCreateDto {
const factory UserCreateDto({
required String name,
required String email,
required String password,
}) = _UserCreateDto;
/// JSON-Serialisierung
factory UserCreateDto.fromJson(Map<String, dynamic> json) =>
_$UserCreateDtoFromJson(json);
}
@freezed
class UserUpdateDto with _$UserUpdateDto {
const factory UserUpdateDto({
String? name,
String? email,
String? password,
}) = _UserUpdateDto;
/// JSON-Serialisierung
factory UserUpdateDto.fromJson(Map<String, dynamic> json) =>
_$UserUpdateDtoFromJson(json);
} }

View File

@ -20,10 +20,9 @@ UserDto _$UserDtoFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$UserDto { mixin _$UserDto {
String? get id => throw _privateConstructorUsedError; String get id => throw _privateConstructorUsedError;
String? get name => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError;
String? get email => throw _privateConstructorUsedError; String get email => throw _privateConstructorUsedError;
String? get password => throw _privateConstructorUsedError;
DateTime? get createdAt => throw _privateConstructorUsedError; DateTime? get createdAt => throw _privateConstructorUsedError;
DateTime? get updatedAt => throw _privateConstructorUsedError; DateTime? get updatedAt => throw _privateConstructorUsedError;
@ -42,10 +41,9 @@ abstract class $UserDtoCopyWith<$Res> {
_$UserDtoCopyWithImpl<$Res, UserDto>; _$UserDtoCopyWithImpl<$Res, UserDto>;
@useResult @useResult
$Res call( $Res call(
{String? id, {String id,
String? name, String name,
String? email, String email,
String? password,
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt}); DateTime? updatedAt});
} }
@ -65,30 +63,25 @@ class _$UserDtoCopyWithImpl<$Res, $Val extends UserDto>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? id = freezed, Object? id = null,
Object? name = freezed, Object? name = null,
Object? email = freezed, Object? email = null,
Object? password = freezed,
Object? createdAt = freezed, Object? createdAt = freezed,
Object? updatedAt = freezed, Object? updatedAt = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
id: freezed == id id: null == id
? _value.id ? _value.id
: id // ignore: cast_nullable_to_non_nullable : id // ignore: cast_nullable_to_non_nullable
as String?, as String,
name: freezed == name name: null == name
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
as String?, as String,
email: freezed == email email: null == email
? _value.email ? _value.email
: email // ignore: cast_nullable_to_non_nullable : email // ignore: cast_nullable_to_non_nullable
as String?, as String,
password: freezed == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String?,
createdAt: freezed == createdAt createdAt: freezed == createdAt
? _value.createdAt ? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable : createdAt // ignore: cast_nullable_to_non_nullable
@ -109,10 +102,9 @@ abstract class _$$UserDtoImplCopyWith<$Res> implements $UserDtoCopyWith<$Res> {
@override @override
@useResult @useResult
$Res call( $Res call(
{String? id, {String id,
String? name, String name,
String? email, String email,
String? password,
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt}); DateTime? updatedAt});
} }
@ -130,30 +122,25 @@ class __$$UserDtoImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? id = freezed, Object? id = null,
Object? name = freezed, Object? name = null,
Object? email = freezed, Object? email = null,
Object? password = freezed,
Object? createdAt = freezed, Object? createdAt = freezed,
Object? updatedAt = freezed, Object? updatedAt = freezed,
}) { }) {
return _then(_$UserDtoImpl( return _then(_$UserDtoImpl(
id: freezed == id id: null == id
? _value.id ? _value.id
: id // ignore: cast_nullable_to_non_nullable : id // ignore: cast_nullable_to_non_nullable
as String?, as String,
name: freezed == name name: null == name
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
as String?, as String,
email: freezed == email email: null == email
? _value.email ? _value.email
: email // ignore: cast_nullable_to_non_nullable : email // ignore: cast_nullable_to_non_nullable
as String?, as String,
password: freezed == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String?,
createdAt: freezed == createdAt createdAt: freezed == createdAt
? _value.createdAt ? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable : createdAt // ignore: cast_nullable_to_non_nullable
@ -170,10 +157,9 @@ class __$$UserDtoImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$UserDtoImpl implements _UserDto { class _$UserDtoImpl implements _UserDto {
const _$UserDtoImpl( const _$UserDtoImpl(
{this.id, {required this.id,
this.name, required this.name,
this.email, required this.email,
this.password,
this.createdAt, this.createdAt,
this.updatedAt}); this.updatedAt});
@ -181,13 +167,11 @@ class _$UserDtoImpl implements _UserDto {
_$$UserDtoImplFromJson(json); _$$UserDtoImplFromJson(json);
@override @override
final String? id; final String id;
@override @override
final String? name; final String name;
@override @override
final String? email; final String email;
@override
final String? password;
@override @override
final DateTime? createdAt; final DateTime? createdAt;
@override @override
@ -195,7 +179,7 @@ class _$UserDtoImpl implements _UserDto {
@override @override
String toString() { String toString() {
return 'UserDto(id: $id, name: $name, email: $email, password: $password, createdAt: $createdAt, updatedAt: $updatedAt)'; return 'UserDto(id: $id, name: $name, email: $email, createdAt: $createdAt, updatedAt: $updatedAt)';
} }
@override @override
@ -206,8 +190,6 @@ class _$UserDtoImpl implements _UserDto {
(identical(other.id, id) || other.id == id) && (identical(other.id, id) || other.id == id) &&
(identical(other.name, name) || other.name == name) && (identical(other.name, name) || other.name == name) &&
(identical(other.email, email) || other.email == email) && (identical(other.email, email) || other.email == email) &&
(identical(other.password, password) ||
other.password == password) &&
(identical(other.createdAt, createdAt) || (identical(other.createdAt, createdAt) ||
other.createdAt == createdAt) && other.createdAt == createdAt) &&
(identical(other.updatedAt, updatedAt) || (identical(other.updatedAt, updatedAt) ||
@ -217,7 +199,7 @@ class _$UserDtoImpl implements _UserDto {
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => int get hashCode =>
Object.hash(runtimeType, id, name, email, password, createdAt, updatedAt); Object.hash(runtimeType, id, name, email, createdAt, updatedAt);
/// Create a copy of UserDto /// Create a copy of UserDto
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@ -237,23 +219,20 @@ class _$UserDtoImpl implements _UserDto {
abstract class _UserDto implements UserDto { abstract class _UserDto implements UserDto {
const factory _UserDto( const factory _UserDto(
{final String? id, {required final String id,
final String? name, required final String name,
final String? email, required final String email,
final String? password,
final DateTime? createdAt, final DateTime? createdAt,
final DateTime? updatedAt}) = _$UserDtoImpl; final DateTime? updatedAt}) = _$UserDtoImpl;
factory _UserDto.fromJson(Map<String, dynamic> json) = _$UserDtoImpl.fromJson; factory _UserDto.fromJson(Map<String, dynamic> json) = _$UserDtoImpl.fromJson;
@override @override
String? get id; String get id;
@override @override
String? get name; String get name;
@override @override
String? get email; String get email;
@override
String? get password;
@override @override
DateTime? get createdAt; DateTime? get createdAt;
@override @override
@ -266,3 +245,374 @@ abstract class _UserDto implements UserDto {
_$$UserDtoImplCopyWith<_$UserDtoImpl> get copyWith => _$$UserDtoImplCopyWith<_$UserDtoImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }
UserCreateDto _$UserCreateDtoFromJson(Map<String, dynamic> json) {
return _UserCreateDto.fromJson(json);
}
/// @nodoc
mixin _$UserCreateDto {
String get name => throw _privateConstructorUsedError;
String get email => throw _privateConstructorUsedError;
String get password => throw _privateConstructorUsedError;
/// Serializes this UserCreateDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of UserCreateDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$UserCreateDtoCopyWith<UserCreateDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UserCreateDtoCopyWith<$Res> {
factory $UserCreateDtoCopyWith(
UserCreateDto value, $Res Function(UserCreateDto) then) =
_$UserCreateDtoCopyWithImpl<$Res, UserCreateDto>;
@useResult
$Res call({String name, String email, String password});
}
/// @nodoc
class _$UserCreateDtoCopyWithImpl<$Res, $Val extends UserCreateDto>
implements $UserCreateDtoCopyWith<$Res> {
_$UserCreateDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of UserCreateDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? email = null,
Object? password = null,
}) {
return _then(_value.copyWith(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
email: null == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String,
password: null == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}
/// @nodoc
abstract class _$$UserCreateDtoImplCopyWith<$Res>
implements $UserCreateDtoCopyWith<$Res> {
factory _$$UserCreateDtoImplCopyWith(
_$UserCreateDtoImpl value, $Res Function(_$UserCreateDtoImpl) then) =
__$$UserCreateDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String name, String email, String password});
}
/// @nodoc
class __$$UserCreateDtoImplCopyWithImpl<$Res>
extends _$UserCreateDtoCopyWithImpl<$Res, _$UserCreateDtoImpl>
implements _$$UserCreateDtoImplCopyWith<$Res> {
__$$UserCreateDtoImplCopyWithImpl(
_$UserCreateDtoImpl _value, $Res Function(_$UserCreateDtoImpl) _then)
: super(_value, _then);
/// Create a copy of UserCreateDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? email = null,
Object? password = null,
}) {
return _then(_$UserCreateDtoImpl(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
email: null == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String,
password: null == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
@JsonSerializable()
class _$UserCreateDtoImpl implements _UserCreateDto {
const _$UserCreateDtoImpl(
{required this.name, required this.email, required this.password});
factory _$UserCreateDtoImpl.fromJson(Map<String, dynamic> json) =>
_$$UserCreateDtoImplFromJson(json);
@override
final String name;
@override
final String email;
@override
final String password;
@override
String toString() {
return 'UserCreateDto(name: $name, email: $email, password: $password)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserCreateDtoImpl &&
(identical(other.name, name) || other.name == name) &&
(identical(other.email, email) || other.email == email) &&
(identical(other.password, password) ||
other.password == password));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, name, email, password);
/// Create a copy of UserCreateDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$UserCreateDtoImplCopyWith<_$UserCreateDtoImpl> get copyWith =>
__$$UserCreateDtoImplCopyWithImpl<_$UserCreateDtoImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$UserCreateDtoImplToJson(
this,
);
}
}
abstract class _UserCreateDto implements UserCreateDto {
const factory _UserCreateDto(
{required final String name,
required final String email,
required final String password}) = _$UserCreateDtoImpl;
factory _UserCreateDto.fromJson(Map<String, dynamic> json) =
_$UserCreateDtoImpl.fromJson;
@override
String get name;
@override
String get email;
@override
String get password;
/// Create a copy of UserCreateDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$UserCreateDtoImplCopyWith<_$UserCreateDtoImpl> get copyWith =>
throw _privateConstructorUsedError;
}
UserUpdateDto _$UserUpdateDtoFromJson(Map<String, dynamic> json) {
return _UserUpdateDto.fromJson(json);
}
/// @nodoc
mixin _$UserUpdateDto {
String? get name => throw _privateConstructorUsedError;
String? get email => throw _privateConstructorUsedError;
String? get password => throw _privateConstructorUsedError;
/// Serializes this UserUpdateDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of UserUpdateDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$UserUpdateDtoCopyWith<UserUpdateDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UserUpdateDtoCopyWith<$Res> {
factory $UserUpdateDtoCopyWith(
UserUpdateDto value, $Res Function(UserUpdateDto) then) =
_$UserUpdateDtoCopyWithImpl<$Res, UserUpdateDto>;
@useResult
$Res call({String? name, String? email, String? password});
}
/// @nodoc
class _$UserUpdateDtoCopyWithImpl<$Res, $Val extends UserUpdateDto>
implements $UserUpdateDtoCopyWith<$Res> {
_$UserUpdateDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of UserUpdateDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = freezed,
Object? email = freezed,
Object? password = freezed,
}) {
return _then(_value.copyWith(
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
email: freezed == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String?,
password: freezed == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
/// @nodoc
abstract class _$$UserUpdateDtoImplCopyWith<$Res>
implements $UserUpdateDtoCopyWith<$Res> {
factory _$$UserUpdateDtoImplCopyWith(
_$UserUpdateDtoImpl value, $Res Function(_$UserUpdateDtoImpl) then) =
__$$UserUpdateDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String? name, String? email, String? password});
}
/// @nodoc
class __$$UserUpdateDtoImplCopyWithImpl<$Res>
extends _$UserUpdateDtoCopyWithImpl<$Res, _$UserUpdateDtoImpl>
implements _$$UserUpdateDtoImplCopyWith<$Res> {
__$$UserUpdateDtoImplCopyWithImpl(
_$UserUpdateDtoImpl _value, $Res Function(_$UserUpdateDtoImpl) _then)
: super(_value, _then);
/// Create a copy of UserUpdateDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = freezed,
Object? email = freezed,
Object? password = freezed,
}) {
return _then(_$UserUpdateDtoImpl(
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
email: freezed == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String?,
password: freezed == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$UserUpdateDtoImpl implements _UserUpdateDto {
const _$UserUpdateDtoImpl({this.name, this.email, this.password});
factory _$UserUpdateDtoImpl.fromJson(Map<String, dynamic> json) =>
_$$UserUpdateDtoImplFromJson(json);
@override
final String? name;
@override
final String? email;
@override
final String? password;
@override
String toString() {
return 'UserUpdateDto(name: $name, email: $email, password: $password)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserUpdateDtoImpl &&
(identical(other.name, name) || other.name == name) &&
(identical(other.email, email) || other.email == email) &&
(identical(other.password, password) ||
other.password == password));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, name, email, password);
/// Create a copy of UserUpdateDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$UserUpdateDtoImplCopyWith<_$UserUpdateDtoImpl> get copyWith =>
__$$UserUpdateDtoImplCopyWithImpl<_$UserUpdateDtoImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$UserUpdateDtoImplToJson(
this,
);
}
}
abstract class _UserUpdateDto implements UserUpdateDto {
const factory _UserUpdateDto(
{final String? name,
final String? email,
final String? password}) = _$UserUpdateDtoImpl;
factory _UserUpdateDto.fromJson(Map<String, dynamic> json) =
_$UserUpdateDtoImpl.fromJson;
@override
String? get name;
@override
String? get email;
@override
String? get password;
/// Create a copy of UserUpdateDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$UserUpdateDtoImplCopyWith<_$UserUpdateDtoImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -8,10 +8,9 @@ part of 'user_dto.dart';
_$UserDtoImpl _$$UserDtoImplFromJson(Map<String, dynamic> json) => _$UserDtoImpl _$$UserDtoImplFromJson(Map<String, dynamic> json) =>
_$UserDtoImpl( _$UserDtoImpl(
id: json['id'] as String?, id: json['id'] as String,
name: json['name'] as String?, name: json['name'] as String,
email: json['email'] as String?, email: json['email'] as String,
password: json['password'] as String?,
createdAt: json['createdAt'] == null createdAt: json['createdAt'] == null
? null ? null
: DateTime.parse(json['createdAt'] as String), : DateTime.parse(json['createdAt'] as String),
@ -25,7 +24,34 @@ Map<String, dynamic> _$$UserDtoImplToJson(_$UserDtoImpl instance) =>
'id': instance.id, 'id': instance.id,
'name': instance.name, 'name': instance.name,
'email': instance.email, 'email': instance.email,
'password': instance.password,
'createdAt': instance.createdAt?.toIso8601String(), 'createdAt': instance.createdAt?.toIso8601String(),
'updatedAt': instance.updatedAt?.toIso8601String(), 'updatedAt': instance.updatedAt?.toIso8601String(),
}; };
_$UserCreateDtoImpl _$$UserCreateDtoImplFromJson(Map<String, dynamic> json) =>
_$UserCreateDtoImpl(
name: json['name'] as String,
email: json['email'] as String,
password: json['password'] as String,
);
Map<String, dynamic> _$$UserCreateDtoImplToJson(_$UserCreateDtoImpl instance) =>
<String, dynamic>{
'name': instance.name,
'email': instance.email,
'password': instance.password,
};
_$UserUpdateDtoImpl _$$UserUpdateDtoImplFromJson(Map<String, dynamic> json) =>
_$UserUpdateDtoImpl(
name: json['name'] as String?,
email: json['email'] as String?,
password: json['password'] as String?,
);
Map<String, dynamic> _$$UserUpdateDtoImplToJson(_$UserUpdateDtoImpl instance) =>
<String, dynamic>{
'name': instance.name,
'email': instance.email,
'password': instance.password,
};

View File

@ -18,7 +18,6 @@ class UserDtoMapper implements IMapper<User, UserDto> {
id: dto.id, id: dto.id,
name: dto.name, name: dto.name,
email: dto.email, email: dto.email,
password: dto.password,
createdAt: dto.createdAt, createdAt: dto.createdAt,
updatedAt: dto.updatedAt, updatedAt: dto.updatedAt,
)); ));
@ -32,4 +31,20 @@ class UserDtoMapper implements IMapper<User, UserDto> {
TaskEither<IError, List<UserDto>> listTo(Iterable<User> origins) { TaskEither<IError, List<UserDto>> listTo(Iterable<User> origins) {
return TaskEither.traverseList(origins.toList(), to); return TaskEither.traverseList(origins.toList(), to);
} }
TaskEither<IError, UserCreate> fromCreateTo(UserCreateDto origin) =>
TaskEither.of(UserCreate(
name: origin.name,
email: origin.email,
password: origin.password,
));
TaskEither<IError, UserUpdate> fromUpdateTo(
UserUpdateDto origin, String id) =>
TaskEither.of(UserUpdate(
id: id,
name: origin.name,
email: origin.email,
password: origin.password,
));
} }

View File

@ -2,11 +2,10 @@ import 'dart:convert';
import 'package:backend_dart/application/service/dto/user_dto.dart'; import 'package:backend_dart/application/service/dto/user_dto.dart';
import 'package:backend_dart/application/service/mapper/user_dto_mapper.dart'; import 'package:backend_dart/application/service/mapper/user_dto_mapper.dart';
import 'package:backend_dart/common/request_helper.dart';
import 'package:backend_dart/common/response_helpers.dart'; import 'package:backend_dart/common/response_helpers.dart';
import 'package:backend_dart/domain/errors/app_error.dart'; import 'package:backend_dart/common/validation.dart';
import 'package:backend_dart/domain/interface/error.dart';
import 'package:backend_dart/domain/repository/user_repository.dart'; import 'package:backend_dart/domain/repository/user_repository.dart';
import 'package:fpdart/fpdart.dart';
import 'package:shelf/shelf.dart'; import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart'; import 'package:shelf_router/shelf_router.dart';
@ -40,15 +39,11 @@ class UserService {
@Route.post('/') @Route.post('/')
Future<Response> createUser(Request request) async { Future<Response> createUser(Request request) async {
return TaskEither<IError, UserDto>.tryCatch(() async { return requestToJson(request)
final json = jsonDecode(await request.readAsString()); .flatMap(
final user = UserDto.fromJson(json); (json) => validateJsonKeys(json, ['name', 'email', 'password']))
return user; .flatMap((json) => decodeJson(json, UserCreateDto.fromJson))
}, (error, stack) { .flatMap(mapper.fromCreateTo)
return AppError.inputError(
message: 'Failed to create user: ${error.toString()}');
})
.flatMap(mapper.from)
.flatMap(users.create) .flatMap(users.create)
.flatMap(mapper.to) .flatMap(mapper.to)
.match((left) => ResponseHelpers.fromError(left), .match((left) => ResponseHelpers.fromError(left),
@ -58,15 +53,10 @@ class UserService {
@Route.put('/<userId>') @Route.put('/<userId>')
Future<Response> updateUser(Request request, String userId) async { Future<Response> updateUser(Request request, String userId) async {
return TaskEither<IError, UserDto>.tryCatch(() async { return requestToJson(request)
final json = jsonDecode(await request.readAsString()); .flatMap((json) => validateJsonKeys(json, []))
final user = UserDto.fromJson(json); .flatMap((json) => decodeJson(json, UserUpdateDto.fromJson))
return user; .flatMap((dto) => mapper.fromUpdateTo(dto, userId))
}, (error, stack) {
return AppError.inputError(
message: 'Failed to update user: ${error.toString()}');
})
.flatMap(mapper.from)
.flatMap(users.update) .flatMap(users.update)
.flatMap(mapper.to) .flatMap(mapper.to)
.match((left) => ResponseHelpers.fromError(left), .match((left) => ResponseHelpers.fromError(left),

View File

@ -0,0 +1,8 @@
extension Let<T> on T? {
R? let<R>(R Function(T it) action) {
if (this != null) {
return action(this!);
}
return null;
}
}

View File

@ -0,0 +1,31 @@
import 'dart:convert';
import 'dart:core';
import 'package:backend_dart/domain/errors/app_error.dart';
import 'package:backend_dart/domain/interface/error.dart';
import 'package:fpdart/fpdart.dart';
import 'package:shelf/shelf.dart';
TaskEither<IError, Map<String, dynamic>> requestToJson(Request request) {
return TaskEither.tryCatch(
() async {
final body = await request.readAsString();
return jsonDecode(body);
},
(error, stack) => AppError.inputError(
message: 'Failed to decode JSON: ${error.toString()}',
),
);
}
TaskEither<IError, T> decodeJson<T>(
Map<String, dynamic> json, T Function(Map<String, dynamic>) fromJson) {
return TaskEither.tryCatch(
() async {
return fromJson(json);
},
(error, stack) => AppError.inputError(
message: 'Failed to decode JSON: ${error.toString()}',
),
);
}

View File

@ -0,0 +1,10 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
String generateSecureHash(String input) {
final bytes = utf8.encode(input);
final hash = sha256.convert(bytes);
print(hash);
return hash.toString();
}

View File

@ -0,0 +1,22 @@
import 'package:backend_dart/domain/errors/app_error.dart';
import 'package:backend_dart/domain/interface/error.dart';
import 'package:fpdart/fpdart.dart';
TaskEither<IError, Map<String, dynamic>> validateJsonKeys(
Map<String, dynamic> json, List<String> requiredKeys) {
return TaskEither.tryCatch(
() async {
final missingKeys =
requiredKeys.where((key) => !json.containsKey(key)).toList();
if (missingKeys.isNotEmpty) {
throw Exception('Missing required keys: ${missingKeys.join(', ')}');
}
return json;
},
(error, _) => AppError.validationError(
message: 'Failed to validate JSON keys: ${error.toString()}',
),
);
}

View File

@ -1,7 +1,6 @@
import 'package:backend_dart/domain/data/user_data_source.dart'; import 'package:backend_dart/domain/data/user_data_source.dart';
import 'package:backend_dart/domain/entities/user.dart';
abstract class IDatabase { abstract class IDatabase {
UserDataSource<User> get users; UserDataSource get users;
Future<void> close(); Future<void> close();
} }

View File

@ -0,0 +1,34 @@
import 'package:backend_dart/domain/entities/project.dart';
/// Interface for managing project data interactions.
abstract class ProjectDataSource {
/// Creates a new project in the data source.
///
/// Throws an error if the creation fails.
Future<void> createProject(NewProject project);
/// Retrieves a project by its unique ID.
///
/// Returns `null` if no project is found.
Future<Project?> findProjectById(String id);
/// Retrieves all projects associated with a specific user.
///
/// Returns an empty list if no projects are found.
Future<List<Project>> findProjectsByUserId(String userId);
/// Updates an existing project in the data source.
///
/// Throws an error if the update fails.
Future<void> updateProject(ProjectUpdate project);
/// Deletes a project by its unique ID.
///
/// Throws an error if the deletion fails.
Future<void> deleteProject(String id);
/// Retrieves all projects in the data source.
///
/// Returns an empty list if no projects exist.
Future<List<Project>> findAllProjects();
}

View File

@ -1,18 +1,19 @@
import 'package:backend_dart/domain/entities/user.dart';
import 'package:backend_dart/domain/interface/error.dart'; import 'package:backend_dart/domain/interface/error.dart';
import 'package:fpdart/fpdart.dart'; import 'package:fpdart/fpdart.dart';
abstract class UserDataSource<T> { abstract class UserDataSource {
TaskEither<IError, T> create(T user); TaskEither<IError, User> create(UserCreate user);
TaskEither<IError, T> findByEmail(String email); TaskEither<IError, User> findByEmail(String email);
TaskEither<IError, T> findById(String id); TaskEither<IError, User> findById(String id);
TaskEither<IError, T> update(T user); TaskEither<IError, User> update(UserUpdate user);
TaskEither<IError, void> delete(String id); TaskEither<IError, void> delete(String id);
TaskEither<IError, List<T>> findAll(); TaskEither<IError, List<User>> findAll();
TaskEither<IError,String> generateId(); TaskEither<IError, String> generateId();
} }

View File

@ -0,0 +1,36 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'project.freezed.dart';
@freezed
class NewProject with _$NewProject {
const factory NewProject({
required String name,
String? description,
String? clientId,
required String userId,
}) = _NewProject;
}
@freezed
class Project with _$Project {
const factory Project({
required String id,
required String name,
String? description,
String? clientId,
required String userId,
required DateTime createdAt,
required DateTime updatedAt,
}) = _Project;
}
@freezed
class ProjectUpdate with _$ProjectUpdate {
const factory ProjectUpdate({
String? name,
String? description,
String? clientId,
String? userId,
}) = _ProjectUpdate;
}

View File

@ -0,0 +1,644 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'project.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$NewProject {
String get name => throw _privateConstructorUsedError;
String? get description => throw _privateConstructorUsedError;
String? get clientId => throw _privateConstructorUsedError;
String get userId => throw _privateConstructorUsedError;
/// Create a copy of NewProject
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$NewProjectCopyWith<NewProject> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $NewProjectCopyWith<$Res> {
factory $NewProjectCopyWith(
NewProject value, $Res Function(NewProject) then) =
_$NewProjectCopyWithImpl<$Res, NewProject>;
@useResult
$Res call(
{String name, String? description, String? clientId, String userId});
}
/// @nodoc
class _$NewProjectCopyWithImpl<$Res, $Val extends NewProject>
implements $NewProjectCopyWith<$Res> {
_$NewProjectCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of NewProject
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? description = freezed,
Object? clientId = freezed,
Object? userId = null,
}) {
return _then(_value.copyWith(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String?,
clientId: freezed == clientId
? _value.clientId
: clientId // ignore: cast_nullable_to_non_nullable
as String?,
userId: null == userId
? _value.userId
: userId // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}
/// @nodoc
abstract class _$$NewProjectImplCopyWith<$Res>
implements $NewProjectCopyWith<$Res> {
factory _$$NewProjectImplCopyWith(
_$NewProjectImpl value, $Res Function(_$NewProjectImpl) then) =
__$$NewProjectImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{String name, String? description, String? clientId, String userId});
}
/// @nodoc
class __$$NewProjectImplCopyWithImpl<$Res>
extends _$NewProjectCopyWithImpl<$Res, _$NewProjectImpl>
implements _$$NewProjectImplCopyWith<$Res> {
__$$NewProjectImplCopyWithImpl(
_$NewProjectImpl _value, $Res Function(_$NewProjectImpl) _then)
: super(_value, _then);
/// Create a copy of NewProject
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = null,
Object? description = freezed,
Object? clientId = freezed,
Object? userId = null,
}) {
return _then(_$NewProjectImpl(
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String?,
clientId: freezed == clientId
? _value.clientId
: clientId // ignore: cast_nullable_to_non_nullable
as String?,
userId: null == userId
? _value.userId
: userId // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$NewProjectImpl implements _NewProject {
const _$NewProjectImpl(
{required this.name,
this.description,
this.clientId,
required this.userId});
@override
final String name;
@override
final String? description;
@override
final String? clientId;
@override
final String userId;
@override
String toString() {
return 'NewProject(name: $name, description: $description, clientId: $clientId, userId: $userId)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$NewProjectImpl &&
(identical(other.name, name) || other.name == name) &&
(identical(other.description, description) ||
other.description == description) &&
(identical(other.clientId, clientId) ||
other.clientId == clientId) &&
(identical(other.userId, userId) || other.userId == userId));
}
@override
int get hashCode =>
Object.hash(runtimeType, name, description, clientId, userId);
/// Create a copy of NewProject
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$NewProjectImplCopyWith<_$NewProjectImpl> get copyWith =>
__$$NewProjectImplCopyWithImpl<_$NewProjectImpl>(this, _$identity);
}
abstract class _NewProject implements NewProject {
const factory _NewProject(
{required final String name,
final String? description,
final String? clientId,
required final String userId}) = _$NewProjectImpl;
@override
String get name;
@override
String? get description;
@override
String? get clientId;
@override
String get userId;
/// Create a copy of NewProject
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$NewProjectImplCopyWith<_$NewProjectImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$Project {
String get id => throw _privateConstructorUsedError;
String get name => throw _privateConstructorUsedError;
String? get description => throw _privateConstructorUsedError;
String? get clientId => throw _privateConstructorUsedError;
String get userId => throw _privateConstructorUsedError;
DateTime get createdAt => throw _privateConstructorUsedError;
DateTime get updatedAt => throw _privateConstructorUsedError;
/// Create a copy of Project
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$ProjectCopyWith<Project> get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ProjectCopyWith<$Res> {
factory $ProjectCopyWith(Project value, $Res Function(Project) then) =
_$ProjectCopyWithImpl<$Res, Project>;
@useResult
$Res call(
{String id,
String name,
String? description,
String? clientId,
String userId,
DateTime createdAt,
DateTime updatedAt});
}
/// @nodoc
class _$ProjectCopyWithImpl<$Res, $Val extends Project>
implements $ProjectCopyWith<$Res> {
_$ProjectCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of Project
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? name = null,
Object? description = freezed,
Object? clientId = freezed,
Object? userId = null,
Object? createdAt = null,
Object? updatedAt = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String?,
clientId: freezed == clientId
? _value.clientId
: clientId // ignore: cast_nullable_to_non_nullable
as String?,
userId: null == userId
? _value.userId
: userId // ignore: cast_nullable_to_non_nullable
as String,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
) as $Val);
}
}
/// @nodoc
abstract class _$$ProjectImplCopyWith<$Res> implements $ProjectCopyWith<$Res> {
factory _$$ProjectImplCopyWith(
_$ProjectImpl value, $Res Function(_$ProjectImpl) then) =
__$$ProjectImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{String id,
String name,
String? description,
String? clientId,
String userId,
DateTime createdAt,
DateTime updatedAt});
}
/// @nodoc
class __$$ProjectImplCopyWithImpl<$Res>
extends _$ProjectCopyWithImpl<$Res, _$ProjectImpl>
implements _$$ProjectImplCopyWith<$Res> {
__$$ProjectImplCopyWithImpl(
_$ProjectImpl _value, $Res Function(_$ProjectImpl) _then)
: super(_value, _then);
/// Create a copy of Project
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? name = null,
Object? description = freezed,
Object? clientId = freezed,
Object? userId = null,
Object? createdAt = null,
Object? updatedAt = null,
}) {
return _then(_$ProjectImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String?,
clientId: freezed == clientId
? _value.clientId
: clientId // ignore: cast_nullable_to_non_nullable
as String?,
userId: null == userId
? _value.userId
: userId // ignore: cast_nullable_to_non_nullable
as String,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
));
}
}
/// @nodoc
class _$ProjectImpl implements _Project {
const _$ProjectImpl(
{required this.id,
required this.name,
this.description,
this.clientId,
required this.userId,
required this.createdAt,
required this.updatedAt});
@override
final String id;
@override
final String name;
@override
final String? description;
@override
final String? clientId;
@override
final String userId;
@override
final DateTime createdAt;
@override
final DateTime updatedAt;
@override
String toString() {
return 'Project(id: $id, name: $name, description: $description, clientId: $clientId, userId: $userId, createdAt: $createdAt, updatedAt: $updatedAt)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ProjectImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.description, description) ||
other.description == description) &&
(identical(other.clientId, clientId) ||
other.clientId == clientId) &&
(identical(other.userId, userId) || other.userId == userId) &&
(identical(other.createdAt, createdAt) ||
other.createdAt == createdAt) &&
(identical(other.updatedAt, updatedAt) ||
other.updatedAt == updatedAt));
}
@override
int get hashCode => Object.hash(runtimeType, id, name, description, clientId,
userId, createdAt, updatedAt);
/// Create a copy of Project
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$ProjectImplCopyWith<_$ProjectImpl> get copyWith =>
__$$ProjectImplCopyWithImpl<_$ProjectImpl>(this, _$identity);
}
abstract class _Project implements Project {
const factory _Project(
{required final String id,
required final String name,
final String? description,
final String? clientId,
required final String userId,
required final DateTime createdAt,
required final DateTime updatedAt}) = _$ProjectImpl;
@override
String get id;
@override
String get name;
@override
String? get description;
@override
String? get clientId;
@override
String get userId;
@override
DateTime get createdAt;
@override
DateTime get updatedAt;
/// Create a copy of Project
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$ProjectImplCopyWith<_$ProjectImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$ProjectUpdate {
String? get name => throw _privateConstructorUsedError;
String? get description => throw _privateConstructorUsedError;
String? get clientId => throw _privateConstructorUsedError;
String? get userId => throw _privateConstructorUsedError;
/// Create a copy of ProjectUpdate
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$ProjectUpdateCopyWith<ProjectUpdate> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ProjectUpdateCopyWith<$Res> {
factory $ProjectUpdateCopyWith(
ProjectUpdate value, $Res Function(ProjectUpdate) then) =
_$ProjectUpdateCopyWithImpl<$Res, ProjectUpdate>;
@useResult
$Res call(
{String? name, String? description, String? clientId, String? userId});
}
/// @nodoc
class _$ProjectUpdateCopyWithImpl<$Res, $Val extends ProjectUpdate>
implements $ProjectUpdateCopyWith<$Res> {
_$ProjectUpdateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of ProjectUpdate
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = freezed,
Object? description = freezed,
Object? clientId = freezed,
Object? userId = freezed,
}) {
return _then(_value.copyWith(
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String?,
clientId: freezed == clientId
? _value.clientId
: clientId // ignore: cast_nullable_to_non_nullable
as String?,
userId: freezed == userId
? _value.userId
: userId // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
/// @nodoc
abstract class _$$ProjectUpdateImplCopyWith<$Res>
implements $ProjectUpdateCopyWith<$Res> {
factory _$$ProjectUpdateImplCopyWith(
_$ProjectUpdateImpl value, $Res Function(_$ProjectUpdateImpl) then) =
__$$ProjectUpdateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{String? name, String? description, String? clientId, String? userId});
}
/// @nodoc
class __$$ProjectUpdateImplCopyWithImpl<$Res>
extends _$ProjectUpdateCopyWithImpl<$Res, _$ProjectUpdateImpl>
implements _$$ProjectUpdateImplCopyWith<$Res> {
__$$ProjectUpdateImplCopyWithImpl(
_$ProjectUpdateImpl _value, $Res Function(_$ProjectUpdateImpl) _then)
: super(_value, _then);
/// Create a copy of ProjectUpdate
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? name = freezed,
Object? description = freezed,
Object? clientId = freezed,
Object? userId = freezed,
}) {
return _then(_$ProjectUpdateImpl(
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String?,
clientId: freezed == clientId
? _value.clientId
: clientId // ignore: cast_nullable_to_non_nullable
as String?,
userId: freezed == userId
? _value.userId
: userId // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// @nodoc
class _$ProjectUpdateImpl implements _ProjectUpdate {
const _$ProjectUpdateImpl(
{this.name, this.description, this.clientId, this.userId});
@override
final String? name;
@override
final String? description;
@override
final String? clientId;
@override
final String? userId;
@override
String toString() {
return 'ProjectUpdate(name: $name, description: $description, clientId: $clientId, userId: $userId)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ProjectUpdateImpl &&
(identical(other.name, name) || other.name == name) &&
(identical(other.description, description) ||
other.description == description) &&
(identical(other.clientId, clientId) ||
other.clientId == clientId) &&
(identical(other.userId, userId) || other.userId == userId));
}
@override
int get hashCode =>
Object.hash(runtimeType, name, description, clientId, userId);
/// Create a copy of ProjectUpdate
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$ProjectUpdateImplCopyWith<_$ProjectUpdateImpl> get copyWith =>
__$$ProjectUpdateImplCopyWithImpl<_$ProjectUpdateImpl>(this, _$identity);
}
abstract class _ProjectUpdate implements ProjectUpdate {
const factory _ProjectUpdate(
{final String? name,
final String? description,
final String? clientId,
final String? userId}) = _$ProjectUpdateImpl;
@override
String? get name;
@override
String? get description;
@override
String? get clientId;
@override
String? get userId;
/// Create a copy of ProjectUpdate
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$ProjectUpdateImplCopyWith<_$ProjectUpdateImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -5,11 +5,31 @@ part 'user.freezed.dart';
@freezed @freezed
class User with _$User { class User with _$User {
const factory User({ const factory User({
String? id, required String id,
String? name, required String name,
String? email, required String email,
String? password, String? passwordHash,
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt, DateTime? updatedAt,
}) = _User; }) = _User;
} }
@freezed
class UserCreate with _$UserCreate {
const factory UserCreate({
String? id,
required String name,
required String email,
required String password,
}) = _UserCreate;
}
@freezed
class UserUpdate with _$UserUpdate {
const factory UserUpdate({
required String id,
String? name,
String? email,
String? password,
}) = _UserUpdate;
}

View File

@ -16,10 +16,10 @@ final _privateConstructorUsedError = UnsupportedError(
/// @nodoc /// @nodoc
mixin _$User { mixin _$User {
String? get id => throw _privateConstructorUsedError; String get id => throw _privateConstructorUsedError;
String? get name => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError;
String? get email => throw _privateConstructorUsedError; String get email => throw _privateConstructorUsedError;
String? get password => throw _privateConstructorUsedError; String? get passwordHash => throw _privateConstructorUsedError;
DateTime? get createdAt => throw _privateConstructorUsedError; DateTime? get createdAt => throw _privateConstructorUsedError;
DateTime? get updatedAt => throw _privateConstructorUsedError; DateTime? get updatedAt => throw _privateConstructorUsedError;
@ -35,10 +35,10 @@ abstract class $UserCopyWith<$Res> {
_$UserCopyWithImpl<$Res, User>; _$UserCopyWithImpl<$Res, User>;
@useResult @useResult
$Res call( $Res call(
{String? id, {String id,
String? name, String name,
String? email, String email,
String? password, String? passwordHash,
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt}); DateTime? updatedAt});
} }
@ -58,29 +58,29 @@ class _$UserCopyWithImpl<$Res, $Val extends User>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? id = freezed, Object? id = null,
Object? name = freezed, Object? name = null,
Object? email = freezed, Object? email = null,
Object? password = freezed, Object? passwordHash = freezed,
Object? createdAt = freezed, Object? createdAt = freezed,
Object? updatedAt = freezed, Object? updatedAt = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
id: freezed == id id: null == id
? _value.id ? _value.id
: id // ignore: cast_nullable_to_non_nullable : id // ignore: cast_nullable_to_non_nullable
as String?, as String,
name: freezed == name name: null == name
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
as String?, as String,
email: freezed == email email: null == email
? _value.email ? _value.email
: email // ignore: cast_nullable_to_non_nullable : email // ignore: cast_nullable_to_non_nullable
as String?, as String,
password: freezed == password passwordHash: freezed == passwordHash
? _value.password ? _value.passwordHash
: password // ignore: cast_nullable_to_non_nullable : passwordHash // ignore: cast_nullable_to_non_nullable
as String?, as String?,
createdAt: freezed == createdAt createdAt: freezed == createdAt
? _value.createdAt ? _value.createdAt
@ -102,10 +102,10 @@ abstract class _$$UserImplCopyWith<$Res> implements $UserCopyWith<$Res> {
@override @override
@useResult @useResult
$Res call( $Res call(
{String? id, {String id,
String? name, String name,
String? email, String email,
String? password, String? passwordHash,
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt}); DateTime? updatedAt});
} }
@ -122,29 +122,29 @@ class __$$UserImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? id = freezed, Object? id = null,
Object? name = freezed, Object? name = null,
Object? email = freezed, Object? email = null,
Object? password = freezed, Object? passwordHash = freezed,
Object? createdAt = freezed, Object? createdAt = freezed,
Object? updatedAt = freezed, Object? updatedAt = freezed,
}) { }) {
return _then(_$UserImpl( return _then(_$UserImpl(
id: freezed == id id: null == id
? _value.id ? _value.id
: id // ignore: cast_nullable_to_non_nullable : id // ignore: cast_nullable_to_non_nullable
as String?, as String,
name: freezed == name name: null == name
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
as String?, as String,
email: freezed == email email: null == email
? _value.email ? _value.email
: email // ignore: cast_nullable_to_non_nullable : email // ignore: cast_nullable_to_non_nullable
as String?, as String,
password: freezed == password passwordHash: freezed == passwordHash
? _value.password ? _value.passwordHash
: password // ignore: cast_nullable_to_non_nullable : passwordHash // ignore: cast_nullable_to_non_nullable
as String?, as String?,
createdAt: freezed == createdAt createdAt: freezed == createdAt
? _value.createdAt ? _value.createdAt
@ -162,21 +162,21 @@ class __$$UserImplCopyWithImpl<$Res>
class _$UserImpl implements _User { class _$UserImpl implements _User {
const _$UserImpl( const _$UserImpl(
{this.id, {required this.id,
this.name, required this.name,
this.email, required this.email,
this.password, this.passwordHash,
this.createdAt, this.createdAt,
this.updatedAt}); this.updatedAt});
@override @override
final String? id; final String id;
@override @override
final String? name; final String name;
@override @override
final String? email; final String email;
@override @override
final String? password; final String? passwordHash;
@override @override
final DateTime? createdAt; final DateTime? createdAt;
@override @override
@ -184,7 +184,7 @@ class _$UserImpl implements _User {
@override @override
String toString() { String toString() {
return 'User(id: $id, name: $name, email: $email, password: $password, createdAt: $createdAt, updatedAt: $updatedAt)'; return 'User(id: $id, name: $name, email: $email, passwordHash: $passwordHash, createdAt: $createdAt, updatedAt: $updatedAt)';
} }
@override @override
@ -195,8 +195,8 @@ class _$UserImpl implements _User {
(identical(other.id, id) || other.id == id) && (identical(other.id, id) || other.id == id) &&
(identical(other.name, name) || other.name == name) && (identical(other.name, name) || other.name == name) &&
(identical(other.email, email) || other.email == email) && (identical(other.email, email) || other.email == email) &&
(identical(other.password, password) || (identical(other.passwordHash, passwordHash) ||
other.password == password) && other.passwordHash == passwordHash) &&
(identical(other.createdAt, createdAt) || (identical(other.createdAt, createdAt) ||
other.createdAt == createdAt) && other.createdAt == createdAt) &&
(identical(other.updatedAt, updatedAt) || (identical(other.updatedAt, updatedAt) ||
@ -204,8 +204,8 @@ class _$UserImpl implements _User {
} }
@override @override
int get hashCode => int get hashCode => Object.hash(
Object.hash(runtimeType, id, name, email, password, createdAt, updatedAt); runtimeType, id, name, email, passwordHash, createdAt, updatedAt);
/// Create a copy of User /// Create a copy of User
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@ -218,21 +218,21 @@ class _$UserImpl implements _User {
abstract class _User implements User { abstract class _User implements User {
const factory _User( const factory _User(
{final String? id, {required final String id,
final String? name, required final String name,
final String? email, required final String email,
final String? password, final String? passwordHash,
final DateTime? createdAt, final DateTime? createdAt,
final DateTime? updatedAt}) = _$UserImpl; final DateTime? updatedAt}) = _$UserImpl;
@override @override
String? get id; String get id;
@override @override
String? get name; String get name;
@override @override
String? get email; String get email;
@override @override
String? get password; String? get passwordHash;
@override @override
DateTime? get createdAt; DateTime? get createdAt;
@override @override
@ -245,3 +245,370 @@ abstract class _User implements User {
_$$UserImplCopyWith<_$UserImpl> get copyWith => _$$UserImplCopyWith<_$UserImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }
/// @nodoc
mixin _$UserCreate {
String? get id => throw _privateConstructorUsedError;
String get name => throw _privateConstructorUsedError;
String get email => throw _privateConstructorUsedError;
String get password => throw _privateConstructorUsedError;
/// Create a copy of UserCreate
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$UserCreateCopyWith<UserCreate> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UserCreateCopyWith<$Res> {
factory $UserCreateCopyWith(
UserCreate value, $Res Function(UserCreate) then) =
_$UserCreateCopyWithImpl<$Res, UserCreate>;
@useResult
$Res call({String? id, String name, String email, String password});
}
/// @nodoc
class _$UserCreateCopyWithImpl<$Res, $Val extends UserCreate>
implements $UserCreateCopyWith<$Res> {
_$UserCreateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of UserCreate
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = freezed,
Object? name = null,
Object? email = null,
Object? password = null,
}) {
return _then(_value.copyWith(
id: freezed == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String?,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
email: null == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String,
password: null == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}
/// @nodoc
abstract class _$$UserCreateImplCopyWith<$Res>
implements $UserCreateCopyWith<$Res> {
factory _$$UserCreateImplCopyWith(
_$UserCreateImpl value, $Res Function(_$UserCreateImpl) then) =
__$$UserCreateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String? id, String name, String email, String password});
}
/// @nodoc
class __$$UserCreateImplCopyWithImpl<$Res>
extends _$UserCreateCopyWithImpl<$Res, _$UserCreateImpl>
implements _$$UserCreateImplCopyWith<$Res> {
__$$UserCreateImplCopyWithImpl(
_$UserCreateImpl _value, $Res Function(_$UserCreateImpl) _then)
: super(_value, _then);
/// Create a copy of UserCreate
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = freezed,
Object? name = null,
Object? email = null,
Object? password = null,
}) {
return _then(_$UserCreateImpl(
id: freezed == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String?,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
email: null == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String,
password: null == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$UserCreateImpl implements _UserCreate {
const _$UserCreateImpl(
{this.id,
required this.name,
required this.email,
required this.password});
@override
final String? id;
@override
final String name;
@override
final String email;
@override
final String password;
@override
String toString() {
return 'UserCreate(id: $id, name: $name, email: $email, password: $password)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserCreateImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.email, email) || other.email == email) &&
(identical(other.password, password) ||
other.password == password));
}
@override
int get hashCode => Object.hash(runtimeType, id, name, email, password);
/// Create a copy of UserCreate
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$UserCreateImplCopyWith<_$UserCreateImpl> get copyWith =>
__$$UserCreateImplCopyWithImpl<_$UserCreateImpl>(this, _$identity);
}
abstract class _UserCreate implements UserCreate {
const factory _UserCreate(
{final String? id,
required final String name,
required final String email,
required final String password}) = _$UserCreateImpl;
@override
String? get id;
@override
String get name;
@override
String get email;
@override
String get password;
/// Create a copy of UserCreate
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$UserCreateImplCopyWith<_$UserCreateImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$UserUpdate {
String get id => throw _privateConstructorUsedError;
String? get name => throw _privateConstructorUsedError;
String? get email => throw _privateConstructorUsedError;
String? get password => throw _privateConstructorUsedError;
/// Create a copy of UserUpdate
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$UserUpdateCopyWith<UserUpdate> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UserUpdateCopyWith<$Res> {
factory $UserUpdateCopyWith(
UserUpdate value, $Res Function(UserUpdate) then) =
_$UserUpdateCopyWithImpl<$Res, UserUpdate>;
@useResult
$Res call({String id, String? name, String? email, String? password});
}
/// @nodoc
class _$UserUpdateCopyWithImpl<$Res, $Val extends UserUpdate>
implements $UserUpdateCopyWith<$Res> {
_$UserUpdateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of UserUpdate
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? name = freezed,
Object? email = freezed,
Object? password = freezed,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String,
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
email: freezed == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String?,
password: freezed == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
/// @nodoc
abstract class _$$UserUpdateImplCopyWith<$Res>
implements $UserUpdateCopyWith<$Res> {
factory _$$UserUpdateImplCopyWith(
_$UserUpdateImpl value, $Res Function(_$UserUpdateImpl) then) =
__$$UserUpdateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String id, String? name, String? email, String? password});
}
/// @nodoc
class __$$UserUpdateImplCopyWithImpl<$Res>
extends _$UserUpdateCopyWithImpl<$Res, _$UserUpdateImpl>
implements _$$UserUpdateImplCopyWith<$Res> {
__$$UserUpdateImplCopyWithImpl(
_$UserUpdateImpl _value, $Res Function(_$UserUpdateImpl) _then)
: super(_value, _then);
/// Create a copy of UserUpdate
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? name = freezed,
Object? email = freezed,
Object? password = freezed,
}) {
return _then(_$UserUpdateImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as String,
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
email: freezed == email
? _value.email
: email // ignore: cast_nullable_to_non_nullable
as String?,
password: freezed == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// @nodoc
class _$UserUpdateImpl implements _UserUpdate {
const _$UserUpdateImpl(
{required this.id, this.name, this.email, this.password});
@override
final String id;
@override
final String? name;
@override
final String? email;
@override
final String? password;
@override
String toString() {
return 'UserUpdate(id: $id, name: $name, email: $email, password: $password)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserUpdateImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.email, email) || other.email == email) &&
(identical(other.password, password) ||
other.password == password));
}
@override
int get hashCode => Object.hash(runtimeType, id, name, email, password);
/// Create a copy of UserUpdate
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$UserUpdateImplCopyWith<_$UserUpdateImpl> get copyWith =>
__$$UserUpdateImplCopyWithImpl<_$UserUpdateImpl>(this, _$identity);
}
abstract class _UserUpdate implements UserUpdate {
const factory _UserUpdate(
{required final String id,
final String? name,
final String? email,
final String? password}) = _$UserUpdateImpl;
@override
String get id;
@override
String? get name;
@override
String? get email;
@override
String? get password;
/// Create a copy of UserUpdate
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$UserUpdateImplCopyWith<_$UserUpdateImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -3,13 +3,13 @@ import 'package:backend_dart/domain/interface/error.dart';
import 'package:fpdart/fpdart.dart'; import 'package:fpdart/fpdart.dart';
abstract class UserRepository { abstract class UserRepository {
TaskEither<IError, User> create(User user); TaskEither<IError, User> create(UserCreate user);
TaskEither<IError, User> findByEmail(String email); TaskEither<IError, User> findByEmail(String email);
TaskEither<IError, User> findById(String id); TaskEither<IError, User> findById(String id);
TaskEither<IError, User> update(User user); TaskEither<IError, User> update(UserUpdate user);
TaskEither<IError, void> delete(String id); TaskEither<IError, void> delete(String id);

View File

@ -1,37 +1,40 @@
import 'package:backend_dart/common/extensions.dart';
import 'package:backend_dart/common/secure_hash.dart';
import 'package:backend_dart/domain/entities/user.dart'; import 'package:backend_dart/domain/entities/user.dart';
import 'package:backend_dart/domain/interface/error.dart'; import 'package:backend_dart/domain/interface/error.dart';
import 'package:backend_dart/domain/interface/mapper.dart';
import 'package:backend_dart/infrastructure/persistence/db/model.dart'; import 'package:backend_dart/infrastructure/persistence/db/model.dart';
import 'package:backend_dart/infrastructure/persistence/db/prisma.dart';
import 'package:fpdart/fpdart.dart'; import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
class UserDboMapper implements IMapper<User, UserDbo> { class UserDboMapper {
@override
TaskEither<IError, User> from(UserDbo target) => TaskEither.of(User( TaskEither<IError, User> from(UserDbo target) => TaskEither.of(User(
id: target.id!, id: target.id!,
name: target.name!, name: target.name!,
email: target.email!, email: target.email!,
password: target.password, passwordHash: target.password,
createdAt: target.createdAt, createdAt: target.createdAt,
updatedAt: target.updatedAt, updatedAt: target.updatedAt,
)); ));
@override
TaskEither<IError, List<User>> listFrom(Iterable<UserDbo> targets) { TaskEither<IError, List<User>> listFrom(Iterable<UserDbo> targets) {
return TaskEither.traverseList(targets.toList(), from); return TaskEither.traverseList(targets.toList(), from);
} }
@override TaskEither<IError, UserDboUncheckedUpdateInput> fromUpdateTo(
TaskEither<IError, List<UserDbo>> listTo(Iterable<User> origins) { UserUpdate origin) =>
return TaskEither.traverseList(origins.toList(), to); TaskEither.of(UserDboUncheckedUpdateInput(
} id: PrismaUnion.$1(origin.id),
name: origin.name.let(PrismaUnion.$1),
email: origin.email.let(PrismaUnion.$1),
password: origin.password.let(generateSecureHash).let(PrismaUnion.$1),
));
@override TaskEither<IError, UserDboCreateInput> fromCreateTo(UserCreate origin) =>
TaskEither<IError, UserDbo> to(User origin) => TaskEither.of(UserDbo( TaskEither.of(UserDboCreateInput(
id: origin.id, id: origin.id,
name: origin.name, name: origin.name,
email: origin.email, email: origin.email,
password: origin.password, password: generateSecureHash(origin.password),
createdAt: origin.createdAt,
updatedAt: origin.updatedAt,
)); ));
} }

View File

@ -1,4 +1,4 @@
import 'package:backend_dart/domain/interface/database.dart'; import 'package:backend_dart/domain/data/database.dart';
import 'package:backend_dart/infrastructure/persistence/db/client.dart'; import 'package:backend_dart/infrastructure/persistence/db/client.dart';
import 'package:backend_dart/infrastructure/persistence/prisma_user_data_source.dart'; import 'package:backend_dart/infrastructure/persistence/prisma_user_data_source.dart';

View File

@ -12,36 +12,25 @@ import 'package:uuid/uuid.dart';
import 'db/client.dart'; import 'db/client.dart';
class PrismaUserDataSource implements UserDataSource<User> { class PrismaUserDataSource implements UserDataSource {
final PrismaClient prisma; final PrismaClient prisma;
final UserDboMapper mapper = UserDboMapper(); final UserDboMapper mapper = UserDboMapper();
PrismaUserDataSource(this.prisma); PrismaUserDataSource(this.prisma);
@override @override
TaskEither<IError, User> create(User user) { TaskEither<IError, User> create(UserCreate user) => mapper
return TaskEither<IError, UserDbo>.tryCatch( .fromCreateTo(user)
.flatMap((userDbo) => TaskEither<IError, UserDbo>.tryCatch(
() async { () async {
if (user.password == null) {
throw Exception('Password is required');
}
if (user.email == null) {
throw Exception('Email is required');
}
final createdUser = await prisma.userDbo.create( final createdUser = await prisma.userDbo.create(
data: PrismaUnion.$1(UserDboCreateInput( data: PrismaUnion.$1(userDbo),
id: user.id,
name: user.name!,
email: user.email!,
password: user.password!,
)),
); );
return createdUser; return createdUser;
}, },
(error, _) => AppError.databaseError( (error, _) => AppError.databaseError(
message: 'Failed to create user: ${error.toString()}', message: 'Failed to create user: ${error.toString()}',
), ),
).flatMap(mapper.from); ).flatMap(mapper.from));
}
@override @override
TaskEither<IError, User> findByEmail(String email) { TaskEither<IError, User> findByEmail(String email) {
@ -81,41 +70,36 @@ class PrismaUserDataSource implements UserDataSource<User> {
} }
@override @override
TaskEither<IError, User> update(User user) { TaskEither<IError, User> update(UserUpdate user) {
return mapper return mapper
.to(user) .fromUpdateTo(user)
.flatMap((userDbo) => TaskEither.tryCatch(() async { .flatMap(
(userDbo) => TaskEither.tryCatch(
() async {
// Führe das Update durch // Führe das Update durch
if (userDbo.id == null) { if (userDbo.id == null) {
throw Exception('User ID is required'); throw Exception('User ID is required');
} }
final updatedUser = await prisma.userDbo.update( final updatedUser = await prisma.userDbo.update(
data: PrismaUnion.$2( data: PrismaUnion.$2(userDbo),
UserDboUncheckedUpdateInput( where: UserDboWhereUniqueInput(id: user.id),
id: PrismaUnion.$1(userDbo.id!),
name: userDbo.name != null
? PrismaUnion.$1(userDbo.name!)
: null,
email: userDbo.email != null
? PrismaUnion.$1(userDbo.email!)
: null,
password: userDbo.password != null
? PrismaUnion.$1(userDbo.password!)
: null,
),
),
where: UserDboWhereUniqueInput(id: userDbo.id),
); );
return updatedUser; return updatedUser;
}, },
(error, _) => AppError.databaseError( (error, _) => AppError.databaseError(
message: 'Failed to update user: ${error.toString()}', message: 'Failed to update user: ${error.toString()}',
))) ),
.flatMap(errorOnNull(AppError.notFound( ),
)
.flatMap(
errorOnNull(
AppError.notFound(
'User not found', 'User not found',
))) ),
),
)
.flatMap(mapper.from); .flatMap(mapper.from);
} }

View File

@ -199,7 +199,7 @@ packages:
source: hosted source: hosted
version: "1.11.0" version: "1.11.0"
crypto: crypto:
dependency: transitive dependency: "direct main"
description: description:
name: crypto name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"

View File

@ -21,6 +21,7 @@ dependencies:
json_annotation: ^4.9.0 json_annotation: ^4.9.0
freezed_annotation: ^2.4.4 freezed_annotation: ^2.4.4
uuid: ^4.5.1 uuid: ^4.5.1
crypto: ^3.0.6
dev_dependencies: dev_dependencies:
lints: ^3.0.0 lints: ^3.0.0