-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathservices-and-tasks.ts
More file actions
51 lines (46 loc) · 1.64 KB
/
Copy pathservices-and-tasks.ts
File metadata and controls
51 lines (46 loc) · 1.64 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
import { Context, Effect, Schema } from "effect";
import { Event, Machine, State } from "effect-machine";
export class Catalog extends Context.Service<
Catalog,
{
readonly search: (query: string) => Effect.Effect<ReadonlyArray<string>, "unavailable">;
}
>()("effect-machine/examples/Catalog") {}
export const SearchState = State({
Searching: { query: Schema.String },
Results: { items: Schema.Array(Schema.String) },
Failed: { message: Schema.String },
});
export const SearchEvent = Event({
SearchSucceeded: { items: Schema.Array(Schema.String) },
SearchFailed: { message: Schema.String },
});
export const searchMachine = Machine.make({
state: SearchState,
event: SearchEvent,
initial: (input: { readonly query: string }) => SearchState.Searching(input),
})
.task(
SearchState.Searching,
({ state }) => Effect.flatMap(Catalog, (catalog) => catalog.search(state.query)),
{
name: "catalog-search",
onSuccess: (items) => SearchEvent.SearchSucceeded({ items }),
onFailure: (error) => SearchEvent.SearchFailed({ message: error }),
},
)
.on(SearchState.Searching, SearchEvent.SearchSucceeded, ({ event }) =>
SearchState.Results({ items: event.items }),
)
.on(SearchState.Searching, SearchEvent.SearchFailed, ({ event }) =>
SearchState.Failed({ message: event.message }),
)
.final(SearchState.Results, ({ state }) => state.items)
.final(SearchState.Failed, () => []);
export const servicesAndTasksProgram = Machine.run(searchMachine, {
input: { query: "coffee" },
}).pipe(
Effect.provideService(Catalog, {
search: (query) => Effect.succeed([`${query} beans`, `${query} grinder`]),
}),
);