This repository was archived by the owner on Jan 5, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathUpdate.ts
92 lines (82 loc) · 2.66 KB
/
Update.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { flow } from "@effect-ts/core/Function"
import * as T from "@effect-ts-app/core/Effect"
import * as O from "@effect-ts-app/core/Option"
import { typedKeysOf } from "@effect-ts-app/core/utils"
import { handle } from "@effect-ts-app/infra/app"
import { Tasks } from "@effect-ts-demo/todo-client"
import {
OptionalEditablePersonalTaskProps,
OptionalEditableTaskProps,
Task,
TaskAudits,
TaskEvents,
UserId,
} from "@effect-ts-demo/todo-types"
import { TodoContext, UserSVC } from "@/services"
import { TaskAuth } from "./_access"
export default handle(Tasks.Update)(({ id, ...input }) =>
T.gen(function* ($) {
const { Lists, Tasks } = yield* $(TodoContext.TodoContext)
const user = yield* $(UserSVC.UserProfile)
const taskLists = yield* $(Lists.allLists(user.id))
const initialTask = yield* $(Tasks.get(id))
const [task, events] = yield* $(
TaskAuth(taskLists).access_(initialTask, user.id, updateTask(input, user.id))
)
// TODO: Context should perhaps know if changed, and should use a transaction
yield* $(
TodoContext.saveTaskAndPublishEvents(events)["|>"](T.ifDiff(task, initialTask))
)
})
)
export function updateTask(
input: OptionalEditableTaskProps & OptionalEditablePersonalTaskProps,
userId: UserId
) {
return (task: Task) => updateTask_(task, userId, input)
}
export function updateTask_(
task: Task,
userId: UserId,
{
myDay,
reminder,
...input
}: OptionalEditableTaskProps & OptionalEditablePersonalTaskProps
) {
const events: TaskEvents.Events[] = []
const hasTaskChanges = typedKeysOf(input).some((x) => typeof input[x] !== "undefined")
if (hasTaskChanges) {
task = task["|>"](Task.update(input))
// Derive audits.
// NOTE: Obviously it would be easier if this was a Task Based approach, where each change would be specialised, instead of allowing to change all the editable props
// TODO: As adding an attachment is actually a special purpose use case, we should extract it to it's own use case + route.
if (input.attachment) {
task = input.attachment["|>"](
O.fold(
// TODO: Attachment removed?
() => task,
flow(
TaskAudits.TaskFileAdded.fromAttachment({ userId }),
Task.addAudit.r(task)
)
)
)
}
}
const userChanges = { myDay, reminder }
const hasUserChanges = typedKeysOf(userChanges).some(
(x) => typeof userChanges[x] !== "undefined"
)
if (hasTaskChanges || hasUserChanges) {
events.push(
new TaskEvents.TaskUpdated({
taskId: task.id,
userId,
changes: input,
userChanges,
})
)
}
return [task, events] as const
}