forked from effect-app/boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBlog.ts
More file actions
95 lines (85 loc) · 2.93 KB
/
Blog.ts
File metadata and controls
95 lines (85 loc) · 2.93 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
93
94
95
import { OperationsDefault } from "api/lib/layers.js"
import { matchFor } from "api/lib/routing.js"
import { Events, Operations } from "api/services.js"
import { Duration, Effect, Schedule } from "effect"
import { Option } from "effect-app"
import { NonEmptyString2k, NonNegativeInt } from "effect-app/Schema"
import { BlogApi } from "resources.js"
import { UserRepo } from "./Accounts/UserRepo.js"
import { BlogPostRepo } from "./Blog/BlogPostRepo.js"
import { BlogPost } from "./Domain/Blog.js"
import { BogusEvent } from "./Domain/Events.js"
export default matchFor(BlogApi)([
BlogPostRepo.Default,
UserRepo.Default,
OperationsDefault,
Events.Default
], ({ CreatePost, FindPost, Index, PublishPost }) =>
Effect.gen(function*() {
const blogPostRepo = yield* BlogPostRepo
const userRepo = yield* UserRepo
const events = yield* Events
const operations = yield* Operations
return {
FindPost: FindPost((req) =>
blogPostRepo
.find(req.id)
.pipe(Effect.andThen(Option.getOrNull))
),
Index: Index(
blogPostRepo
.all
.pipe(Effect.andThen((items) => ({ items })))
),
CreatePost: CreatePost((req) =>
userRepo
.getCurrentUser
.pipe(
Effect.andThen((author) => (new BlogPost({ ...req, author }, true))),
Effect.tap(blogPostRepo.save)
)
),
PublishPost: PublishPost((req) =>
Effect.gen(function*() {
const post = yield* blogPostRepo.get(req.id)
console.log("publishing post", post)
const targets = [
"google",
"twitter",
"facebook"
]
const done: string[] = []
const op = yield* operations.fork(
(opId) =>
operations
.update(opId, {
total: NonNegativeInt(targets.length),
completed: NonNegativeInt(done.length)
})
.pipe(
Effect.andThen(Effect.forEach(targets, (_) =>
Effect
.sync(() => done.push(_))
.pipe(
Effect.tap(() =>
operations.update(opId, {
total: NonNegativeInt(targets.length),
completed: NonNegativeInt(done.length)
})
),
Effect.delay(Duration.seconds(4))
))),
Effect.andThen(() => "the answer to the universe is 41")
),
// while operation is running...
(_opId) =>
Effect
.suspend(() => events.publish(new BogusEvent()))
.pipe(Effect.schedule(Schedule.spaced(Duration.seconds(1)))),
NonEmptyString2k("post publishing")
)
return op.id
})
)
}
}))