foldkit 0.150.0 → 0.151.0

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 (97) hide show
  1. package/README.md +13 -13
  2. package/dist/asyncData/asyncData.d.ts +3 -4
  3. package/dist/asyncData/asyncData.d.ts.map +1 -1
  4. package/dist/asyncData/asyncData.js +3 -4
  5. package/dist/command/index.d.ts +14 -13
  6. package/dist/command/index.d.ts.map +1 -1
  7. package/dist/command/index.js +13 -12
  8. package/dist/experimental/machine/machine.d.ts +9 -2
  9. package/dist/experimental/machine/machine.d.ts.map +1 -1
  10. package/dist/experimental/machine/machine.js +3 -3
  11. package/dist/experimental/server/server.d.ts +6 -5
  12. package/dist/experimental/server/server.d.ts.map +1 -1
  13. package/dist/experimental/server/server.js +1 -2
  14. package/dist/html/submodel.d.ts +4 -4
  15. package/dist/html/submodel.d.ts.map +1 -1
  16. package/dist/runtime/runtime.d.ts +11 -47
  17. package/dist/runtime/runtime.d.ts.map +1 -1
  18. package/dist/runtime/runtime.js +9 -5
  19. package/dist/test/apps/attributes.d.ts +11 -4
  20. package/dist/test/apps/attributes.d.ts.map +1 -1
  21. package/dist/test/apps/attributes.js +1 -1
  22. package/dist/test/apps/bubbling.d.ts +13 -4
  23. package/dist/test/apps/bubbling.d.ts.map +1 -1
  24. package/dist/test/apps/bubbling.js +8 -6
  25. package/dist/test/apps/colorPicker.d.ts +11 -3
  26. package/dist/test/apps/colorPicker.d.ts.map +1 -1
  27. package/dist/test/apps/colorPicker.js +3 -1
  28. package/dist/test/apps/contextMenu.d.ts +16 -8
  29. package/dist/test/apps/contextMenu.d.ts.map +1 -1
  30. package/dist/test/apps/contextMenu.js +3 -4
  31. package/dist/test/apps/counter.d.ts +10 -10
  32. package/dist/test/apps/counter.d.ts.map +1 -1
  33. package/dist/test/apps/counter.js +26 -20
  34. package/dist/test/apps/crashOnRender.d.ts +12 -12
  35. package/dist/test/apps/crashOnRender.d.ts.map +1 -1
  36. package/dist/test/apps/crashOnRender.js +6 -7
  37. package/dist/test/apps/drafts.d.ts +10 -10
  38. package/dist/test/apps/drafts.d.ts.map +1 -1
  39. package/dist/test/apps/drafts.js +7 -5
  40. package/dist/test/apps/feedSocket.d.ts +19 -4
  41. package/dist/test/apps/feedSocket.d.ts.map +1 -1
  42. package/dist/test/apps/feedSocket.js +12 -7
  43. package/dist/test/apps/fileUpload.d.ts +11 -3
  44. package/dist/test/apps/fileUpload.d.ts.map +1 -1
  45. package/dist/test/apps/fileUpload.js +3 -1
  46. package/dist/test/apps/formChild.d.ts +48 -3
  47. package/dist/test/apps/formChild.d.ts.map +1 -1
  48. package/dist/test/apps/formChild.js +33 -38
  49. package/dist/test/apps/interactions.d.ts +25 -7
  50. package/dist/test/apps/interactions.d.ts.map +1 -1
  51. package/dist/test/apps/interactions.js +20 -10
  52. package/dist/test/apps/keypress.d.ts +15 -4
  53. package/dist/test/apps/keypress.d.ts.map +1 -1
  54. package/dist/test/apps/keypress.js +13 -5
  55. package/dist/test/apps/login.d.ts +13 -13
  56. package/dist/test/apps/login.d.ts.map +1 -1
  57. package/dist/test/apps/login.js +28 -18
  58. package/dist/test/apps/logoutButton.d.ts +15 -6
  59. package/dist/test/apps/logoutButton.d.ts.map +1 -1
  60. package/dist/test/apps/logoutButton.js +6 -3
  61. package/dist/test/apps/mountPanel.d.ts +25 -5
  62. package/dist/test/apps/mountPanel.d.ts.map +1 -1
  63. package/dist/test/apps/mountPanel.js +14 -10
  64. package/dist/test/apps/multiRole.d.ts +10 -3
  65. package/dist/test/apps/multiRole.d.ts.map +1 -1
  66. package/dist/test/apps/multiRole.js +5 -2
  67. package/dist/test/apps/pointer.d.ts +16 -5
  68. package/dist/test/apps/pointer.d.ts.map +1 -1
  69. package/dist/test/apps/pointer.js +6 -8
  70. package/dist/test/apps/resumeUpload.d.ts +25 -4
  71. package/dist/test/apps/resumeUpload.d.ts.map +1 -1
  72. package/dist/test/apps/resumeUpload.js +16 -15
  73. package/dist/test/apps/scorePanel.d.ts +10 -3
  74. package/dist/test/apps/scorePanel.d.ts.map +1 -1
  75. package/dist/test/apps/scorePanel.js +3 -1
  76. package/dist/test/apps/selectiveKeys.d.ts +14 -3
  77. package/dist/test/apps/selectiveKeys.d.ts.map +1 -1
  78. package/dist/test/apps/selectiveKeys.js +7 -3
  79. package/dist/test/apps/uploads.d.ts +13 -13
  80. package/dist/test/apps/uploads.d.ts.map +1 -1
  81. package/dist/test/apps/uploads.js +23 -24
  82. package/dist/test/internal.d.ts +18 -3
  83. package/dist/test/internal.d.ts.map +1 -1
  84. package/dist/test/internal.js +8 -16
  85. package/dist/test/scene.d.ts +16 -19
  86. package/dist/test/scene.d.ts.map +1 -1
  87. package/dist/test/scene.js +11 -27
  88. package/dist/test/story.d.ts +16 -8
  89. package/dist/test/story.d.ts.map +1 -1
  90. package/dist/test/story.js +12 -17
  91. package/dist/update/public.d.ts +2 -2
  92. package/dist/update/public.d.ts.map +1 -1
  93. package/dist/update/public.js +1 -1
  94. package/dist/update/update.d.ts +143 -69
  95. package/dist/update/update.d.ts.map +1 -1
  96. package/dist/update/update.js +72 -42
  97. package/package.json +1 -1
@@ -1,40 +1,79 @@
1
1
  import { Option } from 'effect';
2
2
  import { type AsyncData } from '../asyncData/index.js';
3
3
  import { type Command } from '../command/index.js';
4
- /** The Commands half of an update return: every Command the update wants
5
- * the runtime to run, in order. `R` is the services the Commands need
6
- * and defaults to `never` for applications without resources.
4
+ /** The Commands collection an update return may include. The collection keeps
5
+ * the order in which the update returned them, but the runtime forks the
6
+ * Commands independently. `R` is the services the Commands need and defaults
7
+ * to `never` for applications without resources.
7
8
  *
8
- * Each update module pins its concrete types once and uses the alias
9
- * throughout; the root update and every Submodel define their own:
9
+ * Name an alias when a module reuses the same Message and service types:
10
10
  *
11
11
  * ```ts
12
12
  * export type Commands = Update.Commands<Message, AppServices>
13
13
  * ``` */
14
14
  export type Commands<Message, R = never> = ReadonlyArray<Command<Message, never, R>>;
15
- /** The pair every update function returns: the next Model and the
16
- * Commands to run.
15
+ /** The record an update returns when it cannot emit an OutMessage: the next
16
+ * Model and any Commands to run.
17
17
  *
18
- * Each update module pins its concrete types once and aliases the
19
- * result, the root update and every Submodel alike:
18
+ * Inline the type when a matcher is its only use:
20
19
  *
21
20
  * ```ts
22
- * export type UpdateReturn = Update.Return<Model, Message>
23
- * export const withUpdateReturn = M.withReturnType<UpdateReturn>()
24
- * ``` */
25
- export type Return<Model, Message, R = never> = readonly [
26
- Model,
27
- Commands<Message, R>
28
- ];
29
- /** The return shape of an update that also surfaces an OutMessage to its
30
- * parent. The third element is an `Option`: the update always returns
31
- * the channel, and `None` means there is nothing for the parent this
32
- * time. Named for the shape, not the caller: a Submodel without an
33
- * OutMessage channel returns a plain {@link Return}. */
34
- export type ReturnWithOutMessage<Model, Message, OutMessage, R = never> = readonly [Model, Commands<Message, R>, Option.Option<OutMessage>];
21
+ * export const update = (model: Model, message: Message) =>
22
+ * Message.match<Update.Return<Model, Message>>(message, {
23
+ * ClickedSave: () => ({ model, commands: [Save()] }),
24
+ * SucceededSave: ({ note }) => ({
25
+ * model: evo(model, { note: () => note }),
26
+ * }),
27
+ * })
28
+ * ```
29
+ *
30
+ * Give it a local `UpdateReturn` alias when another matcher or helper in the
31
+ * module needs the same type. */
32
+ export type Return<Model, Message, R = never> = Readonly<{
33
+ model: Model;
34
+ commands?: Commands<Message, R>;
35
+ /** Marks this as a result that cannot emit an OutMessage. TypeScript rejects
36
+ * assigning an OutMessage-producing result to this type, so a caller cannot
37
+ * accidentally accept the Model and Commands while losing the OutMessage. */
38
+ outMessage?: never;
39
+ }>;
40
+ /** The return shape of an update that can also surface an OutMessage to its
41
+ * parent. Omit `commands` when the update statically creates none. Return a
42
+ * computed Commands collection directly, even when it may be empty. Omit
43
+ * `outMessage` when the update emitted nothing. A Submodel that cannot emit
44
+ * an OutMessage returns {@link Return} instead. */
45
+ export type ReturnWithOutMessage<Model, Message, OutMessage, R = never> = Readonly<{
46
+ model: Model;
47
+ commands?: Commands<Message, R>;
48
+ outMessage?: OutMessage;
49
+ }>;
50
+ /** Adds a known or optional OutMessage to a plain update return while
51
+ * preserving its Model and Commands. Use this helper when attaching to an
52
+ * existing return or when the value has the type `OutMessage | undefined`.
53
+ * `undefined` means that the operation emitted no OutMessage, so the returned
54
+ * record omits the property.
55
+ *
56
+ * The input must be a {@link Return}, so this helper cannot replace an
57
+ * OutMessage that an update already emitted.
58
+ *
59
+ * ```ts
60
+ * const editorSave = Update.combine(model, [writeDraft, clearErrors])
61
+ *
62
+ * return pipe(editorSave, Update.withOutMessage(outMessage))
63
+ * ```
64
+ *
65
+ * When the OutMessage is already known while constructing a new result,
66
+ * include it directly: `{ model, commands, outMessage }`. If the OutMessage
67
+ * may be `undefined`, pass the new result first:
68
+ * `Update.withOutMessage({ model, commands }, outMessage)`. */
69
+ export declare const withOutMessage: {
70
+ <OutMessage>(outMessage: OutMessage | undefined): <Model, Message, R = never>(updateReturn: Return<Model, Message, R>) => ReturnWithOutMessage<Model, Message, OutMessage, R>;
71
+ <Model, Message, OutMessage, R = never>(updateReturn: Return<Model, Message, R>, outMessage: OutMessage | undefined): ReturnWithOutMessage<Model, Message, OutMessage, R>;
72
+ };
35
73
  /** One self-contained edit to the Model paired with the Commands to run:
36
74
  * the unit {@link combine} composes. A step that needs arguments is a
37
- * function returning a Step (`(noteId: NoteId) => Step<...>`). */
75
+ * function returning a Step
76
+ * (`(noteId: NoteId) => Update.Step<Model, Message>`). */
38
77
  export type Step<Model, Message, R = never> = (model: Model) => Return<Model, Message, R>;
39
78
  /** Composes a list of update steps into one. Each step runs against the
40
79
  * Model the previous step produced, and every step's Commands are
@@ -48,7 +87,7 @@ export type Step<Model, Message, R = never> = (model: Model) => Return<Model, Me
48
87
  * Steps only ever accumulate Commands; a step cannot cancel or replace
49
88
  * another step's Commands, and no Command runs during the fold. The
50
89
  * runtime runs the batch after update returns. `combine([])` returns
51
- * `[model, []]`.
90
+ * `{ model }`.
52
91
  *
53
92
  * ```ts
54
93
  * SucceededUpdateNote: ({ note }) =>
@@ -86,9 +125,9 @@ export type Refreshable<Model, Message, A, E, R = never> = Readonly<{
86
125
  * cache: read the entry, ask `revalidate` whether it should transition,
87
126
  * and only when it says yes write the transitioned state and emit the
88
127
  * load Command. When `revalidate` returns `None` (a missing entry, or a
89
- * state with nothing to revalidate) the step returns `[model, []]`: same
90
- * Model, no Command. That one rule is what makes blanket revalidation
91
- * safe, because only the caches that actually hold data reload.
128
+ * state with nothing to revalidate) the step returns `{ model }`: same
129
+ * Model, no Command. A handler can list every affected cache, and only the
130
+ * caches that currently hold data reload.
92
131
  *
93
132
  * ```ts
94
133
  * const refreshAllNotes = refresh({
@@ -100,7 +139,7 @@ export type Refreshable<Model, Message, A, E, R = never> = Readonly<{
100
139
  * ``` */
101
140
  export declare const refresh: <Model, Message, A, E, R = never>(refreshable: Refreshable<Model, Message, A, E, R>) => Step<Model, Message, R>;
102
141
  /** The four capabilities that fold one child Submodel's update into the
103
- * parent, for a child without an OutMessage channel.
142
+ * parent, for a child whose update cannot emit an OutMessage.
104
143
  *
105
144
  * - `update`: the child update function to run.
106
145
  * - `read`: the getter half of the lens onto the child: reads the child
@@ -122,12 +161,11 @@ export type ChildFold<ParentModel, ParentMessage, ChildModel, Input, ChildMessag
122
161
  /** The lifters a `foldOutMessage` receives as its second parameter,
123
162
  * already bound to the fold config's `toParentMessage`.
124
163
  *
125
- * The fold lifts the Commands the child's `update` returns on its own.
126
- * This covers the other case: a Command the parent returns on the
127
- * child's behalf from the OutMessage Step, whose result Message is the
128
- * child's and therefore still needs wrapping, such as a parent handling
129
- * a child's `Requested*` fact by returning the child's Command that
130
- * fulfills it, built with context only the parent holds.
164
+ * The fold already lifts the Commands returned by the child's `update`.
165
+ * Use these lifters for a Command returned by the parent's OutMessage Step
166
+ * when that Command still produces the child's Message. For example, the
167
+ * parent may handle a child's `Requested*` fact by returning a child Command
168
+ * built with routing context only the parent holds.
131
169
  *
132
170
  * The lifters apply the same lift the fold gives the child's own
133
171
  * Commands, so the Step writes no `Command.mapMessage` call and keeps
@@ -138,20 +176,25 @@ export type ChildFold<ParentModel, ParentMessage, ChildModel, Input, ChildMessag
138
176
  * OutMessage value directly:
139
177
  *
140
178
  * ```ts
141
- * const foldLoginOutMessage: (
179
+ * const foldLoginOutMessage = (
142
180
  * outMessage: Login.OutMessage,
143
- * context: Update.FoldContext<Login.Message, Message>,
144
- * ) => Update.Step<Model, Message> = (outMessage, { liftCommand }) =>
145
- * Login.OutMessage.match<Update.Step<Model, Message>>(outMessage, {
146
- * RequestedMagicLink: ({ email }) => model => [
147
- * model,
148
- * [
149
- * liftCommand(
150
- * Login.SendMagicLink({ email, redirectRoute: model.route }),
151
- * ),
152
- * ],
153
- * ],
154
- * })
181
+ * { liftCommand }: Update.FoldContext<Login.Message, Message>,
182
+ * ) =>
183
+ * M.value(outMessage).pipe(
184
+ * M.withReturnType<Update.Step<Model, Message>>(),
185
+ * M.tagsExhaustive({
186
+ * RequestedMagicLink:
187
+ * ({ email }) =>
188
+ * model => ({
189
+ * model,
190
+ * commands: [
191
+ * liftCommand(
192
+ * Login.SendMagicLink({ email, redirectRoute: model.route }),
193
+ * ),
194
+ * ],
195
+ * }),
196
+ * }),
197
+ * )
155
198
  * ``` */
156
199
  export type FoldContext<ChildMessage, ParentMessage> = Readonly<{
157
200
  liftCommand: <E = never, R = never>(command: Command<ChildMessage, E, R>) => Command<ParentMessage, E, R>;
@@ -176,24 +219,28 @@ export type ChildFoldWithOutMessage<ParentModel, ParentMessage, ChildModel, Inpu
176
219
  foldOutMessage: (outMessage: ChildOutMessage, context: FoldContext<ChildMessage, ParentMessage>) => Step<ParentModel, ParentMessage, R>;
177
220
  }>;
178
221
  /** {@link ChildFoldWithOutMessage} for a parent that is itself a
179
- * Submodel, so the fold's result carries the parent's own OutMessage
180
- * channel as a third tuple element. Adds:
222
+ * Submodel, so the fold can return the parent's own OutMessage. Adds:
181
223
  *
182
224
  * - `toParentOutMessage`: lifts the child's OutMessage into the
183
- * parent's own OutMessage; `None` passes nothing upward. When the
184
- * child returns no OutMessage the fold's third element is `None`.
225
+ * parent's own OutMessage. Return `undefined` for a named child variant
226
+ * that stops at this parent. When the child returns no OutMessage, the fold
227
+ * omits `outMessage`.
185
228
  * - `foldOutMessage` stays available for a parent that also updates
186
229
  * its own state from the child's OutMessage, and is optional here.
187
230
  *
188
- * A parent Submodel embedding a child with no OutMessage channel needs
189
- * no config at all: spread the plain fold into its return,
190
- * `[...foldStartDate(model, message), Option.none()]`. */
231
+ * Use this shape only when `toParentOutMessage` forwards at least one child
232
+ * OutMessage from the current Submodel to its parent. If no child OutMessage
233
+ * is forwarded, use {@link ChildFoldWithOutMessage}. Its plain result is
234
+ * valid wherever the parent accepts {@link ReturnWithOutMessage}, because
235
+ * emitting no OutMessage is valid. Local handling through `foldOutMessage`
236
+ * is independent, so a forwarded child OutMessage may also update the
237
+ * current parent. */
191
238
  export type ChildFoldWithParentOutMessage<ParentModel, ParentMessage, ChildModel, Input, ChildMessage, ChildOutMessage, ParentOutMessage, R = never> = Readonly<{
192
239
  update: (childModel: ChildModel, input: Input) => ReturnWithOutMessage<ChildModel, ChildMessage, ChildOutMessage, R>;
193
240
  read: (model: ParentModel) => Option.Option<ChildModel>;
194
241
  write: (model: ParentModel, nextChildModel: ChildModel) => ParentModel;
195
242
  toParentMessage: (message: ChildMessage) => ParentMessage;
196
- toParentOutMessage: (outMessage: ChildOutMessage) => Option.Option<ParentOutMessage>;
243
+ toParentOutMessage: (outMessage: ChildOutMessage) => ParentOutMessage | undefined;
197
244
  foldOutMessage?: (outMessage: ChildOutMessage, context: FoldContext<ChildMessage, ParentMessage>) => Step<ParentModel, ParentMessage, R>;
198
245
  }>;
199
246
  /** {@link Step} for an update that also surfaces an OutMessage to its
@@ -237,7 +284,7 @@ export type FoldWithOutMessage<ParentModel, ParentMessage, Input, ParentOutMessa
237
284
  * The fold runs `update` against the child Model `read` returns, writes
238
285
  * the child back, and lifts the child's Commands through
239
286
  * `toParentMessage`. When `read` returns `None` the fold returns
240
- * `[model, []]`: a Message for an unmounted child is a no-op. When the
287
+ * `{ model }`: a Message for an unmounted child is a no-op. When the
241
288
  * child's update returns an OutMessage, `foldOutMessage` runs against
242
289
  * the Model with the child already written back, and its Commands
243
290
  * follow the child's in the returned batch.
@@ -250,8 +297,10 @@ export type FoldWithOutMessage<ParentModel, ParentMessage, Input, ParentOutMessa
250
297
  *
251
298
  * A parent that is itself a Submodel passes a
252
299
  * {@link ChildFoldWithParentOutMessage} and receives a
253
- * {@link FoldWithOutMessage}, whose results carry the parent's own
254
- * OutMessage channel as a third element.
300
+ * {@link FoldWithOutMessage}, whose results may include the parent's own
301
+ * OutMessage. Add `toParentOutMessage` only when it forwards at least one
302
+ * child OutMessage from the current Submodel to its parent. Omit
303
+ * `toParentOutMessage` when the local `foldOutMessage` handles every variant.
255
304
  *
256
305
  * An entry point that takes nothing but the child Model, such as
257
306
  * `Dialog.close`, has no input to pass: fold it with
@@ -264,7 +313,7 @@ export type FoldWithOutMessage<ParentModel, ParentMessage, Input, ParentOutMessa
264
313
  * ```ts
265
314
  * const enterJoinedRoom = (roomId: string, player: Player): UpdateStep =>
266
315
  * Update.combine([
267
- * model => [model, [NavigateToRoom({ roomId })]],
316
+ * model => ({ model, commands: [NavigateToRoom({ roomId })] }),
268
317
  * Update.foldChild({
269
318
  * update: (room: Room.Model, joinedPlayer: Player) =>
270
319
  * Room.informJoined(room, joinedPlayer, { roomId }),
@@ -290,10 +339,11 @@ export type ChildStepFold<ParentModel, ParentMessage, ChildModel, ChildMessage,
290
339
  write: (model: ParentModel, nextChildModel: ChildModel) => ParentModel;
291
340
  toParentMessage: (message: ChildMessage) => ParentMessage;
292
341
  }>;
293
- /** {@link ChildStepFold} for an entry point whose return carries the child's
294
- * OutMessage channel, adding `foldOutMessage`. It behaves exactly as it does
295
- * in {@link ChildFoldWithOutMessage}, down to the optional second parameter,
296
- * a {@link FoldContext} of lifters bound to `toParentMessage`. */
342
+ /** {@link ChildStepFold} for an entry point that can emit the child's
343
+ * OutMessage, adding `foldOutMessage`. The function has the same contract as
344
+ * `foldOutMessage` in {@link ChildFoldWithOutMessage}, including the optional
345
+ * second parameter: a {@link FoldContext} of lifters bound to
346
+ * `toParentMessage`. */
297
347
  export type ChildStepFoldWithOutMessage<ParentModel, ParentMessage, ChildModel, ChildMessage, ChildOutMessage, R = never> = Readonly<{
298
348
  update: (childModel: ChildModel) => ReturnWithOutMessage<ChildModel, ChildMessage, ChildOutMessage, R>;
299
349
  read: (model: ParentModel) => Option.Option<ChildModel>;
@@ -301,6 +351,25 @@ export type ChildStepFoldWithOutMessage<ParentModel, ParentMessage, ChildModel,
301
351
  toParentMessage: (message: ChildMessage) => ParentMessage;
302
352
  foldOutMessage: (outMessage: ChildOutMessage, context: FoldContext<ChildMessage, ParentMessage>) => Step<ParentModel, ParentMessage, R>;
303
353
  }>;
354
+ /** {@link ChildStepFoldWithOutMessage} for a parent that is itself a
355
+ * Submodel. `toParentOutMessage` turns the child's OutMessage into the
356
+ * parent's OutMessage. Return `undefined` for a named child variant that
357
+ * stops at this parent. `foldOutMessage` remains available when the parent
358
+ * also updates its own state from the child's OutMessage.
359
+ *
360
+ * Use this shape only when `toParentOutMessage` forwards at least one child
361
+ * OutMessage from the current Submodel to its parent. If no child OutMessage
362
+ * is forwarded, use {@link ChildStepFoldWithOutMessage}. Local handling
363
+ * through `foldOutMessage` is independent, so a forwarded child OutMessage
364
+ * may also update the current parent. */
365
+ export type ChildStepFoldWithParentOutMessage<ParentModel, ParentMessage, ChildModel, ChildMessage, ChildOutMessage, ParentOutMessage, R = never> = Readonly<{
366
+ update: (childModel: ChildModel) => ReturnWithOutMessage<ChildModel, ChildMessage, ChildOutMessage, R>;
367
+ read: (model: ParentModel) => Option.Option<ChildModel>;
368
+ write: (model: ParentModel, nextChildModel: ChildModel) => ParentModel;
369
+ toParentMessage: (message: ChildMessage) => ParentMessage;
370
+ toParentOutMessage: (outMessage: ChildOutMessage) => ParentOutMessage | undefined;
371
+ foldOutMessage?: (outMessage: ChildOutMessage, context: FoldContext<ChildMessage, ParentMessage>) => Step<ParentModel, ParentMessage, R>;
372
+ }>;
304
373
  /** Folds a child entry point that takes nothing but the child Model, and
305
374
  * returns the {@link Step} directly. Everything else matches
306
375
  * {@link foldChild}: the child is read, updated, and written back, its
@@ -325,14 +394,19 @@ export type ChildStepFoldWithOutMessage<ParentModel, ParentMessage, ChildModel,
325
394
  * Update.combine(model, [writeRouteFields, foldMobileMenuDialogClose])
326
395
  * ```
327
396
  *
328
- * `foldOutMessage` takes the same optional second parameter `foldChild`'s
329
- * does, a {@link FoldContext} carrying `liftCommand` and `liftCommands` bound
330
- * to this config's `toParentMessage`, for a Command the Step returns whose
331
- * result is the child's Message.
397
+ * `foldOutMessage` takes the same optional second parameter as
398
+ * {@link foldChild}: a {@link FoldContext} carrying `liftCommand` and
399
+ * `liftCommands` bound to this config's `toParentMessage`, for a Command the
400
+ * Step returns whose result is the child's Message.
332
401
  *
333
- * A parent that is itself a Submodel, and so needs its own OutMessage
334
- * channel on the result, uses {@link foldChild}. */
402
+ * A parent that is itself a Submodel adds `toParentOutMessage` when it
403
+ * forwards at least one child OutMessage to its own parent and receives a
404
+ * {@link StepWithOutMessage}, just as the input-taking {@link foldChild}
405
+ * returns a {@link FoldWithOutMessage}. When no child OutMessage is
406
+ * forwarded, omit the lift and use the plain Step directly. Local handling
407
+ * through `foldOutMessage` is independent of forwarding. */
335
408
  export declare const foldChildStep: {
409
+ <ParentModel, ParentMessage, ChildModel, ChildMessage, ChildOutMessage, ParentOutMessage, R = never>(childFold: ChildStepFoldWithParentOutMessage<ParentModel, ParentMessage, ChildModel, ChildMessage, ChildOutMessage, ParentOutMessage, R>): StepWithOutMessage<ParentModel, ParentMessage, ParentOutMessage, R>;
336
410
  <ParentModel, ParentMessage, ChildModel, ChildMessage, ChildOutMessage, R = never>(childFold: ChildStepFoldWithOutMessage<ParentModel, ParentMessage, ChildModel, ChildMessage, ChildOutMessage, R>): Step<ParentModel, ParentMessage, R>;
337
411
  <ParentModel, ParentMessage, ChildModel, ChildMessage, R = never>(childFold: ChildStepFold<ParentModel, ParentMessage, ChildModel, ChildMessage, R>): Step<ParentModel, ParentMessage, R>;
338
412
  };
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/update/update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/update/update.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,25 @@
1
1
  import { Array, Function, Option, pipe } from 'effect';
2
2
  import { mapMessage, mapMessages } from '../command/index.js';
3
+ /** Adds a known or optional OutMessage to a plain update return while
4
+ * preserving its Model and Commands. Use this helper when attaching to an
5
+ * existing return or when the value has the type `OutMessage | undefined`.
6
+ * `undefined` means that the operation emitted no OutMessage, so the returned
7
+ * record omits the property.
8
+ *
9
+ * The input must be a {@link Return}, so this helper cannot replace an
10
+ * OutMessage that an update already emitted.
11
+ *
12
+ * ```ts
13
+ * const editorSave = Update.combine(model, [writeDraft, clearErrors])
14
+ *
15
+ * return pipe(editorSave, Update.withOutMessage(outMessage))
16
+ * ```
17
+ *
18
+ * When the OutMessage is already known while constructing a new result,
19
+ * include it directly: `{ model, commands, outMessage }`. If the OutMessage
20
+ * may be `undefined`, pass the new result first:
21
+ * `Update.withOutMessage({ model, commands }, outMessage)`. */
22
+ export const withOutMessage = Function.dual(2, (updateReturn, outMessage) => outMessage === undefined ? updateReturn : { ...updateReturn, outMessage });
3
23
  /** Composes a list of update steps into one. Each step runs against the
4
24
  * Model the previous step produced, and every step's Commands are
5
25
  * concatenated into a single batch, in step order.
@@ -12,7 +32,7 @@ import { mapMessage, mapMessages } from '../command/index.js';
12
32
  * Steps only ever accumulate Commands; a step cannot cancel or replace
13
33
  * another step's Commands, and no Command runs during the fold. The
14
34
  * runtime runs the batch after update returns. `combine([])` returns
15
- * `[model, []]`.
35
+ * `{ model }`.
16
36
  *
17
37
  * ```ts
18
38
  * SucceededUpdateNote: ({ note }) =>
@@ -26,19 +46,20 @@ import { mapMessage, mapMessages } from '../command/index.js';
26
46
  * ])
27
47
  * ``` */
28
48
  export const combine = Function.dual(2, (model, steps) => {
29
- const seed = [model, []];
30
- return Array.reduce(steps, seed, ([currentModel, commands], step) => {
31
- const [nextModel, nextCommands] = step(currentModel);
32
- return [nextModel, [...commands, ...nextCommands]];
49
+ const seed = { model };
50
+ return Array.reduce(steps, seed, (current, step) => {
51
+ const next = step(current.model);
52
+ const commands = [...(current.commands ?? []), ...(next.commands ?? [])];
53
+ return { model: next.model, commands };
33
54
  });
34
55
  });
35
56
  /** Turns a {@link Refreshable} into an update step that revalidates one
36
57
  * cache: read the entry, ask `revalidate` whether it should transition,
37
58
  * and only when it says yes write the transitioned state and emit the
38
59
  * load Command. When `revalidate` returns `None` (a missing entry, or a
39
- * state with nothing to revalidate) the step returns `[model, []]`: same
40
- * Model, no Command. That one rule is what makes blanket revalidation
41
- * safe, because only the caches that actually hold data reload.
60
+ * state with nothing to revalidate) the step returns `{ model }`: same
61
+ * Model, no Command. A handler can list every affected cache, and only the
62
+ * caches that currently hold data reload.
42
63
  *
43
64
  * ```ts
44
65
  * const refreshAllNotes = refresh({
@@ -49,8 +70,11 @@ export const combine = Function.dual(2, (model, steps) => {
49
70
  * })
50
71
  * ``` */
51
72
  export const refresh = (refreshable) => model => pipe(refreshable.read(model), Option.flatMap(refreshable.revalidate), Option.match({
52
- onNone: () => [model, []],
53
- onSome: next => [refreshable.write(model, next), [refreshable.load]],
73
+ onNone: () => ({ model }),
74
+ onSome: next => ({
75
+ model: refreshable.write(model, next),
76
+ commands: [refreshable.load],
77
+ }),
54
78
  }));
55
79
  /** Folds a child Submodel's update into the parent: the update half of
56
80
  * embedding a child, complementing `h.submodel` on the view half. Give
@@ -73,7 +97,7 @@ export const refresh = (refreshable) => model => pipe(refreshable.read(model), O
73
97
  * The fold runs `update` against the child Model `read` returns, writes
74
98
  * the child back, and lifts the child's Commands through
75
99
  * `toParentMessage`. When `read` returns `None` the fold returns
76
- * `[model, []]`: a Message for an unmounted child is a no-op. When the
100
+ * `{ model }`: a Message for an unmounted child is a no-op. When the
77
101
  * child's update returns an OutMessage, `foldOutMessage` runs against
78
102
  * the Model with the child already written back, and its Commands
79
103
  * follow the child's in the returned batch.
@@ -86,8 +110,10 @@ export const refresh = (refreshable) => model => pipe(refreshable.read(model), O
86
110
  *
87
111
  * A parent that is itself a Submodel passes a
88
112
  * {@link ChildFoldWithParentOutMessage} and receives a
89
- * {@link FoldWithOutMessage}, whose results carry the parent's own
90
- * OutMessage channel as a third element.
113
+ * {@link FoldWithOutMessage}, whose results may include the parent's own
114
+ * OutMessage. Add `toParentOutMessage` only when it forwards at least one
115
+ * child OutMessage from the current Submodel to its parent. Omit
116
+ * `toParentOutMessage` when the local `foldOutMessage` handles every variant.
91
117
  *
92
118
  * An entry point that takes nothing but the child Model, such as
93
119
  * `Dialog.close`, has no input to pass: fold it with
@@ -100,7 +126,7 @@ export const refresh = (refreshable) => model => pipe(refreshable.read(model), O
100
126
  * ```ts
101
127
  * const enterJoinedRoom = (roomId: string, player: Player): UpdateStep =>
102
128
  * Update.combine([
103
- * model => [model, [NavigateToRoom({ roomId })]],
129
+ * model => ({ model, commands: [NavigateToRoom({ roomId })] }),
104
130
  * Update.foldChild({
105
131
  * update: (room: Room.Model, joinedPlayer: Player) =>
106
132
  * Room.informJoined(room, joinedPlayer, { roomId }),
@@ -119,25 +145,29 @@ const makeFoldContext = (toParentMessage) => ({
119
145
  liftCommands: commands => mapMessages(commands, toParentMessage),
120
146
  });
121
147
  const runChildFold = (childFold, context, model, input) => pipe(model, childFold.read, Option.match({
122
- onNone: () => childFold.toParentOutMessage === undefined
123
- ? [model, []]
124
- : [model, [], Option.none()],
148
+ onNone: () => ({ model }),
125
149
  onSome: childModel => {
126
- const [nextChildModel, childCommands, maybeOutMessage] = childFold.update(childModel, input);
127
- const modelWithChild = childFold.write(model, nextChildModel);
128
- const mappedCommands = mapMessages(childCommands, childFold.toParentMessage);
129
- const [nextModel, commands] = childFold.foldOutMessage === undefined ||
130
- maybeOutMessage === undefined ||
131
- Option.isNone(maybeOutMessage)
132
- ? [modelWithChild, mappedCommands]
133
- : appendOutMessageStep(childFold.foldOutMessage, maybeOutMessage.value, context, modelWithChild, mappedCommands);
150
+ const childUpdate = childFold.update(childModel, input);
151
+ const modelWithChild = childFold.write(model, childUpdate.model);
152
+ const mappedCommands = mapMessages(childUpdate.commands, childFold.toParentMessage);
153
+ const update = childFold.foldOutMessage === undefined ||
154
+ childUpdate.outMessage === undefined
155
+ ? { model: modelWithChild, commands: mappedCommands }
156
+ : combine(modelWithChild, [
157
+ stepModel => ({
158
+ model: stepModel,
159
+ commands: mappedCommands,
160
+ }),
161
+ childFold.foldOutMessage(childUpdate.outMessage, context),
162
+ ]);
134
163
  if (childFold.toParentOutMessage === undefined) {
135
- return [nextModel, commands];
164
+ return update;
165
+ }
166
+ if (childUpdate.outMessage === undefined) {
167
+ return update;
136
168
  }
137
- const maybeParentOutMessage = maybeOutMessage === undefined
138
- ? Option.none()
139
- : Option.flatMap(maybeOutMessage, childFold.toParentOutMessage);
140
- return [nextModel, commands, maybeParentOutMessage];
169
+ const parentOutMessage = childFold.toParentOutMessage(childUpdate.outMessage);
170
+ return withOutMessage(update, parentOutMessage);
141
171
  },
142
172
  }));
143
173
  /** Folds a child entry point that takes nothing but the child Model, and
@@ -164,18 +194,18 @@ const runChildFold = (childFold, context, model, input) => pipe(model, childFold
164
194
  * Update.combine(model, [writeRouteFields, foldMobileMenuDialogClose])
165
195
  * ```
166
196
  *
167
- * `foldOutMessage` takes the same optional second parameter `foldChild`'s
168
- * does, a {@link FoldContext} carrying `liftCommand` and `liftCommands` bound
169
- * to this config's `toParentMessage`, for a Command the Step returns whose
170
- * result is the child's Message.
171
- *
172
- * A parent that is itself a Submodel, and so needs its own OutMessage
173
- * channel on the result, uses {@link foldChild}. */
197
+ * `foldOutMessage` takes the same optional second parameter as
198
+ * {@link foldChild}: a {@link FoldContext} carrying `liftCommand` and
199
+ * `liftCommands` bound to this config's `toParentMessage`, for a Command the
200
+ * Step returns whose result is the child's Message.
201
+ *
202
+ * A parent that is itself a Submodel adds `toParentOutMessage` when it
203
+ * forwards at least one child OutMessage to its own parent and receives a
204
+ * {@link StepWithOutMessage}, just as the input-taking {@link foldChild}
205
+ * returns a {@link FoldWithOutMessage}. When no child OutMessage is
206
+ * forwarded, omit the lift and use the plain Step directly. Local handling
207
+ * through `foldOutMessage` is independent of forwarding. */
174
208
  export const foldChildStep = (childFold) => {
175
209
  const context = makeFoldContext(childFold.toParentMessage);
176
- return model => runChildFold(childFold, context, model, undefined);
177
- };
178
- const appendOutMessageStep = (foldOutMessage, outMessage, context, modelWithChild, mappedCommands) => {
179
- const [nextModel, outCommands] = foldOutMessage(outMessage, context)(modelWithChild);
180
- return [nextModel, [...mappedCommands, ...outCommands]];
210
+ return (model) => runChildFold(childFold, context, model, undefined);
181
211
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foldkit",
3
- "version": "0.150.0",
3
+ "version": "0.151.0",
4
4
  "description": "A TypeScript frontend framework, built on Effect and architected like Elm",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",