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.
Files changed (68) hide show
  1. package/dist/templates/base/AGENTS.md +5 -112
  2. package/dist/templates/base/FOLDKIT.md +144 -0
  3. package/dist/templates/examples/api-cache/src/main.ts +36 -40
  4. package/dist/templates/examples/auth/src/main.ts +16 -15
  5. package/dist/templates/examples/auth/src/page/loggedIn/update.ts +10 -11
  6. package/dist/templates/examples/auth/src/page/loggedOut/page/login.ts +44 -55
  7. package/dist/templates/examples/auth/src/page/loggedOut/update.ts +8 -12
  8. package/dist/templates/examples/auth/src/update.ts +67 -73
  9. package/dist/templates/examples/canvas-art/src/main.ts +32 -31
  10. package/dist/templates/examples/charting/src/init.test.ts +6 -3
  11. package/dist/templates/examples/charting/src/init.ts +4 -4
  12. package/dist/templates/examples/charting/src/update.ts +34 -38
  13. package/dist/templates/examples/counter/src/main.ts +13 -13
  14. package/dist/templates/examples/counters/src/counter.ts +9 -8
  15. package/dist/templates/examples/counters/src/main.ts +20 -26
  16. package/dist/templates/examples/crash-view/src/main.ts +5 -3
  17. package/dist/templates/examples/embedding/src/main.ts +11 -9
  18. package/dist/templates/examples/form/src/main.ts +79 -89
  19. package/dist/templates/examples/generative-art/src/main.ts +6 -4
  20. package/dist/templates/examples/generative-art/src/update.ts +26 -23
  21. package/dist/templates/examples/interrupting-commands/src/main.ts +68 -66
  22. package/dist/templates/examples/job-application/src/main.ts +3 -4
  23. package/dist/templates/examples/job-application/src/step/attachments.ts +16 -19
  24. package/dist/templates/examples/job-application/src/step/coverLetter.ts +5 -5
  25. package/dist/templates/examples/job-application/src/step/education/education.ts +12 -17
  26. package/dist/templates/examples/job-application/src/step/education/entry.ts +29 -42
  27. package/dist/templates/examples/job-application/src/step/personalInfo.ts +35 -44
  28. package/dist/templates/examples/job-application/src/step/skills/entry.ts +15 -21
  29. package/dist/templates/examples/job-application/src/step/skills/skills.ts +12 -17
  30. package/dist/templates/examples/job-application/src/step/workHistory/entry.ts +41 -58
  31. package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +12 -17
  32. package/dist/templates/examples/job-application/src/update.ts +26 -29
  33. package/dist/templates/examples/kanban/src/main.ts +3 -4
  34. package/dist/templates/examples/kanban/src/update.ts +31 -31
  35. package/dist/templates/examples/managed-resource-layer/src/main.ts +30 -34
  36. package/dist/templates/examples/map/src/main.ts +48 -56
  37. package/dist/templates/examples/pixel-art/src/comparison.bench.test.ts +34 -13
  38. package/dist/templates/examples/pixel-art/src/main.bench.ts +3 -3
  39. package/dist/templates/examples/pixel-art/src/main.ts +3 -4
  40. package/dist/templates/examples/pixel-art/src/update.ts +109 -100
  41. package/dist/templates/examples/query-sync/src/main.ts +27 -25
  42. package/dist/templates/examples/route-transitions/src/main.ts +46 -43
  43. package/dist/templates/examples/route-transitions/src/story.test.ts +11 -11
  44. package/dist/templates/examples/routing/src/main.ts +16 -14
  45. package/dist/templates/examples/routing/src/page/people.ts +23 -28
  46. package/dist/templates/examples/shopping-cart/src/main.ts +41 -42
  47. package/dist/templates/examples/shopping-cart/src/page/products.ts +28 -35
  48. package/dist/templates/examples/slow-warnings/src/main.ts +23 -32
  49. package/dist/templates/examples/snake/src/main.ts +135 -143
  50. package/dist/templates/examples/ssg/src/main.ts +20 -17
  51. package/dist/templates/examples/ssr/src/main.ts +20 -24
  52. package/dist/templates/examples/state-machine/src/main.ts +24 -11
  53. package/dist/templates/examples/state-machine/src/story.test.ts +2 -2
  54. package/dist/templates/examples/stopwatch/src/main.ts +42 -50
  55. package/dist/templates/examples/todo/src/main.ts +152 -160
  56. package/dist/templates/examples/ui-showcase/src/main.ts +53 -54
  57. package/dist/templates/examples/ui-showcase/src/scene.test.ts +2 -2
  58. package/dist/templates/examples/ui-showcase/src/story.test.ts +2 -2
  59. package/dist/templates/examples/ui-showcase/src/ui/init.ts +6 -7
  60. package/dist/templates/examples/ui-showcase/src/ui/update.ts +265 -336
  61. package/dist/templates/examples/view-transitions/src/main.ts +18 -17
  62. package/dist/templates/examples/weather/src/main.ts +33 -40
  63. package/dist/templates/examples/web-components/src/main.ts +14 -17
  64. package/dist/templates/examples/websocket-chat/src/main.ts +44 -50
  65. package/dist/templates/release.json +8 -8
  66. package/dist/templates/rendering/ssg/src/main.ts +20 -17
  67. package/dist/templates/rendering/ssr/src/main.ts +20 -24
  68. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { Duration, Effect, Schema as S, Stream } from 'effect'
2
- import { Command, Port, Runtime, Subscription } from 'foldkit'
2
+ import { Command, Port, Runtime, Subscription, type Update } from 'foldkit'
3
3
  import { Html, HtmlBuilder } from 'foldkit/html'
4
4
  import { defineMessageUnion } from 'foldkit/message'
5
5
  import { evo } from 'foldkit/struct'
@@ -34,10 +34,9 @@ export const ports = {
34
34
  export const Flags = S.Struct({ initialCount: S.Number })
35
35
  export type Flags = typeof Flags.Type
36
36
 
37
- export const init: Runtime.ElementInit<Model, Message, Flags> = flags => [
38
- { count: flags.initialCount, step: 1 },
39
- [],
40
- ]
37
+ export const init: Runtime.ElementInit<Model, Message, Flags> = flags => ({
38
+ model: { count: flags.initialCount, step: 1 },
39
+ })
41
40
 
42
41
  // COMMAND
43
42
 
@@ -52,19 +51,22 @@ export const ReportCount = Command.define('ReportCount', {
52
51
 
53
52
  // UPDATE
54
53
 
55
- type UpdateReturn = readonly [Model, ReadonlyArray<Command.Command<Message>>]
54
+ type UpdateReturn = Update.Return<Model, Message>
56
55
 
57
56
  const advance = (model: Model): UpdateReturn => {
58
57
  const count = model.count + model.step
59
- return [evo(model, { count: () => count }), [ReportCount({ count })]]
58
+ return {
59
+ model: evo(model, { count: () => count }),
60
+ commands: [ReportCount({ count })],
61
+ }
60
62
  }
61
63
 
62
64
  export const update = (model: Model, message: Message) =>
63
65
  Message.match<UpdateReturn>(message, {
64
66
  Ticked: () => advance(model),
65
67
  ClickedAdvance: () => advance(model),
66
- ChangedStep: ({ step }) => [evo(model, { step: () => step }), []],
67
- CompletedReportCount: () => [model, []],
68
+ ChangedStep: ({ step }) => ({ model: evo(model, { step: () => step }) }),
69
+ CompletedReportCount: () => ({ model }),
68
70
  })
69
71
 
70
72
  // SUBSCRIPTION
@@ -7,7 +7,7 @@ import {
7
7
  Random,
8
8
  Schema as S,
9
9
  } from 'effect'
10
- import { Command, Runtime } from 'foldkit'
10
+ import { Command, Runtime, type Update } from 'foldkit'
11
11
  import {
12
12
  Field,
13
13
  Invalid,
@@ -86,10 +86,9 @@ export const initialModel: Model = {
86
86
  submission: NotSubmitted(),
87
87
  }
88
88
 
89
- export const init: Runtime.ApplicationInit<Model, Message> = () => [
90
- initialModel,
91
- [],
92
- ]
89
+ export const init: Runtime.ApplicationInit<Model, Message> = () => ({
90
+ model: initialModel,
91
+ })
93
92
 
94
93
  // FIELD VALIDATION
95
94
 
@@ -137,101 +136,92 @@ const isFormValid = (model: Model): boolean =>
137
136
  // UPDATE
138
137
 
139
138
  export const update = (model: Model, message: Message) =>
140
- Message.match<readonly [Model, ReadonlyArray<Command.Command<Message>>]>(
141
- message,
142
- {
143
- UpdatedName: ({ value }) => [
144
- evo(model, {
145
- name: () => validateName(value),
146
- }),
147
- [],
148
- ],
139
+ Message.match<Update.Return<Model, Message>>(message, {
140
+ UpdatedName: ({ value }) => ({
141
+ model: evo(model, {
142
+ name: () => validateName(value),
143
+ }),
144
+ }),
149
145
 
150
- UpdatedEmail: ({ value }) => {
151
- const validateEmailResult = validateEmail(value)
146
+ UpdatedEmail: ({ value }) => {
147
+ const validateEmailResult = validateEmail(value)
152
148
 
153
- if (validateEmailResult._tag === 'Valid') {
154
- return [
155
- evo(model, {
156
- email: () => Validating({ value }),
157
- }),
158
- [ValidateEmail({ email: value })],
159
- ]
160
- } else {
161
- return [
162
- evo(model, {
163
- email: () => validateEmailResult,
164
- }),
165
- [],
166
- ]
149
+ if (validateEmailResult._tag === 'Valid') {
150
+ return {
151
+ model: evo(model, {
152
+ email: () => Validating({ value }),
153
+ }),
154
+ commands: [ValidateEmail({ email: value })],
155
+ }
156
+ } else {
157
+ return {
158
+ model: evo(model, {
159
+ email: () => validateEmailResult,
160
+ }),
167
161
  }
168
- },
162
+ }
163
+ },
169
164
 
170
- CompletedValidateEmail: ({ field }) => {
171
- if (field.value === model.email.value) {
172
- return [
173
- evo(model, {
174
- email: () => field,
175
- }),
176
- [],
177
- ]
178
- } else {
179
- return [model, []]
165
+ CompletedValidateEmail: ({ field }) => {
166
+ if (field.value === model.email.value) {
167
+ return {
168
+ model: evo(model, {
169
+ email: () => field,
170
+ }),
180
171
  }
181
- },
172
+ } else {
173
+ return { model }
174
+ }
175
+ },
182
176
 
183
- UpdatedMessageText: ({ value }) => [
184
- evo(model, {
185
- messageText: () => Valid({ value }),
186
- }),
187
- [],
188
- ],
177
+ UpdatedMessageText: ({ value }) => ({
178
+ model: evo(model, {
179
+ messageText: () => Valid({ value }),
180
+ }),
181
+ }),
189
182
 
190
- ClickedFormSubmit: () => {
191
- if (model.submission._tag === 'Submitting') {
192
- return [model, []]
193
- }
183
+ ClickedFormSubmit: () => {
184
+ if (model.submission._tag === 'Submitting') {
185
+ return { model }
186
+ }
194
187
 
195
- if (!isFormValid(model)) {
196
- return [model, []]
197
- }
188
+ if (!isFormValid(model)) {
189
+ return { model }
190
+ }
198
191
 
199
- return [
200
- evo(model, {
201
- submission: () => Submitting(),
202
- }),
203
- [
204
- SubmitForm({
205
- name: model.name.value,
206
- email: model.email.value,
207
- messageText: model.messageText.value,
208
- }),
209
- ],
210
- ]
211
- },
212
-
213
- SucceededSubmitForm: ({ name }) => [
214
- evo(model, {
215
- submission: () =>
216
- SubmitSuccess({
217
- confirmationText: `Welcome to the waitlist, ${name}! We'll be in touch soon.`,
218
- }),
192
+ return {
193
+ model: evo(model, {
194
+ submission: () => Submitting(),
219
195
  }),
220
- [],
221
- ],
222
-
223
- FailedSubmitForm: () => [
224
- evo(model, {
225
- submission: () =>
226
- SubmitError({
227
- error:
228
- 'Sorry, there was an error adding you to the waitlist. Please try again.',
229
- }),
230
- }),
231
- [],
232
- ],
196
+ commands: [
197
+ SubmitForm({
198
+ name: model.name.value,
199
+ email: model.email.value,
200
+ messageText: model.messageText.value,
201
+ }),
202
+ ],
203
+ }
233
204
  },
234
- )
205
+
206
+ SucceededSubmitForm: ({ name }) => ({
207
+ model: evo(model, {
208
+ submission: () =>
209
+ SubmitSuccess({
210
+ confirmationText: `Welcome to the waitlist, ${name}! We'll be in touch soon.`,
211
+ }),
212
+ }),
213
+ }),
214
+
215
+ FailedSubmitForm: () => ({
216
+ model: evo(model, {
217
+ submission: () =>
218
+ SubmitError({
219
+ error:
220
+ 'Sorry, there was an error adding you to the waitlist. Please try again.',
221
+ }),
222
+ }),
223
+ }),
224
+ })
235
225
 
236
226
  // COMMAND
237
227
 
@@ -21,8 +21,8 @@ import { subscriptions } from './subscription'
21
21
  import { update } from './update'
22
22
  import { view } from './view'
23
23
 
24
- export const init: Runtime.ApplicationInit<Model, Message> = () => [
25
- {
24
+ export const init: Runtime.ApplicationInit<Model, Message> = () => ({
25
+ model: {
26
26
  particles: [],
27
27
  nextId: 0,
28
28
  elapsedSeconds: 0,
@@ -53,7 +53,9 @@ export const init: Runtime.ApplicationInit<Model, Message> = () => [
53
53
  step: NOISE_SCALE_STEP,
54
54
  }),
55
55
  },
56
- Array.makeBy(INITIAL_PARTICLE_COUNT, () => GenerateAmbientParticle()),
57
- ]
56
+ commands: Array.makeBy(INITIAL_PARTICLE_COUNT, () =>
57
+ GenerateAmbientParticle(),
58
+ ),
59
+ })
58
60
 
59
61
  export { Message, Model, subscriptions, update, view }
@@ -35,7 +35,7 @@ import { Message } from './message'
35
35
  import { Model, Particle, Point } from './model'
36
36
  import { fractalNoise } from './noise'
37
37
 
38
- type UpdateReturn = readonly [Model, ReadonlyArray<Command.Command<Message>>]
38
+ type UpdateReturn = Update.Return<Model, Message>
39
39
 
40
40
  const computeFieldAngle = (
41
41
  point: Point,
@@ -215,13 +215,12 @@ const appendGeneratedParticle =
215
215
  initialAngle: generatedParticle.initialAngle,
216
216
  initialSpeedScale: generatedParticle.initialSpeedScale,
217
217
  }
218
- return [
219
- evo(model, {
218
+ return {
219
+ model: evo(model, {
220
220
  particles: Array.append(newParticle),
221
221
  nextId: Number.increment,
222
222
  }),
223
- [],
224
- ]
223
+ }
225
224
  }
226
225
 
227
226
  const foldFlowStrengthSliderOutMessage = M.type<Slider.OutMessage>().pipe(
@@ -229,7 +228,7 @@ const foldFlowStrengthSliderOutMessage = M.type<Slider.OutMessage>().pipe(
229
228
  M.tagsExhaustive({
230
229
  ChangedValue:
231
230
  ({ value }) =>
232
- model => [evo(model, { flowStrength: () => value }), []],
231
+ model => ({ model: evo(model, { flowStrength: () => value }) }),
233
232
  }),
234
233
  )
235
234
 
@@ -247,7 +246,7 @@ const foldNoiseScaleSliderOutMessage = M.type<Slider.OutMessage>().pipe(
247
246
  M.tagsExhaustive({
248
247
  ChangedValue:
249
248
  ({ value }) =>
250
- model => [evo(model, { noiseScale: () => value }), []],
249
+ model => ({ model: evo(model, { noiseScale: () => value }) }),
251
250
  }),
252
251
  )
253
252
 
@@ -279,37 +278,41 @@ export const update = (model: Model, message: Message) =>
279
278
  particles: () => advancedParticles,
280
279
  elapsedSeconds: () => nextElapsedSeconds,
281
280
  })
282
- return [nextModel, spawnAmbientParticles(advancedParticles.length)]
281
+ return {
282
+ model: nextModel,
283
+ commands: spawnAmbientParticles(advancedParticles.length),
284
+ }
283
285
  },
284
286
 
285
287
  CompletedGenerateAmbientParticle: appendGeneratedParticle(model),
286
288
 
287
289
  CompletedGenerateBurstParticle: appendGeneratedParticle(model),
288
290
 
289
- PressedCanvas: ({ x, y }) => [
291
+ PressedCanvas: ({ x, y }) => ({
290
292
  model,
291
- spawnBurstParticles(x, y, computeBurstHueAnchor(model.elapsedSeconds)),
292
- ],
293
+ commands: spawnBurstParticles(
294
+ x,
295
+ y,
296
+ computeBurstHueAnchor(model.elapsedSeconds),
297
+ ),
298
+ }),
293
299
 
294
- MovedPointer: ({ x, y }) => [
295
- evo(model, {
300
+ MovedPointer: ({ x, y }) => ({
301
+ model: evo(model, {
296
302
  maybeMousePosition: () => Option.some(Point.make({ x, y })),
297
303
  }),
298
- [],
299
- ],
304
+ }),
300
305
 
301
- ClickedTogglePlay: () => [
302
- evo(model, { isRunning: running => !running }),
303
- [],
304
- ],
306
+ ClickedTogglePlay: () => ({
307
+ model: evo(model, { isRunning: running => !running }),
308
+ }),
305
309
 
306
- ClickedReset: () => [
307
- evo(model, {
310
+ ClickedReset: () => ({
311
+ model: evo(model, {
308
312
  particles: () => [],
309
313
  maybeMousePosition: () => Option.none(),
310
314
  }),
311
- [],
312
- ],
315
+ }),
313
316
 
314
317
  GotFlowStrengthSliderMessage: ({ message }) =>
315
318
  foldFlowStrengthSlider(model, message),
@@ -9,7 +9,7 @@ import {
9
9
  Schema as S,
10
10
  pipe,
11
11
  } from 'effect'
12
- import { Command, Runtime } from 'foldkit'
12
+ import { Command, Runtime, type Update } from 'foldkit'
13
13
  import { Document, Html, HtmlBuilder } from 'foldkit/html'
14
14
  import { defineMessageUnion } from 'foldkit/message'
15
15
  import { evo } from 'foldkit/struct'
@@ -56,10 +56,9 @@ export const initialModel: Model = {
56
56
  uploads: [],
57
57
  }
58
58
 
59
- export const init: Runtime.ApplicationInit<Model, Message> = () => [
60
- initialModel,
61
- [],
62
- ]
59
+ export const init: Runtime.ApplicationInit<Model, Message> = () => ({
60
+ model: initialModel,
61
+ })
63
62
 
64
63
  // FAKE FILES
65
64
 
@@ -116,81 +115,84 @@ const setStatusForId = (uploadId: number, status: UploadStatus) =>
116
115
  upload.id === uploadId ? evo(upload, { status: () => status }) : upload,
117
116
  )
118
117
 
118
+ type UpdateReturn = Update.Return<Model, Message>
119
+
119
120
  export const update = (model: Model, message: Message) =>
120
- Message.match<readonly [Model, ReadonlyArray<Command.Command<Message>>]>(
121
- message,
122
- {
123
- ClickedStartUpload: () => {
124
- const fakeFile = fakeFileForUpload(model.uploadId)
125
- const startedUpload = Upload.make({
126
- id: model.uploadId,
127
- fileName: fakeFile.name,
128
- sizeMegabytes: fakeFile.sizeMegabytes,
129
- status: 'Uploading',
130
- })
131
- return [
132
- evo(model, {
133
- uploadId: Number.increment,
134
- uploads: Array.append(startedUpload),
121
+ Message.match<UpdateReturn>(message, {
122
+ ClickedStartUpload: () => {
123
+ const fakeFile = fakeFileForUpload(model.uploadId)
124
+ const startedUpload = Upload.make({
125
+ id: model.uploadId,
126
+ fileName: fakeFile.name,
127
+ sizeMegabytes: fakeFile.sizeMegabytes,
128
+ status: 'Uploading',
129
+ })
130
+ return {
131
+ model: evo(model, {
132
+ uploadId: Number.increment,
133
+ uploads: Array.append(startedUpload),
134
+ }),
135
+ commands: [
136
+ UploadFile({
137
+ uploadId: startedUpload.id,
138
+ sizeMegabytes: startedUpload.sizeMegabytes,
135
139
  }),
136
- [
137
- UploadFile({
138
- uploadId: startedUpload.id,
139
- sizeMegabytes: startedUpload.sizeMegabytes,
140
- }),
141
- ],
142
- ]
143
- },
140
+ ],
141
+ }
142
+ },
144
143
 
145
- ClickedCancelUpload: ({ uploadId }) => [
146
- model,
147
- [CancelUploadFile({ uploadId })],
148
- ],
144
+ ClickedCancelUpload: ({ uploadId }) => ({
145
+ model,
146
+ commands: [CancelUploadFile({ uploadId })],
147
+ }),
149
148
 
150
- ClickedCancelAllUploads: () => [
149
+ ClickedCancelAllUploads: () => {
150
+ return {
151
151
  model,
152
- pipe(
152
+ commands: pipe(
153
153
  model.uploads,
154
154
  Array.filter(upload => upload.status === 'Uploading'),
155
155
  Array.map(upload => CancelUploadFile({ uploadId: upload.id })),
156
156
  ),
157
- ],
157
+ }
158
+ },
158
159
 
159
- ClickedRestartUpload: ({ uploadId }) =>
160
- pipe(
161
- model.uploads,
162
- Array.findFirst(
163
- upload => upload.id === uploadId && upload.status === 'Cancelled',
164
- ),
165
- Option.match({
166
- onNone: () => [model, []],
167
- onSome: upload => [
168
- evo(model, { uploads: setStatusForId(uploadId, 'Uploading') }),
169
- [UploadFile({ uploadId, sizeMegabytes: upload.sizeMegabytes })],
160
+ ClickedRestartUpload: ({ uploadId }) =>
161
+ pipe(
162
+ model.uploads,
163
+ Array.findFirst(
164
+ upload => upload.id === uploadId && upload.status === 'Cancelled',
165
+ ),
166
+ Option.match({
167
+ onNone: () => ({ model }),
168
+ onSome: upload => ({
169
+ model: evo(model, {
170
+ uploads: setStatusForId(uploadId, 'Uploading'),
171
+ }),
172
+ commands: [
173
+ UploadFile({ uploadId, sizeMegabytes: upload.sizeMegabytes }),
170
174
  ],
171
175
  }),
172
- ),
176
+ }),
177
+ ),
173
178
 
174
- SucceededUploadFile: ({ uploadId }) => [
175
- evo(model, { uploads: setStatusForId(uploadId, 'Done') }),
176
- [],
177
- ],
178
-
179
- CompletedCancelUploadFile: ({ uploadId, outcome }) =>
180
- M.value(outcome).pipe(
181
- M.withReturnType<
182
- readonly [Model, ReadonlyArray<Command.Command<Message>>]
183
- >(),
184
- M.tagsExhaustive({
185
- Interrupted: () => [
186
- evo(model, { uploads: setStatusForId(uploadId, 'Cancelled') }),
187
- [],
188
- ],
189
- NotFound: () => [model, []],
179
+ SucceededUploadFile: ({ uploadId }) => ({
180
+ model: evo(model, { uploads: setStatusForId(uploadId, 'Done') }),
181
+ }),
182
+
183
+ CompletedCancelUploadFile: ({ uploadId, outcome }) =>
184
+ M.value(outcome).pipe(
185
+ M.withReturnType<UpdateReturn>(),
186
+ M.tagsExhaustive({
187
+ Interrupted: () => ({
188
+ model: evo(model, {
189
+ uploads: setStatusForId(uploadId, 'Cancelled'),
190
+ }),
190
191
  }),
191
- ),
192
- },
193
- )
192
+ NotFound: () => ({ model }),
193
+ }),
194
+ ),
195
+ })
194
196
 
195
197
  // VIEW
196
198
 
@@ -48,8 +48,8 @@ export const init: Runtime.ApplicationInit<Model, Message, Flags> = ({
48
48
  initialWorkHistoryEntryId,
49
49
  initialEducationEntryId,
50
50
  initialSkillsEntryId,
51
- }) => [
52
- {
51
+ }) => ({
52
+ model: {
53
53
  currentStep: 'PersonalInfo',
54
54
  personalInfo: PersonalInfo.init(today),
55
55
  workHistory: WorkHistory.init(today, initialWorkHistoryEntryId),
@@ -63,7 +63,6 @@ export const init: Runtime.ApplicationInit<Model, Message, Flags> = ({
63
63
  stepTabs: Tabs.init({ id: 'step-tabs' }),
64
64
  isSubmitAttempted: false,
65
65
  },
66
- [],
67
- ]
66
+ })
68
67
 
69
68
  export { Message, Model, update, view }
@@ -1,5 +1,5 @@
1
1
  import { Array, Match as M, Option, Schema as S, pipe } from 'effect'
2
- import { Command, File, Update } from 'foldkit'
2
+ import { File, Update } from 'foldkit'
3
3
  import { defineMessageUnion } from 'foldkit/message'
4
4
  import { evo } from 'foldkit/struct'
5
5
 
@@ -37,15 +37,13 @@ export const init = (): Model => ({
37
37
 
38
38
  // UPDATE
39
39
 
40
- type UpdateReturn = readonly [Model, ReadonlyArray<Command.Command<Message>>]
41
-
42
40
  const foldResumeDropOutMessage = M.type<FileDrop.OutMessage>().pipe(
43
41
  M.withReturnType<Update.Step<Model, Message>>(),
44
42
  M.tagsExhaustive({
45
43
  ReceivedFiles:
46
44
  ({ files }) =>
47
- model => [
48
- evo(model, {
45
+ model => ({
46
+ model: evo(model, {
49
47
  maybeResume: () =>
50
48
  pipe(
51
49
  files,
@@ -53,9 +51,8 @@ const foldResumeDropOutMessage = M.type<FileDrop.OutMessage>().pipe(
53
51
  Option.orElse(() => model.maybeResume),
54
52
  ),
55
53
  }),
56
- [],
57
- ],
58
- RejectedNonFiles: () => model => [model, []],
54
+ }),
55
+ RejectedNonFiles: () => model => ({ model }),
59
56
  }),
60
57
  )
61
58
 
@@ -73,13 +70,12 @@ const foldAdditionalFilesDropOutMessage = M.type<FileDrop.OutMessage>().pipe(
73
70
  M.tagsExhaustive({
74
71
  ReceivedFiles:
75
72
  ({ files }) =>
76
- model => [
77
- evo(model, {
73
+ model => ({
74
+ model: evo(model, {
78
75
  additionalFiles: Array.appendAll(files),
79
76
  }),
80
- [],
81
- ],
82
- RejectedNonFiles: () => model => [model, []],
77
+ }),
78
+ RejectedNonFiles: () => model => ({ model }),
83
79
  }),
84
80
  )
85
81
 
@@ -94,18 +90,19 @@ const foldAdditionalFilesDrop = Update.foldChild({
94
90
  })
95
91
 
96
92
  export const update = (model: Model, message: Message) =>
97
- Message.match<UpdateReturn>(message, {
93
+ Message.match<Update.Return<Model, Message>>(message, {
98
94
  GotResumeDropMessage: ({ message }) => foldResumeDrop(model, message),
99
95
 
100
96
  GotAdditionalFilesDropMessage: ({ message }) =>
101
97
  foldAdditionalFilesDrop(model, message),
102
98
 
103
- RemovedResume: () => [evo(model, { maybeResume: () => Option.none() }), []],
99
+ RemovedResume: () => ({
100
+ model: evo(model, { maybeResume: () => Option.none() }),
101
+ }),
104
102
 
105
- RemovedAdditionalFile: ({ fileIndex }) => [
106
- evo(model, {
103
+ RemovedAdditionalFile: ({ fileIndex }) => ({
104
+ model: evo(model, {
107
105
  additionalFiles: Array.remove(fileIndex),
108
106
  }),
109
- [],
110
- ],
107
+ }),
111
108
  })
@@ -1,5 +1,5 @@
1
1
  import { Schema as S } from 'effect'
2
- import { Command } from 'foldkit'
2
+ import { type Update } from 'foldkit'
3
3
  import { defineMessageUnion } from 'foldkit/message'
4
4
  import { evo } from 'foldkit/struct'
5
5
 
@@ -26,9 +26,9 @@ export const init = (): Model => ({
26
26
 
27
27
  // UPDATE
28
28
 
29
- type UpdateReturn = readonly [Model, ReadonlyArray<Command.Command<Message>>]
30
-
31
29
  export const update = (model: Model, message: Message) =>
32
- Message.match<UpdateReturn>(message, {
33
- UpdatedContent: ({ value }) => [evo(model, { content: () => value }), []],
30
+ Message.match<Update.Return<Model, Message>>(message, {
31
+ UpdatedContent: ({ value }) => ({
32
+ model: evo(model, { content: () => value }),
33
+ }),
34
34
  })