Skip to content

Instantly share code, notes, and snippets.

@patroza
Last active May 24, 2021 08:52
Show Gist options
  • Save patroza/8f2d634b23e6efa01a244e9067bfe249 to your computer and use it in GitHub Desktop.
Save patroza/8f2d634b23e6efa01a244e9067bfe249 to your computer and use it in GitHub Desktop.
// 3. Presentation/Root
const start = () => {
const getCompletedTodosRequestHandler = async (ctx) => {
const result = await getCompletedTodosResolved(ctx.params.id)
ctx.body = JSON.stringify(result)
}
const completeTodoRequestHandler = async (ctx) => {
await completeTodoResolved(ctx.params.id)
ctx.status = 204
}
const url = "some-url"
const getTodoApiResolved = getTodoApi(url)
const getTodosApiResolved = getTodosApi(url)
const saveTodoResolved = saveTodoApi(url)
const getCompletedTodosResolved = getCompletedTodos(getTodosApiResolved)
const completeTodoResolved = completeTodo(getTodoApiResolved, saveTodoResolved)
app.get("/users/:id/todos", getCompletedTodosRequestHandler)
app.post("/todos/:id/complete", completeTodoRequestHandler)
app.listen(3000)
}
//start()
// 3. Infra
let todoStubs = [
{ id: 1, title: "Test", isCompleted: false, updatedAt: new Date(2020, 1, 1)},
{ id: 2, title: "Test 2", isCompleted: true, updatedAt: new Date(2020, 1, 1)},
]
const getTodosApi = (url: string) => async function (userId: number): Promise<Todo[]> {
return todoStubs
}
const getTodoApi = (url: string) => async function (todoId: number): Promise<Todo | undefined> {
return todoStubs.find(x => x.id === todoId)
}
const saveTodoApi = (url: string) => async function (todo: Todo): Promise<void> {
todoStubs = todoStubs.filter(x => x.id === todo.id).concat([todo])
}
// 2. Application
const getCompletedTodos = (getTodos: ReturnType<typeof getTodosApi>) =>
async function (userId: number): Promise<TodoView> {
const allTodos = await getTodos(userId)
const completedTodos = allTodos.filter(x => x.isCompleted)
return {
items: completedTodos,
userId,
}
}
const completeTodo = (getTodo: ReturnType<typeof getTodoApi>, saveTodo: ReturnType<typeof saveTodoApi>) =>
async function (todoId: number): Promise<void> {
const todo = await getTodo(todoId)
const updatedTodo = complete(todo, new Date())
await saveTodo(updatedTodo)
}
type TodoView = {
items: Todo[]
userId: number
}
// 1. Domain
type Todo = {
readonly id: number
readonly title: string
readonly isCompleted: boolean
readonly updatedAt: Date
}
const complete = (todo: Todo, currentDate: Date) => {
if (todo.isCompleted) {
throw new Error("already completed")
}
return {
...todo,
isCompleted: true,
updatedAt: currentDate,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment