create-foldkit-app 0.29.0 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/templates/base/AGENTS.md +5 -112
- package/dist/templates/base/FOLDKIT.md +144 -0
- package/dist/templates/examples/api-cache/src/main.ts +36 -40
- package/dist/templates/examples/auth/src/main.ts +16 -15
- package/dist/templates/examples/auth/src/page/loggedIn/update.ts +10 -11
- package/dist/templates/examples/auth/src/page/loggedOut/page/login.ts +44 -55
- package/dist/templates/examples/auth/src/page/loggedOut/update.ts +8 -12
- package/dist/templates/examples/auth/src/update.ts +67 -73
- package/dist/templates/examples/canvas-art/src/main.ts +32 -31
- package/dist/templates/examples/charting/src/init.test.ts +6 -3
- package/dist/templates/examples/charting/src/init.ts +4 -4
- package/dist/templates/examples/charting/src/update.ts +34 -38
- package/dist/templates/examples/counter/src/main.ts +13 -13
- package/dist/templates/examples/counters/src/counter.ts +9 -8
- package/dist/templates/examples/counters/src/main.ts +20 -26
- package/dist/templates/examples/crash-view/src/main.ts +5 -3
- package/dist/templates/examples/embedding/src/main.ts +11 -9
- package/dist/templates/examples/form/src/main.ts +79 -89
- package/dist/templates/examples/generative-art/src/main.ts +6 -4
- package/dist/templates/examples/generative-art/src/update.ts +26 -23
- package/dist/templates/examples/interrupting-commands/src/main.ts +68 -66
- package/dist/templates/examples/job-application/src/main.ts +3 -4
- package/dist/templates/examples/job-application/src/step/attachments.ts +16 -19
- package/dist/templates/examples/job-application/src/step/coverLetter.ts +5 -5
- package/dist/templates/examples/job-application/src/step/education/education.ts +12 -17
- package/dist/templates/examples/job-application/src/step/education/entry.ts +29 -42
- package/dist/templates/examples/job-application/src/step/personalInfo.ts +35 -44
- package/dist/templates/examples/job-application/src/step/skills/entry.ts +15 -21
- package/dist/templates/examples/job-application/src/step/skills/skills.ts +12 -17
- package/dist/templates/examples/job-application/src/step/workHistory/entry.ts +41 -58
- package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +12 -17
- package/dist/templates/examples/job-application/src/update.ts +26 -29
- package/dist/templates/examples/kanban/src/main.ts +3 -4
- package/dist/templates/examples/kanban/src/update.ts +31 -31
- package/dist/templates/examples/managed-resource-layer/src/main.ts +30 -34
- package/dist/templates/examples/map/src/main.ts +48 -56
- package/dist/templates/examples/pixel-art/src/comparison.bench.test.ts +34 -13
- package/dist/templates/examples/pixel-art/src/main.bench.ts +3 -3
- package/dist/templates/examples/pixel-art/src/main.ts +3 -4
- package/dist/templates/examples/pixel-art/src/update.ts +109 -100
- package/dist/templates/examples/query-sync/src/main.ts +27 -25
- package/dist/templates/examples/route-transitions/src/main.ts +46 -43
- package/dist/templates/examples/route-transitions/src/story.test.ts +11 -11
- package/dist/templates/examples/routing/src/main.ts +16 -14
- package/dist/templates/examples/routing/src/page/people.ts +23 -28
- package/dist/templates/examples/shopping-cart/src/main.ts +41 -42
- package/dist/templates/examples/shopping-cart/src/page/products.ts +28 -35
- package/dist/templates/examples/slow-warnings/src/main.ts +23 -32
- package/dist/templates/examples/snake/src/main.ts +135 -143
- package/dist/templates/examples/ssg/src/main.ts +20 -17
- package/dist/templates/examples/ssr/src/main.ts +20 -24
- package/dist/templates/examples/state-machine/src/main.ts +24 -11
- package/dist/templates/examples/state-machine/src/story.test.ts +2 -2
- package/dist/templates/examples/stopwatch/src/main.ts +42 -50
- package/dist/templates/examples/todo/src/main.ts +152 -160
- package/dist/templates/examples/ui-showcase/src/main.ts +53 -54
- package/dist/templates/examples/ui-showcase/src/scene.test.ts +2 -2
- package/dist/templates/examples/ui-showcase/src/story.test.ts +2 -2
- package/dist/templates/examples/ui-showcase/src/ui/init.ts +6 -7
- package/dist/templates/examples/ui-showcase/src/ui/update.ts +265 -336
- package/dist/templates/examples/view-transitions/src/main.ts +18 -17
- package/dist/templates/examples/weather/src/main.ts +33 -40
- package/dist/templates/examples/web-components/src/main.ts +14 -17
- package/dist/templates/examples/websocket-chat/src/main.ts +44 -50
- package/dist/templates/release.json +8 -8
- package/dist/templates/rendering/ssg/src/main.ts +20 -17
- package/dist/templates/rendering/ssr/src/main.ts +20 -24
- package/package.json +1 -1
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { Match as M, Option } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Update } from 'foldkit'
|
|
3
3
|
import { evo } from 'foldkit/struct'
|
|
4
4
|
|
|
5
5
|
import { Message, OutMessage } from './message'
|
|
6
6
|
import { Model } from './model'
|
|
7
7
|
import * as Login from './page/login'
|
|
8
8
|
|
|
9
|
-
type UpdateReturn = readonly [
|
|
10
|
-
Model,
|
|
11
|
-
ReadonlyArray<Command.Command<Message>>,
|
|
12
|
-
Option.Option<OutMessage>,
|
|
13
|
-
]
|
|
14
|
-
|
|
15
9
|
const foldLogin = Update.foldChild({
|
|
16
10
|
update: Login.update,
|
|
17
11
|
read: (model: Model) => Option.some(model.loginModel),
|
|
@@ -20,13 +14,15 @@ const foldLogin = Update.foldChild({
|
|
|
20
14
|
toParentMessage: message => Message.GotLoginMessage({ message }),
|
|
21
15
|
toParentOutMessage: M.type<Login.OutMessage>().pipe(
|
|
22
16
|
M.tagsExhaustive({
|
|
23
|
-
SucceededLogin: ({ session }) =>
|
|
24
|
-
Option.some(OutMessage.SucceededLogin({ session })),
|
|
17
|
+
SucceededLogin: ({ session }) => OutMessage.SucceededLogin({ session }),
|
|
25
18
|
}),
|
|
26
19
|
),
|
|
27
20
|
})
|
|
28
21
|
|
|
29
22
|
export const update = (model: Model, message: Message) =>
|
|
30
|
-
Message.match<
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
Message.match<Update.ReturnWithOutMessage<Model, Message, OutMessage>>(
|
|
24
|
+
message,
|
|
25
|
+
{
|
|
26
|
+
GotLoginMessage: ({ message }) => foldLogin(model, message),
|
|
27
|
+
},
|
|
28
|
+
)
|
|
@@ -51,7 +51,7 @@ const RedirectToHome = Command.define('RedirectToHome', {
|
|
|
51
51
|
),
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
type UpdateReturn =
|
|
54
|
+
type UpdateReturn = Update.Return<Model, Message>
|
|
55
55
|
const withUpdateReturn = M.withReturnType<UpdateReturn>()
|
|
56
56
|
|
|
57
57
|
const foldLoggedOutOutMessage: (
|
|
@@ -61,10 +61,10 @@ const foldLoggedOutOutMessage: (
|
|
|
61
61
|
M.tagsExhaustive({
|
|
62
62
|
SucceededLogin:
|
|
63
63
|
({ session }) =>
|
|
64
|
-
() =>
|
|
65
|
-
LoggedIn.init(DashboardRoute(), session),
|
|
66
|
-
[SaveSession({ session }), RedirectToDashboard()],
|
|
67
|
-
|
|
64
|
+
() => ({
|
|
65
|
+
model: LoggedIn.init(DashboardRoute(), session),
|
|
66
|
+
commands: [SaveSession({ session }), RedirectToDashboard()],
|
|
67
|
+
}),
|
|
68
68
|
}),
|
|
69
69
|
)
|
|
70
70
|
|
|
@@ -87,10 +87,10 @@ const foldLoggedInOutMessage: (
|
|
|
87
87
|
) => Update.Step<Model, Message> = M.type<LoggedIn.OutMessage>().pipe(
|
|
88
88
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
89
89
|
M.tagsExhaustive({
|
|
90
|
-
RequestedLogout: () => () =>
|
|
91
|
-
LoggedOut.init(HomeRoute()),
|
|
92
|
-
[ClearSession(), RedirectToHome()],
|
|
93
|
-
|
|
90
|
+
RequestedLogout: () => () => ({
|
|
91
|
+
model: LoggedOut.init(HomeRoute()),
|
|
92
|
+
commands: [ClearSession(), RedirectToHome()],
|
|
93
|
+
}),
|
|
94
94
|
}),
|
|
95
95
|
)
|
|
96
96
|
|
|
@@ -108,72 +108,66 @@ const foldLoggedIn = Update.foldChild({
|
|
|
108
108
|
foldOutMessage: foldLoggedInOutMessage,
|
|
109
109
|
})
|
|
110
110
|
|
|
111
|
-
export const update = (model: Model, message: Message)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
M.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
model,
|
|
121
|
-
[NavigateInternal({ url: urlToString(url) })],
|
|
122
|
-
],
|
|
123
|
-
External: ({ href }) => [model, [LoadExternal({ href })]],
|
|
111
|
+
export const update = (model: Model, message: Message) =>
|
|
112
|
+
Message.match<UpdateReturn>(message, {
|
|
113
|
+
ClickedLink: ({ request }) =>
|
|
114
|
+
M.value(request).pipe(
|
|
115
|
+
withUpdateReturn,
|
|
116
|
+
M.tagsExhaustive({
|
|
117
|
+
Internal: ({ url }) => ({
|
|
118
|
+
model,
|
|
119
|
+
commands: [NavigateInternal({ url: urlToString(url) })],
|
|
124
120
|
}),
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const route = urlToAppRoute(url)
|
|
129
|
-
|
|
130
|
-
return M.value(model).pipe(
|
|
131
|
-
withUpdateReturn,
|
|
132
|
-
M.tagsExhaustive({
|
|
133
|
-
LoggedOut: loggedOutModel =>
|
|
134
|
-
M.value(route).pipe(
|
|
135
|
-
withUpdateReturn,
|
|
136
|
-
M.tag('Home', 'Login', 'NotFound', route => [
|
|
137
|
-
evo(loggedOutModel, { route: () => route }),
|
|
138
|
-
[],
|
|
139
|
-
]),
|
|
140
|
-
M.orElse(() => [model, [RedirectToLogin()]]),
|
|
141
|
-
),
|
|
142
|
-
|
|
143
|
-
LoggedIn: loggedInModel =>
|
|
144
|
-
M.value(route).pipe(
|
|
145
|
-
withUpdateReturn,
|
|
146
|
-
M.tag('Dashboard', 'Settings', 'NotFound', route => [
|
|
147
|
-
evo(loggedInModel, { route: () => route }),
|
|
148
|
-
[],
|
|
149
|
-
]),
|
|
150
|
-
M.orElse(() => [model, [RedirectToDashboard()]]),
|
|
151
|
-
),
|
|
121
|
+
External: ({ href }) => ({
|
|
122
|
+
model,
|
|
123
|
+
commands: [LoadExternal({ href })],
|
|
152
124
|
}),
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
125
|
+
}),
|
|
126
|
+
),
|
|
127
|
+
|
|
128
|
+
ChangedUrl: ({ url }) => {
|
|
129
|
+
const route = urlToAppRoute(url)
|
|
130
|
+
|
|
131
|
+
return M.value(model).pipe(
|
|
132
|
+
withUpdateReturn,
|
|
133
|
+
M.tagsExhaustive({
|
|
134
|
+
LoggedOut: loggedOutModel =>
|
|
135
|
+
M.value(route).pipe(
|
|
136
|
+
withUpdateReturn,
|
|
137
|
+
M.tag('Home', 'Login', 'NotFound', route => ({
|
|
138
|
+
model: evo(loggedOutModel, { route: () => route }),
|
|
139
|
+
})),
|
|
140
|
+
M.orElse(() => ({ model, commands: [RedirectToLogin()] })),
|
|
141
|
+
),
|
|
142
|
+
|
|
143
|
+
LoggedIn: loggedInModel =>
|
|
144
|
+
M.value(route).pipe(
|
|
145
|
+
withUpdateReturn,
|
|
146
|
+
M.tag('Dashboard', 'Settings', 'NotFound', route => ({
|
|
147
|
+
model: evo(loggedInModel, { route: () => route }),
|
|
148
|
+
})),
|
|
149
|
+
M.orElse(() => ({ model, commands: [RedirectToDashboard()] })),
|
|
150
|
+
),
|
|
151
|
+
}),
|
|
152
|
+
)
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
FailedSaveSession: ({ error }) => ({
|
|
156
|
+
model,
|
|
157
|
+
commands: [LogError({ entries: ['Failed to save session:', error] })],
|
|
158
|
+
}),
|
|
160
159
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
160
|
+
FailedClearSession: ({ error }) => ({
|
|
161
|
+
model,
|
|
162
|
+
commands: [LogError({ entries: ['Failed to clear session:', error] })],
|
|
163
|
+
}),
|
|
165
164
|
|
|
166
|
-
|
|
165
|
+
GotLoggedOutMessage: ({ message }) => foldLoggedOut(model, message),
|
|
167
166
|
|
|
168
|
-
|
|
169
|
-
}),
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
'SucceededClearSession',
|
|
176
|
-
() => [model, []],
|
|
177
|
-
),
|
|
178
|
-
M.exhaustive,
|
|
179
|
-
)
|
|
167
|
+
GotLoggedInMessage: ({ message }) => foldLoggedIn(model, message),
|
|
168
|
+
CompletedNavigateInternal: () => ({ model }),
|
|
169
|
+
CompletedLoadExternal: () => ({ model }),
|
|
170
|
+
CompletedLogError: () => ({ model }),
|
|
171
|
+
SucceededSaveSession: () => ({ model }),
|
|
172
|
+
SucceededClearSession: () => ({ model }),
|
|
173
|
+
})
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
Schema as S,
|
|
8
8
|
pipe,
|
|
9
9
|
} from 'effect'
|
|
10
|
-
import { Canvas, Command, Runtime, Subscription } from 'foldkit'
|
|
10
|
+
import { Canvas, Command, Runtime, Subscription, type Update } from 'foldkit'
|
|
11
11
|
import { Document, Html, HtmlBuilder } from 'foldkit/html'
|
|
12
12
|
import { defineMessageUnion } from 'foldkit/message'
|
|
13
13
|
import { evo } from 'foldkit/struct'
|
|
@@ -75,10 +75,9 @@ export type Message = typeof Message.Type
|
|
|
75
75
|
|
|
76
76
|
// INIT
|
|
77
77
|
|
|
78
|
-
export const init: Runtime.ApplicationInit<Model, Message> = () =>
|
|
79
|
-
{ balls: [], nextId: 0, isRunning: true },
|
|
80
|
-
|
|
81
|
-
]
|
|
78
|
+
export const init: Runtime.ApplicationInit<Model, Message> = () => ({
|
|
79
|
+
model: { balls: [], nextId: 0, isRunning: true },
|
|
80
|
+
})
|
|
82
81
|
|
|
83
82
|
// COMMAND
|
|
84
83
|
|
|
@@ -131,37 +130,39 @@ const advanceBall =
|
|
|
131
130
|
}
|
|
132
131
|
|
|
133
132
|
export const update = (model: Model, message: Message) =>
|
|
134
|
-
Message.match<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}),
|
|
141
|
-
[],
|
|
142
|
-
],
|
|
133
|
+
Message.match<Update.Return<Model, Message>>(message, {
|
|
134
|
+
TickedFrame: ({ deltaTime }) => ({
|
|
135
|
+
model: evo(model, {
|
|
136
|
+
balls: Array.map(advanceBall(deltaTime / MS_PER_SECOND)),
|
|
137
|
+
}),
|
|
138
|
+
}),
|
|
143
139
|
|
|
144
|
-
|
|
140
|
+
ClickedCanvas: ({ x, y }) => ({
|
|
141
|
+
model,
|
|
142
|
+
commands: [GenerateBall({ x, y })],
|
|
143
|
+
}),
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
CompletedGenerateBall: ({ x, y, vx, vy, radius, color }) => ({
|
|
146
|
+
model: evo(model, {
|
|
147
|
+
balls: Array.append({
|
|
148
|
+
id: model.nextId,
|
|
149
|
+
x,
|
|
150
|
+
y,
|
|
151
|
+
vx,
|
|
152
|
+
vy,
|
|
153
|
+
radius,
|
|
154
|
+
color,
|
|
153
155
|
}),
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
nextId: Number.increment,
|
|
157
|
+
}),
|
|
158
|
+
}),
|
|
156
159
|
|
|
157
|
-
|
|
160
|
+
ClickedClear: () => ({ model: evo(model, { balls: () => [] }) }),
|
|
158
161
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
},
|
|
164
|
-
)
|
|
162
|
+
ClickedTogglePlay: () => ({
|
|
163
|
+
model: evo(model, { isRunning: running => !running }),
|
|
164
|
+
}),
|
|
165
|
+
})
|
|
165
166
|
|
|
166
167
|
// SUBSCRIPTION
|
|
167
168
|
|
|
@@ -5,10 +5,13 @@ import { FetchTelemetry } from './command'
|
|
|
5
5
|
import { init } from './init'
|
|
6
6
|
|
|
7
7
|
test('seeds loading state and queues a telemetry fetch', () => {
|
|
8
|
-
const
|
|
8
|
+
const init_ = init()
|
|
9
9
|
|
|
10
|
-
expect(model.telemetry._tag).toBe('Loading')
|
|
10
|
+
expect(init_.model.telemetry._tag).toBe('Loading')
|
|
11
11
|
expect(
|
|
12
|
-
Array.some(
|
|
12
|
+
Array.some(
|
|
13
|
+
init_.commands ?? [],
|
|
14
|
+
command => command.name === FetchTelemetry.name,
|
|
15
|
+
),
|
|
13
16
|
).toBe(true)
|
|
14
17
|
})
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
PERIOD_RADIO_GROUP_ID,
|
|
13
13
|
} from './radioGroups'
|
|
14
14
|
|
|
15
|
-
export const init: Runtime.ApplicationInit<Model, Message> = () =>
|
|
16
|
-
{
|
|
15
|
+
export const init: Runtime.ApplicationInit<Model, Message> = () => ({
|
|
16
|
+
model: {
|
|
17
17
|
telemetry: TelemetryAsyncData.Loading(),
|
|
18
18
|
chartMode: 'Adoption',
|
|
19
19
|
chartModeRadioGroup: RadioGroup.init({ id: CHART_MODE_RADIO_GROUP_ID }),
|
|
@@ -25,5 +25,5 @@ export const init: Runtime.ApplicationInit<Model, Message> = () => [
|
|
|
25
25
|
maybeChartError: Option.none(),
|
|
26
26
|
maybeSelectedDatumId: Option.none(),
|
|
27
27
|
},
|
|
28
|
-
[FetchTelemetry()],
|
|
29
|
-
|
|
28
|
+
commands: [FetchTelemetry()],
|
|
29
|
+
})
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
PeriodRadioGroup,
|
|
15
15
|
} from './radioGroups'
|
|
16
16
|
|
|
17
|
-
type UpdateReturn =
|
|
17
|
+
type UpdateReturn = Update.Return<Model, Message>
|
|
18
18
|
|
|
19
19
|
const syncChart = (args: {
|
|
20
20
|
maybeChartHostId: Model['maybeChartHostId']
|
|
@@ -43,11 +43,11 @@ const syncChart = (args: {
|
|
|
43
43
|
|
|
44
44
|
const refetchTelemetry = (model: Model): UpdateReturn =>
|
|
45
45
|
Option.match(AsyncData.revalidateOrLoad(model.telemetry), {
|
|
46
|
-
onNone: () =>
|
|
47
|
-
onSome: nextTelemetry =>
|
|
48
|
-
evo(model, { telemetry: () => nextTelemetry }),
|
|
49
|
-
[FetchTelemetry()],
|
|
50
|
-
|
|
46
|
+
onNone: () => ({ model }),
|
|
47
|
+
onSome: nextTelemetry => ({
|
|
48
|
+
model: evo(model, { telemetry: () => nextTelemetry }),
|
|
49
|
+
commands: [FetchTelemetry()],
|
|
50
|
+
}),
|
|
51
51
|
})
|
|
52
52
|
|
|
53
53
|
const selectedControl =
|
|
@@ -57,9 +57,9 @@ const selectedControl =
|
|
|
57
57
|
evo(model, { maybeSelectedDatumId: () => Option.none() }),
|
|
58
58
|
)
|
|
59
59
|
|
|
60
|
-
return
|
|
61
|
-
nextModel,
|
|
62
|
-
syncChart({
|
|
60
|
+
return {
|
|
61
|
+
model: nextModel,
|
|
62
|
+
commands: syncChart({
|
|
63
63
|
maybeChartHostId: nextModel.maybeChartHostId,
|
|
64
64
|
telemetry: nextModel.telemetry,
|
|
65
65
|
chartMode: nextModel.chartMode,
|
|
@@ -67,7 +67,7 @@ const selectedControl =
|
|
|
67
67
|
period: nextModel.period,
|
|
68
68
|
maybeSelectedDatumId: nextModel.maybeSelectedDatumId,
|
|
69
69
|
}),
|
|
70
|
-
|
|
70
|
+
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
const foldChartModeRadioGroupOutMessage = M.type<
|
|
@@ -141,11 +141,11 @@ export const update = (model: Model, message: Message) =>
|
|
|
141
141
|
|
|
142
142
|
ClickedRetry: () => refetchTelemetry(model),
|
|
143
143
|
|
|
144
|
-
ClickedChartDatum: ({ datumId }) =>
|
|
145
|
-
evo(model, {
|
|
144
|
+
ClickedChartDatum: ({ datumId }) => ({
|
|
145
|
+
model: evo(model, {
|
|
146
146
|
maybeSelectedDatumId: () => Option.some(datumId),
|
|
147
147
|
}),
|
|
148
|
-
syncChart({
|
|
148
|
+
commands: syncChart({
|
|
149
149
|
maybeChartHostId: model.maybeChartHostId,
|
|
150
150
|
telemetry: model.telemetry,
|
|
151
151
|
chartMode: model.chartMode,
|
|
@@ -153,15 +153,15 @@ export const update = (model: Model, message: Message) =>
|
|
|
153
153
|
period: model.period,
|
|
154
154
|
maybeSelectedDatumId: Option.some(datumId),
|
|
155
155
|
}),
|
|
156
|
-
|
|
156
|
+
}),
|
|
157
157
|
|
|
158
158
|
SucceededFetchTelemetry: ({ telemetry }) => {
|
|
159
159
|
const nextModel = evo(model, {
|
|
160
160
|
telemetry: () => TelemetryAsyncData.Success({ data: telemetry }),
|
|
161
161
|
})
|
|
162
|
-
return
|
|
163
|
-
nextModel,
|
|
164
|
-
syncChart({
|
|
162
|
+
return {
|
|
163
|
+
model: nextModel,
|
|
164
|
+
commands: syncChart({
|
|
165
165
|
maybeChartHostId: nextModel.maybeChartHostId,
|
|
166
166
|
telemetry: nextModel.telemetry,
|
|
167
167
|
chartMode: nextModel.chartMode,
|
|
@@ -169,22 +169,21 @@ export const update = (model: Model, message: Message) =>
|
|
|
169
169
|
period: nextModel.period,
|
|
170
170
|
maybeSelectedDatumId: nextModel.maybeSelectedDatumId,
|
|
171
171
|
}),
|
|
172
|
-
|
|
172
|
+
}
|
|
173
173
|
},
|
|
174
174
|
|
|
175
|
-
FailedFetchTelemetry: ({ error }) =>
|
|
176
|
-
evo(model, {
|
|
175
|
+
FailedFetchTelemetry: ({ error }) => ({
|
|
176
|
+
model: evo(model, {
|
|
177
177
|
telemetry: () => AsyncData.settle(model.telemetry, Result.fail(error)),
|
|
178
178
|
}),
|
|
179
|
-
|
|
180
|
-
],
|
|
179
|
+
}),
|
|
181
180
|
|
|
182
|
-
SucceededMountChart: ({ hostId }) =>
|
|
183
|
-
evo(model, {
|
|
181
|
+
SucceededMountChart: ({ hostId }) => ({
|
|
182
|
+
model: evo(model, {
|
|
184
183
|
maybeChartHostId: () => Option.some(hostId),
|
|
185
184
|
maybeChartError: () => Option.none(),
|
|
186
185
|
}),
|
|
187
|
-
syncChart({
|
|
186
|
+
commands: syncChart({
|
|
188
187
|
maybeChartHostId: Option.some(hostId),
|
|
189
188
|
telemetry: model.telemetry,
|
|
190
189
|
chartMode: model.chartMode,
|
|
@@ -192,26 +191,23 @@ export const update = (model: Model, message: Message) =>
|
|
|
192
191
|
period: model.period,
|
|
193
192
|
maybeSelectedDatumId: model.maybeSelectedDatumId,
|
|
194
193
|
}),
|
|
195
|
-
|
|
194
|
+
}),
|
|
196
195
|
|
|
197
|
-
FailedMountChart: ({ reason }) =>
|
|
198
|
-
evo(model, {
|
|
196
|
+
FailedMountChart: ({ reason }) => ({
|
|
197
|
+
model: evo(model, {
|
|
199
198
|
maybeChartError: () => Option.some(reason),
|
|
200
199
|
}),
|
|
201
|
-
|
|
202
|
-
],
|
|
200
|
+
}),
|
|
203
201
|
|
|
204
|
-
SucceededSyncChart: () =>
|
|
205
|
-
evo(model, {
|
|
202
|
+
SucceededSyncChart: () => ({
|
|
203
|
+
model: evo(model, {
|
|
206
204
|
maybeChartError: () => Option.none(),
|
|
207
205
|
}),
|
|
208
|
-
|
|
209
|
-
],
|
|
206
|
+
}),
|
|
210
207
|
|
|
211
|
-
FailedSyncChart: ({ reason }) =>
|
|
212
|
-
evo(model, {
|
|
208
|
+
FailedSyncChart: ({ reason }) => ({
|
|
209
|
+
model: evo(model, {
|
|
213
210
|
maybeChartError: () => Option.some(reason),
|
|
214
211
|
}),
|
|
215
|
-
|
|
216
|
-
],
|
|
212
|
+
}),
|
|
217
213
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema as S } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Runtime, type Update } from 'foldkit'
|
|
3
3
|
import { Document, HtmlBuilder } from 'foldkit/html'
|
|
4
4
|
import { defineMessageUnion } from 'foldkit/message'
|
|
5
5
|
import { evo } from 'foldkit/struct'
|
|
@@ -23,21 +23,21 @@ export type Message = typeof Message.Type
|
|
|
23
23
|
// UPDATE
|
|
24
24
|
|
|
25
25
|
export const update = (model: Model, message: Message) =>
|
|
26
|
-
Message.match<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
},
|
|
33
|
-
|
|
26
|
+
Message.match<Update.Return<Model, Message>>(message, {
|
|
27
|
+
ClickedDecrement: () => ({
|
|
28
|
+
model: evo(model, { count: count => count - 1 }),
|
|
29
|
+
}),
|
|
30
|
+
ClickedIncrement: () => ({
|
|
31
|
+
model: evo(model, { count: count => count + 1 }),
|
|
32
|
+
}),
|
|
33
|
+
ClickedReset: () => ({ model: evo(model, { count: () => 0 }) }),
|
|
34
|
+
})
|
|
34
35
|
|
|
35
36
|
// INIT
|
|
36
37
|
|
|
37
|
-
export const init: Runtime.ApplicationInit<Model, Message> = () =>
|
|
38
|
-
{ count: 0 },
|
|
39
|
-
|
|
40
|
-
]
|
|
38
|
+
export const init: Runtime.ApplicationInit<Model, Message> = () => ({
|
|
39
|
+
model: { count: 0 },
|
|
40
|
+
})
|
|
41
41
|
|
|
42
42
|
// VIEW
|
|
43
43
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema as S } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Submodel, type Update } from 'foldkit'
|
|
3
3
|
import { defineMessageUnion } from 'foldkit/message'
|
|
4
4
|
import { evo } from 'foldkit/struct'
|
|
5
5
|
|
|
@@ -24,13 +24,14 @@ export type Message = typeof Message.Type
|
|
|
24
24
|
// UPDATE
|
|
25
25
|
|
|
26
26
|
export const update = (model: Model, message: Message) =>
|
|
27
|
-
Message.match<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
Message.match<Update.Return<Model, Message>>(message, {
|
|
28
|
+
ClickedDecrement: () => ({
|
|
29
|
+
model: evo(model, { count: count => count - 1 }),
|
|
30
|
+
}),
|
|
31
|
+
ClickedIncrement: () => ({
|
|
32
|
+
model: evo(model, { count: count => count + 1 }),
|
|
33
|
+
}),
|
|
34
|
+
})
|
|
34
35
|
|
|
35
36
|
// VIEW
|
|
36
37
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Array, Option, Schema as S, pipe } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Runtime, Update } from 'foldkit'
|
|
3
3
|
import { Document, Html, HtmlBuilder } from 'foldkit/html'
|
|
4
4
|
import { defineMessageUnion } from 'foldkit/message'
|
|
5
5
|
import { evo } from 'foldkit/struct'
|
|
@@ -55,33 +55,28 @@ const foldCounter = (id: string) =>
|
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
export const update = (model: Model, message: Message) =>
|
|
58
|
-
Message.match<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
id: `counter-${model.nextRowId}`,
|
|
65
|
-
counter: Counter.init,
|
|
66
|
-
}),
|
|
67
|
-
nextRowId: nextRowId => nextRowId + 1,
|
|
68
|
-
}),
|
|
69
|
-
[],
|
|
70
|
-
],
|
|
71
|
-
ClickedRemoveRow: ({ id }) => [
|
|
72
|
-
evo(model, {
|
|
73
|
-
rows: Array.filter(row => row.id !== id),
|
|
58
|
+
Message.match<Update.Return<Model, Message>>(message, {
|
|
59
|
+
ClickedAddRow: () => ({
|
|
60
|
+
model: evo(model, {
|
|
61
|
+
rows: Array.append({
|
|
62
|
+
id: `counter-${model.nextRowId}`,
|
|
63
|
+
counter: Counter.init,
|
|
74
64
|
}),
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
65
|
+
nextRowId: nextRowId => nextRowId + 1,
|
|
66
|
+
}),
|
|
67
|
+
}),
|
|
68
|
+
ClickedRemoveRow: ({ id }) => ({
|
|
69
|
+
model: evo(model, {
|
|
70
|
+
rows: Array.filter(row => row.id !== id),
|
|
71
|
+
}),
|
|
72
|
+
}),
|
|
73
|
+
GotCounterMessage: ({ id, message }) => foldCounter(id)(model, message),
|
|
74
|
+
})
|
|
80
75
|
|
|
81
76
|
// INIT
|
|
82
77
|
|
|
83
|
-
export const init: Runtime.ApplicationInit<Model, Message> = () =>
|
|
84
|
-
{
|
|
78
|
+
export const init: Runtime.ApplicationInit<Model, Message> = () => ({
|
|
79
|
+
model: {
|
|
85
80
|
rows: [
|
|
86
81
|
{ id: 'counter-0', counter: Counter.init },
|
|
87
82
|
{ id: 'counter-1', counter: Counter.init },
|
|
@@ -89,8 +84,7 @@ export const init: Runtime.ApplicationInit<Model, Message> = () => [
|
|
|
89
84
|
],
|
|
90
85
|
nextRowId: 3,
|
|
91
86
|
},
|
|
92
|
-
|
|
93
|
-
]
|
|
87
|
+
})
|
|
94
88
|
|
|
95
89
|
// VIEW
|
|
96
90
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Runtime, type Update } from 'foldkit'
|
|
3
3
|
import { Document, HtmlBuilder } from 'foldkit/html'
|
|
4
4
|
import { defineMessageUnion } from 'foldkit/message'
|
|
5
5
|
|
|
@@ -23,13 +23,15 @@ export type Message = typeof Message.Type
|
|
|
23
23
|
export const update = (
|
|
24
24
|
_model: Model,
|
|
25
25
|
_message: Message,
|
|
26
|
-
):
|
|
26
|
+
): Update.Return<Model, Message> => {
|
|
27
27
|
throw new Error('This is a simulated crash!')
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// INIT
|
|
31
31
|
|
|
32
|
-
export const init: Runtime.ApplicationInit<Model, Message> = () =>
|
|
32
|
+
export const init: Runtime.ApplicationInit<Model, Message> = () => ({
|
|
33
|
+
model: null,
|
|
34
|
+
})
|
|
33
35
|
|
|
34
36
|
// VIEW
|
|
35
37
|
|