-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreateTodoFlow.ts
More file actions
92 lines (87 loc) · 2.52 KB
/
createTodoFlow.ts
File metadata and controls
92 lines (87 loc) · 2.52 KB
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 { createFlow, optimistic } from "mutaflow";
import {
consistency,
createInvalidationRegistry,
createServerActionAdapter,
definePaths,
defineTags,
} from "mutaflow/next";
export type CreateTodoInput = {
title: string;
};
export type Todo = {
id: string;
title: string;
pending?: boolean;
};
export async function createTodo(input: CreateTodoInput): Promise<{ id: string; title: string }> {
return { id: `todo-${input.title.toLowerCase().replace(/\s+/g, "-")}`, title: input.title };
}
export const todoInvalidation = createInvalidationRegistry({
tags: defineTags((tags) => ({
todos: {
list: () => tags.todos.list(),
byId: (id: string) => tags.todos.byId(id),
},
})),
paths: definePaths((paths) => ({
todos: {
list: () => paths.todos.list(),
byId: (id: string) => paths.todos.byId(id),
},
})),
});
export const createTodoFlow = createFlow({
action: createServerActionAdapter(createTodo),
meta: {
feature: "todos",
source: "basic-example",
},
middleware: [
async (context, next) => {
console.debug("[mutaflow] middleware before", context.meta, context.input);
const result = await next();
console.debug("[mutaflow] middleware after", result);
return result;
},
],
beforeRun: ({ meta, input }) => {
console.debug("[mutaflow] beforeRun", meta, input);
},
optimistic: optimistic.insert<CreateTodoInput, Todo>({
target: "todos:list",
position: "start",
item: (input) => ({
id: `temp:${input.title}`,
title: input.title,
pending: true,
}),
}),
reconcile: {
target: "todos:list",
onSuccess: (current, result) =>
(Array.isArray(current) ? current : []).map((todo) =>
typeof todo === "object" && todo !== null && "id" in todo && String(todo.id).startsWith("temp:")
? { ...todo, id: result.id, pending: false }
: todo,
),
},
consistency: ({ result }) =>
consistency.immediate({
tags: [
todoInvalidation.tags.todos.list(),
todoInvalidation.tags.todos.byId(result.id),
],
paths: [todoInvalidation.paths.todos.byId(result.id)],
}),
afterSuccess: ({ result, meta, consistency }) => {
console.debug("[mutaflow] afterSuccess", meta, result, consistency);
},
afterError: ({ error, meta }) => {
console.error("[mutaflow] afterError", meta, error);
},
onSettled: ({ cancelled, meta }) => {
console.debug("[mutaflow] onSettled", meta, { cancelled });
},
redirect: ({ result }) => `/todos/${result.id}`,
});