Skip to content

Commit

Permalink
feat: remove s3
Browse files Browse the repository at this point in the history
  • Loading branch information
solufa committed May 11, 2024
1 parent e65cfaa commit ad11fd8
Show file tree
Hide file tree
Showing 14 changed files with 777 additions and 3,711 deletions.
5 changes: 0 additions & 5 deletions server/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ API_ORIGIN=http://localhost:31577
CORS_ORIGIN=http://localhost:3000
FIREBASE_AUTH_EMULATOR_HOST=localhost:9099
FIREBASE_SERVER_KEY={}
S3_ENDPOINT=http://localhost:9000
S3_BUCKET=app
S3_ACCESS_KEY=minio
S3_SECRET_KEY=password
S3_REGION=ap-northeast-1
DATABASE_URL=postgresql://root:root@localhost:5432/app
TEST_DATABASE_URL=postgresql://root:root@localhost:5432/test
MINIO_ROOT_USER=minio
Expand Down
3 changes: 1 addition & 2 deletions server/api/@types/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ export type TaskEntity = {
label: string;
done: boolean;
createdTime: number;
image: { url: string; s3Key: string } | undefined;
author: { id: UserId; displayName: string | undefined };
};

export type TaskCreateVal = { label: string; image?: Blob };
export type TaskCreateVal = { label: string };

export type TaskUpdateVal = { taskId: Maybe<TaskId>; label?: string; done?: boolean };
1 change: 0 additions & 1 deletion server/api/private/tasks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export type Methods = DefineMethods<{
};

post: {
reqFormat: FormData;
reqBody: TaskCreateVal;
resBody: TaskEntity;
};
Expand Down
6 changes: 0 additions & 6 deletions server/domain/task/model/taskEntity.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import type { MultipartFile } from '@fastify/multipart';
import type { DeletableTaskId } from 'api/@types/brandedId';
import type { TaskEntity } from 'api/@types/task';
import type { S3PutParams } from 'service/s3Client';

export type TaskCreateServerVal = { label: string; image?: MultipartFile };

export type TaskSaveVal = { task: TaskEntity; s3Params?: S3PutParams };

export type TaskDeleteVal = { deletableId: DeletableTaskId; task: TaskEntity };
24 changes: 6 additions & 18 deletions server/domain/task/model/taskMethod.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,24 @@
import type { TaskEntity, TaskUpdateVal } from 'api/@types/task';
import type { TaskCreateVal, TaskEntity, TaskUpdateVal } from 'api/@types/task';
import type { UserEntity } from 'api/@types/user';
import assert from 'assert';
import { randomUUID } from 'crypto';
import { deletableTaskIdParser, taskIdParser } from 'service/idParsers';
import { s3 } from 'service/s3Client';
import type { TaskCreateServerVal, TaskDeleteVal, TaskSaveVal } from './taskEntity';
import type { TaskDeleteVal } from './taskEntity';

export const taskMethod = {
create: async (user: UserEntity, val: TaskCreateServerVal): Promise<TaskSaveVal> => {
const task: TaskEntity = {
create: async (user: UserEntity, val: TaskCreateVal): Promise<TaskEntity> => {
return {
id: taskIdParser.parse(randomUUID()),
done: false,
label: val.label,
image: undefined,
createdTime: Date.now(),
author: { id: user.id, displayName: user.displayName },
};

if (val.image === undefined) return { task };

const s3Key = `tasks/images/${randomUUID()}.${val.image.filename.split('.').at(-1)}`;
const url = await s3.getSignedUrl(s3Key);

return {
task: { ...task, image: { s3Key, url } },
s3Params: { key: s3Key, data: val.image },
};
},
update: (user: UserEntity, task: TaskEntity, val: TaskUpdateVal): TaskSaveVal => {
update: (user: UserEntity, task: TaskEntity, val: TaskUpdateVal): TaskEntity => {
assert(user.id === task.author.id);

return { task: { ...task, ...val } };
return { ...task, ...val };
},
delete: (user: UserEntity, task: TaskEntity): TaskDeleteVal => {
assert(user.id === task.author.id);
Expand Down
25 changes: 10 additions & 15 deletions server/domain/task/repository/taskCommand.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import type { Prisma } from '@prisma/client';
import { s3 } from 'service/s3Client';
import type { TaskDeleteVal, TaskSaveVal } from '../model/taskEntity';
import type { TaskEntity } from 'api/@types/task';
import type { TaskDeleteVal } from '../model/taskEntity';

export const taskCommand = {
save: async (tx: Prisma.TransactionClient, val: TaskSaveVal): Promise<void> => {
if (val.s3Params !== undefined) await s3.put(val.s3Params);

save: async (tx: Prisma.TransactionClient, task: TaskEntity): Promise<void> => {
await tx.task.upsert({
where: { id: val.task.id },
update: { label: val.task.label, done: val.task.done, imageKey: val.task.image?.s3Key },
where: { id: task.id },
update: { label: task.label, done: task.done },
create: {
id: val.task.id,
label: val.task.label,
done: val.task.done,
imageKey: val.task.image?.s3Key,
createdAt: new Date(val.task.createdTime),
authorId: val.task.author.id,
id: task.id,
label: task.label,
done: task.done,
createdAt: new Date(task.createdTime),
authorId: task.author.id,
},
});
},
delete: async (tx: Prisma.TransactionClient, val: TaskDeleteVal): Promise<void> => {
await tx.task.delete({ where: { id: val.deletableId } });

if (val.task.image !== undefined) await s3.delete(val.task.image.s3Key);
},
};
5 changes: 0 additions & 5 deletions server/domain/task/repository/taskQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@ import type { Prisma, Task, User } from '@prisma/client';
import type { Maybe, TaskId, UserId } from 'api/@types/brandedId';
import type { TaskEntity } from 'api/@types/task';
import { taskIdParser, userIdParser } from 'service/idParsers';
import { s3 } from 'service/s3Client';
import { depend } from 'velona';

const toModel = async (prismaTask: Task & { Author: User }): Promise<TaskEntity> => ({
id: taskIdParser.parse(prismaTask.id),
label: prismaTask.label,
done: prismaTask.done,
image:
prismaTask.imageKey === null
? undefined
: { url: await s3.getSignedUrl(prismaTask.imageKey), s3Key: prismaTask.imageKey },
author: {
id: userIdParser.parse(prismaTask.authorId),
displayName: prismaTask.Author.displayName ?? undefined,
Expand Down
9 changes: 2 additions & 7 deletions server/domain/task/service/taskValidator.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { multipartFileValidator } from 'api/$relay';
import type { TaskUpdateVal } from 'api/@types/task';
import type { TaskCreateVal, TaskUpdateVal } from 'api/@types/task';
import { taskIdParser } from 'service/idParsers';
import { z } from 'zod';
import type { TaskCreateServerVal } from '../model/taskEntity';

export const taskValidator = {
taskCreate: z.object({
label: z.string(),
image: multipartFileValidator().optional(),
}) satisfies z.ZodType<TaskCreateServerVal>,
taskCreate: z.object({ label: z.string() }) satisfies z.ZodType<TaskCreateVal>,
taskUpdate: z.object({
taskId: taskIdParser,
label: z.string().optional(),
Expand Down
9 changes: 4 additions & 5 deletions server/domain/task/useCase/taskUseCase.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import type { Maybe, TaskId } from 'api/@types/brandedId';
import type { TaskEntity, TaskUpdateVal } from 'api/@types/task';
import type { TaskCreateVal, TaskEntity, TaskUpdateVal } from 'api/@types/task';
import type { UserEntity } from 'api/@types/user';
import { transaction } from 'service/prismaClient';
import type { TaskCreateServerVal } from '../model/taskEntity';
import { taskMethod } from '../model/taskMethod';
import { taskCommand } from '../repository/taskCommand';
import { taskQuery } from '../repository/taskQuery';

export const taskUseCase = {
create: (user: UserEntity, val: TaskCreateServerVal): Promise<TaskEntity> =>
create: (user: UserEntity, val: TaskCreateVal): Promise<TaskEntity> =>
transaction('RepeatableRead', async (tx) => {
const created = await taskMethod.create(user, val);

await taskCommand.save(tx, created);

return created.task;
return created;
}),
update: (user: UserEntity, val: TaskUpdateVal): Promise<TaskEntity> =>
transaction('RepeatableRead', async (tx) => {
Expand All @@ -23,7 +22,7 @@ export const taskUseCase = {

await taskCommand.save(tx, updated);

return updated.task;
return updated;
}),
delete: (user: UserEntity, taskId: Maybe<TaskId>): Promise<TaskEntity> =>
transaction('RepeatableRead', async (tx) => {
Expand Down
Loading

0 comments on commit ad11fd8

Please sign in to comment.