This commit is contained in:
2025-01-04 15:10:21 +00:00
parent ea8d6b9b30
commit bdfb08f092
14 changed files with 30 additions and 30 deletions
@@ -0,0 +1,8 @@
import 'package:backend_dart/infrastructure/data/prisma_database.dart';
import 'package:riverpod/riverpod.dart';
final databaseProvider = Provider<PrismaDatabase>((ref) {
// Hier die Datenbankverbindung initialisieren
final database = PrismaDatabase();
return database;
});
File diff suppressed because it is too large Load Diff
+531
View File
@@ -0,0 +1,531 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'model.dart' as _i1;
import 'prisma.dart' as _i2;
class ProjectTaskDbo {
const ProjectTaskDbo({
this.id,
this.name,
this.description,
this.projectId,
this.createdAt,
this.updatedAt,
this.project,
});
factory ProjectTaskDbo.fromJson(Map json) => ProjectTaskDbo(
id: json['id'],
name: json['name'],
description: json['description'],
projectId: json['projectId'],
createdAt: switch (json['createdAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['createdAt']
},
updatedAt: switch (json['updatedAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['updatedAt']
},
project: json['project'] is Map
? _i1.ProjectDbo.fromJson(json['project'])
: null,
);
final String? id;
final String? name;
final String? description;
final String? projectId;
final DateTime? createdAt;
final DateTime? updatedAt;
final _i1.ProjectDbo? project;
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'description': description,
'projectId': projectId,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'project': project?.toJson(),
};
}
class TimeEntryDbo {
const TimeEntryDbo({
this.id,
this.startTime,
this.endTime,
this.description,
this.userId,
this.projectId,
this.createdAt,
this.updatedAt,
this.user,
this.project,
});
factory TimeEntryDbo.fromJson(Map json) => TimeEntryDbo(
id: json['id'],
startTime: switch (json['startTime']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['startTime']
},
endTime: switch (json['endTime']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['endTime']
},
description: json['description'],
userId: json['userId'],
projectId: json['projectId'],
createdAt: switch (json['createdAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['createdAt']
},
updatedAt: switch (json['updatedAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['updatedAt']
},
user: json['user'] is Map ? _i1.UserDbo.fromJson(json['user']) : null,
project: json['project'] is Map
? _i1.ProjectDbo.fromJson(json['project'])
: null,
);
final String? id;
final DateTime? startTime;
final DateTime? endTime;
final String? description;
final String? userId;
final String? projectId;
final DateTime? createdAt;
final DateTime? updatedAt;
final _i1.UserDbo? user;
final _i1.ProjectDbo? project;
Map<String, dynamic> toJson() => {
'id': id,
'startTime': startTime?.toIso8601String(),
'endTime': endTime?.toIso8601String(),
'description': description,
'userId': userId,
'projectId': projectId,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'user': user?.toJson(),
'project': project?.toJson(),
};
}
class ProjectDbo {
const ProjectDbo({
this.id,
this.name,
this.description,
this.clientId,
this.userId,
this.createdAt,
this.updatedAt,
this.tasks,
this.timeEntries,
this.user,
this.$count,
});
factory ProjectDbo.fromJson(Map json) => ProjectDbo(
id: json['id'],
name: json['name'],
description: json['description'],
clientId: json['clientId'],
userId: json['userId'],
createdAt: switch (json['createdAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['createdAt']
},
updatedAt: switch (json['updatedAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['updatedAt']
},
tasks: (json['tasks'] as Iterable?)
?.map((json) => _i1.ProjectTaskDbo.fromJson(json)),
timeEntries: (json['timeEntries'] as Iterable?)
?.map((json) => _i1.TimeEntryDbo.fromJson(json)),
user: json['user'] is Map ? _i1.UserDbo.fromJson(json['user']) : null,
$count: json['_count'] is Map
? _i2.ProjectDboCountOutputType.fromJson(json['_count'])
: null,
);
final String? id;
final String? name;
final String? description;
final String? clientId;
final String? userId;
final DateTime? createdAt;
final DateTime? updatedAt;
final Iterable<_i1.ProjectTaskDbo>? tasks;
final Iterable<_i1.TimeEntryDbo>? timeEntries;
final _i1.UserDbo? user;
final _i2.ProjectDboCountOutputType? $count;
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'description': description,
'clientId': clientId,
'userId': userId,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'tasks': tasks?.map((e) => e.toJson()),
'timeEntries': timeEntries?.map((e) => e.toJson()),
'user': user?.toJson(),
'_count': $count?.toJson(),
};
}
class UserDbo {
const UserDbo({
this.id,
this.name,
this.email,
this.password,
this.createdAt,
this.updatedAt,
this.projects,
this.timeEntries,
this.$count,
});
factory UserDbo.fromJson(Map json) => UserDbo(
id: json['id'],
name: json['name'],
email: json['email'],
password: json['password'],
createdAt: switch (json['createdAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['createdAt']
},
updatedAt: switch (json['updatedAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['updatedAt']
},
projects: (json['projects'] as Iterable?)
?.map((json) => _i1.ProjectDbo.fromJson(json)),
timeEntries: (json['timeEntries'] as Iterable?)
?.map((json) => _i1.TimeEntryDbo.fromJson(json)),
$count: json['_count'] is Map
? _i2.UserDboCountOutputType.fromJson(json['_count'])
: null,
);
final String? id;
final String? name;
final String? email;
final String? password;
final DateTime? createdAt;
final DateTime? updatedAt;
final Iterable<_i1.ProjectDbo>? projects;
final Iterable<_i1.TimeEntryDbo>? timeEntries;
final _i2.UserDboCountOutputType? $count;
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'email': email,
'password': password,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'projects': projects?.map((e) => e.toJson()),
'timeEntries': timeEntries?.map((e) => e.toJson()),
'_count': $count?.toJson(),
};
}
class CreateManyUserDboAndReturnOutputType {
const CreateManyUserDboAndReturnOutputType({
this.id,
this.name,
this.email,
this.password,
this.createdAt,
this.updatedAt,
});
factory CreateManyUserDboAndReturnOutputType.fromJson(Map json) =>
CreateManyUserDboAndReturnOutputType(
id: json['id'],
name: json['name'],
email: json['email'],
password: json['password'],
createdAt: switch (json['createdAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['createdAt']
},
updatedAt: switch (json['updatedAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['updatedAt']
},
);
final String? id;
final String? name;
final String? email;
final String? password;
final DateTime? createdAt;
final DateTime? updatedAt;
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'email': email,
'password': password,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
};
}
class CreateManyProjectDboAndReturnOutputType {
const CreateManyProjectDboAndReturnOutputType({
this.id,
this.name,
this.description,
this.clientId,
this.userId,
this.createdAt,
this.updatedAt,
this.user,
});
factory CreateManyProjectDboAndReturnOutputType.fromJson(Map json) =>
CreateManyProjectDboAndReturnOutputType(
id: json['id'],
name: json['name'],
description: json['description'],
clientId: json['clientId'],
userId: json['userId'],
createdAt: switch (json['createdAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['createdAt']
},
updatedAt: switch (json['updatedAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['updatedAt']
},
user: json['user'] is Map ? _i1.UserDbo.fromJson(json['user']) : null,
);
final String? id;
final String? name;
final String? description;
final String? clientId;
final String? userId;
final DateTime? createdAt;
final DateTime? updatedAt;
final _i1.UserDbo? user;
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'description': description,
'clientId': clientId,
'userId': userId,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'user': user?.toJson(),
};
}
class CreateManyTimeEntryDboAndReturnOutputType {
const CreateManyTimeEntryDboAndReturnOutputType({
this.id,
this.startTime,
this.endTime,
this.description,
this.userId,
this.projectId,
this.createdAt,
this.updatedAt,
this.user,
this.project,
});
factory CreateManyTimeEntryDboAndReturnOutputType.fromJson(Map json) =>
CreateManyTimeEntryDboAndReturnOutputType(
id: json['id'],
startTime: switch (json['startTime']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['startTime']
},
endTime: switch (json['endTime']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['endTime']
},
description: json['description'],
userId: json['userId'],
projectId: json['projectId'],
createdAt: switch (json['createdAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['createdAt']
},
updatedAt: switch (json['updatedAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['updatedAt']
},
user: json['user'] is Map ? _i1.UserDbo.fromJson(json['user']) : null,
project: json['project'] is Map
? _i1.ProjectDbo.fromJson(json['project'])
: null,
);
final String? id;
final DateTime? startTime;
final DateTime? endTime;
final String? description;
final String? userId;
final String? projectId;
final DateTime? createdAt;
final DateTime? updatedAt;
final _i1.UserDbo? user;
final _i1.ProjectDbo? project;
Map<String, dynamic> toJson() => {
'id': id,
'startTime': startTime?.toIso8601String(),
'endTime': endTime?.toIso8601String(),
'description': description,
'userId': userId,
'projectId': projectId,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'user': user?.toJson(),
'project': project?.toJson(),
};
}
class CreateManyProjectTaskDboAndReturnOutputType {
const CreateManyProjectTaskDboAndReturnOutputType({
this.id,
this.name,
this.description,
this.projectId,
this.createdAt,
this.updatedAt,
this.project,
});
factory CreateManyProjectTaskDboAndReturnOutputType.fromJson(Map json) =>
CreateManyProjectTaskDboAndReturnOutputType(
id: json['id'],
name: json['name'],
description: json['description'],
projectId: json['projectId'],
createdAt: switch (json['createdAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['createdAt']
},
updatedAt: switch (json['updatedAt']) {
DateTime value => value,
String value => DateTime.parse(value),
_ => json['updatedAt']
},
project: json['project'] is Map
? _i1.ProjectDbo.fromJson(json['project'])
: null,
);
final String? id;
final String? name;
final String? description;
final String? projectId;
final DateTime? createdAt;
final DateTime? updatedAt;
final _i1.ProjectDbo? project;
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'description': description,
'projectId': projectId,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'project': project?.toJson(),
};
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,53 @@
import 'package:backend_dart/common/extensions.dart';
import 'package:backend_dart/domain/entities/project.dart';
import 'package:backend_dart/domain/errors/error.dart';
import 'package:backend_dart/infrastructure/data/db/model.dart';
import 'package:backend_dart/infrastructure/data/db/prisma.dart';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
class ProjectDboMapper {
TaskEither<IError, Project> fromDbo(ProjectDbo dbo) {
return TaskEither.of(Project(
id: dbo.id!,
name: dbo.name!,
description: dbo.description,
clientId: dbo.clientId,
userId: dbo.userId!,
createdAt: dbo.createdAt!,
updatedAt: dbo.updatedAt!,
));
}
TaskEither<IError, List<Project>> listFrom(Iterable<ProjectDbo> dbos) {
return TaskEither.traverseList(dbos.toList(), fromDbo);
}
TaskEither<IError, ProjectDboCreateInput> fromCreatetoDbo(
ProjectCreate project) {
return TaskEither.of(ProjectDboCreateInput(
id: project.id,
name: project.name,
description: project.description.let(PrismaUnion.$1),
clientId: project.clientId.let(PrismaUnion.$1),
user: UserDboCreateNestedOneWithoutProjectsInput(
connect: UserDboWhereUniqueInput(id: project.userId),
),
));
}
TaskEither<IError, ProjectDboUpdateInput> fromUpdateToDbo(
ProjectUpdate project) {
return TaskEither.of(ProjectDboUpdateInput(
id: PrismaUnion.$1(project.id),
name: project.name.let(PrismaUnion.$1),
description: project.description.let(PrismaUnion.$1),
clientId: project.clientId.let(PrismaUnion.$1),
user: project.userId.let(
(userId) => UserDboUpdateOneRequiredWithoutProjectsNestedInput(
connect: UserDboWhereUniqueInput(id: userId),
),
),
));
}
}
@@ -0,0 +1,52 @@
import 'package:backend_dart/common/extensions.dart';
import 'package:backend_dart/domain/entities/project_task.dart';
import 'package:backend_dart/domain/errors/error.dart';
import 'package:backend_dart/infrastructure/data/db/model.dart';
import 'package:backend_dart/infrastructure/data/db/prisma.dart';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
class ProjectTaskDboMapper {
TaskEither<IError, ProjectTask> from(ProjectTaskDbo target) =>
TaskEither.of(ProjectTask(
id: target.id!,
name: target.name!,
description: target.description,
projectId: target.projectId!,
createdAt: target.createdAt!,
updatedAt: target.updatedAt!,
));
TaskEither<IError, List<ProjectTask>> listFrom(
Iterable<ProjectTaskDbo> targets) {
return TaskEither.traverseList(targets.toList(), from);
}
TaskEither<IError, ProjectTaskDboCreateInput> fromCreateTo(
ProjectTaskCreate origin) =>
TaskEither.of(ProjectTaskDboCreateInput(
id: origin.id,
name: origin.name,
description: origin.description.let(PrismaUnion.$1),
project: ProjectDboCreateNestedOneWithoutTasksInput(
connect: ProjectDboWhereUniqueInput(
id: origin.projectId,
),
),
));
TaskEither<IError, ProjectTaskDboUpdateInput> fromUpdateTo(
ProjectTaskUpdate origin) =>
TaskEither.of(ProjectTaskDboUpdateInput(
id: PrismaUnion.$1(origin.id),
name: origin.name?.let(PrismaUnion.$1),
description: origin.description?.let(PrismaUnion.$1),
project: origin.projectId?.let(
(projectId) => ProjectDboUpdateOneRequiredWithoutTasksNestedInput(
connect: ProjectDboWhereUniqueInput(
id: projectId,
),
),
),
));
}
@@ -0,0 +1,69 @@
import 'package:backend_dart/common/extensions.dart';
import 'package:backend_dart/domain/entities/time_entry.dart';
import 'package:backend_dart/domain/errors/error.dart';
import 'package:backend_dart/infrastructure/data/db/model.dart';
import 'package:backend_dart/infrastructure/data/db/prisma.dart';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
class TimeEntryDboMapper {
TaskEither<IError, TimeEntry> from(TimeEntryDbo target) => TaskEither.of(
TimeEntry(
id: target.id!,
startTime: target.startTime!,
endTime: target.endTime,
description: target.description,
userId: target.userId!,
projectId: target.projectId!,
createdAt: target.createdAt!,
updatedAt: target.updatedAt!,
),
);
TaskEither<IError, List<TimeEntry>> listFrom(Iterable<TimeEntryDbo> targets) {
return TaskEither.traverseList(targets.toList(), from);
}
TaskEither<IError, TimeEntryDboCreateInput> fromCreateTo(
TimeEntryCreate origin) =>
TaskEither.of(TimeEntryDboCreateInput(
id: origin.id,
startTime: origin.startTime,
endTime: origin.endTime.let(PrismaUnion.$1),
description: origin.description.let(PrismaUnion.$1),
user: UserDboCreateNestedOneWithoutTimeEntriesInput(
connect: UserDboWhereUniqueInput(
id: origin.userId,
),
),
project: ProjectDboCreateNestedOneWithoutTimeEntriesInput(
connect: ProjectDboWhereUniqueInput(
id: origin.projectId,
),
),
));
TaskEither<IError, TimeEntryDboUpdateInput> fromUpdateTo(
TimeEntryUpdate origin) =>
TaskEither.of(TimeEntryDboUpdateInput(
id: PrismaUnion.$1(origin.id),
startTime: origin.startTime?.let(PrismaUnion.$1),
endTime: origin.endTime?.let(PrismaUnion.$1),
description: origin.description?.let(PrismaUnion.$1),
user: origin.userId?.let(
(userId) => UserDboUpdateOneRequiredWithoutTimeEntriesNestedInput(
connect: UserDboWhereUniqueInput(
id: userId,
),
),
),
project: origin.projectId?.let(
(projectId) =>
ProjectDboUpdateOneRequiredWithoutTimeEntriesNestedInput(
connect: ProjectDboWhereUniqueInput(
id: projectId,
),
),
),
));
}
@@ -0,0 +1,39 @@
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/errors/error.dart';
import 'package:backend_dart/infrastructure/data/db/model.dart';
import 'package:backend_dart/infrastructure/data/db/prisma.dart';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
class UserDboMapper {
TaskEither<IError, User> from(UserDbo target) => TaskEither.of(User(
id: target.id!,
name: target.name!,
email: target.email!,
passwordHash: target.password,
createdAt: target.createdAt,
updatedAt: target.updatedAt,
));
TaskEither<IError, List<User>> listFrom(Iterable<UserDbo> targets) {
return TaskEither.traverseList(targets.toList(), from);
}
TaskEither<IError, UserDboUpdateInput> fromUpdateTo(UserUpdate origin) =>
TaskEither.of(UserDboUpdateInput(
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),
));
TaskEither<IError, UserDboCreateInput> fromCreateTo(UserCreate origin) =>
TaskEither.of(UserDboCreateInput(
id: origin.id,
name: origin.name,
email: origin.email,
password: generateSecureHash(origin.password),
));
}
@@ -0,0 +1,38 @@
import 'package:backend_dart/domain/data/database.dart';
import 'package:backend_dart/domain/data/project_data_source.dart';
import 'package:backend_dart/domain/data/project_task_data_source.dart';
import 'package:backend_dart/domain/data/time_entry_data_source.dart';
import 'package:backend_dart/infrastructure/data/db/client.dart';
import 'package:backend_dart/infrastructure/data/prisma_project_data_source.dart';
import 'package:backend_dart/infrastructure/data/prisma_project_task_data_source.dart';
import 'package:backend_dart/infrastructure/data/prisma_time_entry_data_source.dart';
import 'package:backend_dart/infrastructure/data/prisma_user_data_source.dart';
class PrismaDatabase implements IDatabase {
final prisma = PrismaClient();
late final PrismaUserDataSource _users;
late final TimeEntryDataSource _timeEntries;
late final ProjectTaskDataSource _tasks;
late final ProjectDataSource _projects;
PrismaDatabase() {
_users = PrismaUserDataSource(prisma);
_timeEntries = PrismaTimeEntryDataSource(prisma);
_tasks = PrismaProjectTaskDataSource(prisma);
_projects = PrismaProjectDataSource(prisma);
print('Database initialized');
}
@override
get users => _users;
@override
get timeEntries => _timeEntries;
@override
get tasks => _tasks;
@override
get projects => _projects;
@override
Future<void> close() {
return Future.value();
}
}
@@ -0,0 +1,148 @@
import 'package:backend_dart/common/error_on_null.dart';
import 'package:backend_dart/domain/data/project_data_source.dart';
import 'package:backend_dart/domain/entities/project.dart';
import 'package:backend_dart/domain/errors/app_error.dart';
import 'package:backend_dart/domain/errors/error.dart';
import 'package:backend_dart/infrastructure/data/db/client.dart';
import 'package:backend_dart/infrastructure/data/db/model.dart';
import 'package:backend_dart/infrastructure/data/db/prisma.dart';
import 'package:backend_dart/infrastructure/data/mapper/project_dbo_mapper.dart';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
import 'package:uuid/uuid.dart';
class PrismaProjectDataSource implements ProjectDataSource {
final PrismaClient prisma;
final ProjectDboMapper mapper = ProjectDboMapper();
PrismaProjectDataSource(this.prisma);
@override
TaskEither<IError, Project> create(ProjectCreate project) {
return mapper
.fromCreatetoDbo(project)
.flatMap((projectDbo) => TaskEither.tryCatch(
() async {
return await prisma.projectDbo.create(
data: PrismaUnion.$1(projectDbo),
);
},
(error, _) => AppError.databaseError(
message: 'Failed to create project: ${error.toString()}',
),
))
.flatMap(mapper.fromDbo);
}
@override
TaskEither<IError, Project> findById(String id) {
return TaskEither<IError, ProjectDbo?>.tryCatch(
() async {
final project = await prisma.projectDbo
.findUnique(where: ProjectDboWhereUniqueInput(id: id));
return project;
},
(error, _) => AppError.databaseError(
message: 'Failed to find project by ID: ${error.toString()}',
),
)
.flatMap(
errorOnNull(AppError.notFound('Project with ID $id not found')))
.flatMap(mapper.fromDbo);
}
@override
TaskEither<IError, List<Project>> findByUserId(String userId) {
return TaskEither<IError, Iterable<ProjectDbo>>.tryCatch(
() async {
final projects = await prisma.projectDbo.findMany(
where: ProjectDboWhereInput(
userId: PrismaUnion.$1(StringFilter(
equals: PrismaUnion.$1(userId),
))),
);
return projects;
},
(error, _) => AppError.databaseError(
message: 'Failed to find projects by user ID: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, Project> update(ProjectUpdate project) {
return mapper
.fromUpdateToDbo(project)
.flatMap(
(projectDbo) => TaskEither.tryCatch(
() async {
return await prisma.projectDbo.update(
data: PrismaUnion.$1(projectDbo),
where: ProjectDboWhereUniqueInput(id: project.id),
);
},
(error, _) => AppError.databaseError(
message: 'Failed to update project: ${error.toString()}',
),
),
)
.flatMap(
errorOnNull(
AppError.notFound(
'Project with ID ${project.id} not found',
),
),
)
.flatMap(mapper.fromDbo);
}
@override
TaskEither<IError, Project> delete(String id) {
return TaskEither<IError, ProjectDbo?>.tryCatch(
() async {
return await prisma.projectDbo
.delete(where: ProjectDboWhereUniqueInput(id: id));
},
(error, _) => AppError.databaseError(
message: 'Failed to delete project: ${error.toString()}',
),
)
.flatMap(
errorOnNull(
AppError.notFound(
'Project with ID $id not found',
),
),
)
.flatMap(mapper.fromDbo);
}
@override
TaskEither<IError, List<Project>> findAll() {
return TaskEither<IError, Iterable<ProjectDbo>>.tryCatch(
() async => await prisma.projectDbo.findMany(),
(error, _) => AppError.databaseError(
message: 'Failed to fetch all projects: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, String> generateId() {
return TaskEither.tryCatch(
() async {
var uuid = Uuid();
do {
final id = uuid.v4();
final project = await prisma.projectDbo.findUnique(
where: ProjectDboWhereUniqueInput(id: id),
);
if (project == null) return id;
} while (true);
},
(error, _) => AppError.databaseError(
message: 'Failed to generate ID: ${error.toString()}',
),
);
}
}
@@ -0,0 +1,139 @@
import 'package:backend_dart/common/error_on_null.dart';
import 'package:backend_dart/domain/data/project_task_data_source.dart';
import 'package:backend_dart/domain/entities/project_task.dart';
import 'package:backend_dart/domain/errors/app_error.dart';
import 'package:backend_dart/domain/errors/error.dart';
import 'package:backend_dart/infrastructure/data/db/client.dart';
import 'package:backend_dart/infrastructure/data/db/model.dart';
import 'package:backend_dart/infrastructure/data/db/prisma.dart';
import 'package:backend_dart/infrastructure/data/mapper/project_task_dbo_mapper.dart';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
import 'package:uuid/uuid.dart';
class PrismaProjectTaskDataSource implements ProjectTaskDataSource {
final PrismaClient prisma;
final ProjectTaskDboMapper mapper = ProjectTaskDboMapper();
PrismaProjectTaskDataSource(this.prisma);
@override
TaskEither<IError, ProjectTask> create(ProjectTaskCreate task) =>
mapper.fromCreateTo(task).flatMap(
(taskDbo) => TaskEither<IError, ProjectTaskDbo>.tryCatch(
() async {
final createdTask = await prisma.projectTaskDbo.create(
data: PrismaUnion.$1(taskDbo),
);
return createdTask;
},
(error, _) => AppError.databaseError(
message: 'Failed to create project task: ${error.toString()}',
),
).flatMap(mapper.from),
);
@override
TaskEither<IError, ProjectTask> findById(String id) {
return TaskEither<IError, ProjectTaskDbo?>.tryCatch(
() async {
final task = await prisma.projectTaskDbo
.findUnique(where: ProjectTaskDboWhereUniqueInput(id: id));
return task;
},
(error, _) => AppError.databaseError(
message: 'Failed to find project task by ID: ${error.toString()}',
),
)
.flatMap(errorOnNull(AppError.notFound(
"Project task with id $id not found",
)))
.flatMap(mapper.from);
}
@override
TaskEither<IError, List<ProjectTask>> findByProjectId(String projectId) {
return TaskEither<IError, Iterable<ProjectTaskDbo>>.tryCatch(
() async => await prisma.projectTaskDbo.findMany(
where: ProjectTaskDboWhereInput(projectId: PrismaUnion.$2(projectId)),
),
(error, _) => AppError.databaseError(
message:
'Failed to fetch tasks for project $projectId: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, ProjectTask> update(ProjectTaskUpdate task) => mapper
.fromUpdateTo(task)
.flatMap(
(taskDbo) => TaskEither.tryCatch(
() async {
final updatedTask = await prisma.projectTaskDbo.update(
data: PrismaUnion.$1(taskDbo),
where: ProjectTaskDboWhereUniqueInput(id: task.id),
);
return updatedTask;
},
(error, _) => AppError.databaseError(
message: 'Failed to update project task: ${error.toString()}',
),
),
)
.flatMap(
errorOnNull(AppError.notFound("Project task not found")),
)
.flatMap(mapper.from);
@override
TaskEither<IError, ProjectTask> delete(String id) {
return TaskEither<IError, ProjectTaskDbo?>.tryCatch(
() async {
return await prisma.projectTaskDbo.delete(
where: ProjectTaskDboWhereUniqueInput(id: id),
);
},
(error, _) => AppError.databaseError(
message: 'Failed to delete project task: ${error.toString()}',
),
)
.flatMap(
errorOnNull(
AppError.notFound(
'Project task with ID $id not found',
),
),
)
.flatMap(mapper.from);
}
@override
TaskEither<IError, List<ProjectTask>> findAll() {
return TaskEither<IError, Iterable<ProjectTaskDbo>>.tryCatch(
() async => await prisma.projectTaskDbo.findMany(),
(error, _) => AppError.databaseError(
message: 'Failed to fetch all project tasks: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, String> generateId() {
return TaskEither.tryCatch(
() async {
var uuid = Uuid();
do {
final id = uuid.v4();
final task = await prisma.projectTaskDbo.findUnique(
where: ProjectTaskDboWhereUniqueInput(id: id),
);
if (task == null) return id;
} while (true);
},
(error, _) => AppError.databaseError(
message: 'Failed to generate ID: ${error.toString()}',
),
);
}
}
@@ -0,0 +1,150 @@
import 'package:backend_dart/common/error_on_null.dart';
import 'package:backend_dart/domain/data/time_entry_data_source.dart';
import 'package:backend_dart/domain/entities/time_entry.dart';
import 'package:backend_dart/domain/errors/app_error.dart';
import 'package:backend_dart/domain/errors/error.dart';
import 'package:backend_dart/infrastructure/data/db/client.dart';
import 'package:backend_dart/infrastructure/data/db/model.dart';
import 'package:backend_dart/infrastructure/data/db/prisma.dart';
import 'package:backend_dart/infrastructure/data/mapper/time_entry_dbo_mapper.dart';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
import 'package:uuid/uuid.dart';
class PrismaTimeEntryDataSource implements TimeEntryDataSource {
final PrismaClient prisma;
final TimeEntryDboMapper mapper = TimeEntryDboMapper();
PrismaTimeEntryDataSource(this.prisma);
@override
TaskEither<IError, TimeEntry> create(TimeEntryCreate timeEntry) =>
mapper.fromCreateTo(timeEntry).flatMap(
(timeEntryDbo) => TaskEither<IError, TimeEntryDbo>.tryCatch(
() async {
final createdEntry = await prisma.timeEntryDbo.create(
data: PrismaUnion.$1(timeEntryDbo),
);
return createdEntry;
},
(error, _) => AppError.databaseError(
message: 'Failed to create time entry: ${error.toString()}',
),
).flatMap(mapper.from),
);
@override
TaskEither<IError, TimeEntry> findById(String id) {
return TaskEither<IError, TimeEntryDbo?>.tryCatch(
() async {
final timeEntry = await prisma.timeEntryDbo
.findUnique(where: TimeEntryDboWhereUniqueInput(id: id));
return timeEntry;
},
(error, _) => AppError.databaseError(
message: 'Failed to find time entry by ID: ${error.toString()}',
),
)
.flatMap(errorOnNull(AppError.notFound(
"Time entry with id $id not found",
)))
.flatMap(mapper.from);
}
@override
TaskEither<IError, List<TimeEntry>> findByUserId(String userId) {
return TaskEither<IError, Iterable<TimeEntryDbo>>.tryCatch(
() async => await prisma.timeEntryDbo.findMany(
where: TimeEntryDboWhereInput(userId: PrismaUnion.$2(userId)),
),
(error, _) => AppError.databaseError(
message:
'Failed to fetch time entries for user $userId: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, List<TimeEntry>> findByProjectId(String projectId) {
return TaskEither<IError, Iterable<TimeEntryDbo>>.tryCatch(
() async => await prisma.timeEntryDbo.findMany(
where: TimeEntryDboWhereInput(projectId: PrismaUnion.$2(projectId)),
),
(error, _) => AppError.databaseError(
message:
'Failed to fetch time entries for project $projectId: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, TimeEntry> update(TimeEntryUpdate timeEntry) => mapper
.fromUpdateTo(timeEntry)
.flatMap(
(timeEntryDbo) => TaskEither.tryCatch(
() async {
final updatedEntry = await prisma.timeEntryDbo.update(
data: PrismaUnion.$1(timeEntryDbo),
where: TimeEntryDboWhereUniqueInput(id: timeEntry.id),
);
return updatedEntry;
},
(error, _) => AppError.databaseError(
message: 'Failed to update time entry: ${error.toString()}',
),
),
)
.flatMap(
errorOnNull(AppError.notFound("Time entry not found")),
)
.flatMap(mapper.from);
@override
TaskEither<IError, TimeEntry> delete(String id) {
return TaskEither<IError, TimeEntryDbo?>.tryCatch(
() async {
return await prisma.timeEntryDbo.delete(
where: TimeEntryDboWhereUniqueInput(id: id),
);
},
(error, _) => AppError.databaseError(
message: 'Failed to delete time entry: ${error.toString()}',
),
)
.flatMap(
errorOnNull(AppError.notFound(
"Time entry with id $id not found",
)),
)
.flatMap(mapper.from);
}
@override
TaskEither<IError, List<TimeEntry>> findAll() {
return TaskEither<IError, Iterable<TimeEntryDbo>>.tryCatch(
() async => await prisma.timeEntryDbo.findMany(),
(error, _) => AppError.databaseError(
message: 'Failed to fetch all time entries: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, String> generateId() {
return TaskEither.tryCatch(
() async {
var uuid = Uuid();
do {
final id = uuid.v4();
final entry = await prisma.timeEntryDbo.findUnique(
where: TimeEntryDboWhereUniqueInput(id: id),
);
if (entry == null) return id;
} while (true);
},
(error, _) => AppError.databaseError(
message: 'Failed to generate ID: ${error.toString()}',
),
);
}
}
@@ -0,0 +1,163 @@
import 'package:backend_dart/common/error_on_null.dart';
import 'package:backend_dart/domain/data/user_data_source.dart';
import 'package:backend_dart/domain/entities/user.dart';
import 'package:backend_dart/domain/errors/app_error.dart';
import 'package:backend_dart/domain/errors/error.dart';
import 'package:backend_dart/infrastructure/data/db/model.dart';
import 'package:backend_dart/infrastructure/data/db/prisma.dart';
import 'package:backend_dart/infrastructure/data/mapper/user_dbo_mapper.dart';
import 'package:fpdart/fpdart.dart';
import 'package:orm/orm.dart';
import 'package:uuid/uuid.dart';
import 'db/client.dart';
class PrismaUserDataSource implements UserDataSource {
final PrismaClient prisma;
final UserDboMapper mapper = UserDboMapper();
PrismaUserDataSource(this.prisma);
@override
TaskEither<IError, User> create(UserCreate user) => mapper
.fromCreateTo(user)
.flatMap((userDbo) => TaskEither<IError, UserDbo>.tryCatch(
() async {
final createdUser = await prisma.userDbo.create(
data: PrismaUnion.$1(userDbo),
);
return createdUser;
},
(error, _) => AppError.databaseError(
message: 'Failed to create user: ${error.toString()}',
),
).flatMap(mapper.from));
@override
TaskEither<IError, User> findByEmail(String email) {
return TaskEither<IError, UserDbo?>.tryCatch(
() async {
final user = await prisma.userDbo
.findUnique(where: UserDboWhereUniqueInput(email: email));
if (user == null) return null;
return user;
},
(error, _) => AppError.databaseError(
message: 'Failed to find user by email: ${error.toString()}',
),
)
.flatMap(
errorOnNull(
AppError.notFound(
'User with email $email found',
),
),
)
.flatMap(mapper.from);
}
@override
TaskEither<IError, User> findById(String id) {
return TaskEither<IError, UserDbo?>.tryCatch(
() async {
final user = await prisma.userDbo
.findUnique(where: UserDboWhereUniqueInput(id: id));
return user;
},
(error, _) => AppError.databaseError(
message: 'Failed to find user by ID: ${error.toString()}',
),
)
.flatMap(
errorOnNull(
AppError.notFound(
"User with id $id not found",
),
),
)
.flatMap(mapper.from);
}
@override
TaskEither<IError, User> update(UserUpdate user) {
return mapper
.fromUpdateTo(user)
.flatMap(
(userDbo) => TaskEither.tryCatch(
() async {
// Führe das Update durch
if (userDbo.id == null) {
throw Exception('User ID is required');
}
final updatedUser = await prisma.userDbo.update(
data: PrismaUnion.$1(userDbo),
where: UserDboWhereUniqueInput(id: user.id),
);
return updatedUser;
},
(error, _) => AppError.databaseError(
message: 'Failed to update user: ${error.toString()}',
),
),
)
.flatMap(
errorOnNull(
AppError.notFound(
'User not found',
),
),
)
.flatMap(mapper.from);
}
@override
TaskEither<IError, User> delete(String id) {
return TaskEither<IError, UserDbo?>.tryCatch(
() async {
return await prisma.userDbo
.delete(where: UserDboWhereUniqueInput(id: id));
},
(error, _) => AppError.databaseError(
message: 'Failed to delete user: ${error.toString()}',
),
)
.flatMap(
errorOnNull(
AppError.notFound(
'User not found',
),
),
)
.flatMap(mapper.from);
}
@override
TaskEither<IError, List<User>> findAll() {
return TaskEither<IError, Iterable<UserDbo>>.tryCatch(
() async => await prisma.userDbo.findMany(),
(error, _) => AppError.databaseError(
message: 'Failed to fetch all users: ${error.toString()}',
),
).flatMap(mapper.listFrom);
}
@override
TaskEither<IError, String> generateId() {
return TaskEither.tryCatch(
() async {
var uuid = Uuid();
do {
final id = uuid.v4();
final user = await prisma.userDbo.findUnique(
where: UserDboWhereUniqueInput(id: id),
);
if (user == null) return id;
} while (true);
},
(error, _) => AppError.databaseError(
message: 'Failed to generate ID: ${error.toString()}',
),
);
}
}