@confect/foldkit 10.0.0-next.21 → 10.0.0-next.23

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/src/Command.ts CHANGED
@@ -6,10 +6,10 @@ import * as FoldkitCommand from "foldkit/command";
6
6
  import * as Client from "./Client";
7
7
 
8
8
  /**
9
- * Everything a Command against `Ref_` can fail with before it is folded into
10
- * an `onError` Message: the ref's typed error (if it declares an `error`
11
- * schema), a transport-level `WebSocketClientError`, or a `SchemaError` from
12
- * encoding args or decoding returns.
9
+ * Everything a Command against `Ref_` can fail with before it is folded into an
10
+ * `onError` Message: the ref's typed error (if it declares an `error` schema),
11
+ * a transport-level `WebSocketClientError`, or a `SchemaError` from encoding
12
+ * args or decoding returns.
13
13
  */
14
14
  export type Error<Ref_ extends Ref.AnyConfect> =
15
15
  | Ref.Error<Ref_>
@@ -17,11 +17,11 @@ export type Error<Ref_ extends Ref.AnyConfect> =
17
17
  | Schema.SchemaError;
18
18
 
19
19
  /**
20
- * Maps a Confect function's outcome into the app's Messages. Every failure —
21
- * the ref's typed error, a transport error, or a codec error — arrives via
22
- * `onError`, so the resulting Command's error channel is `never`, as Foldkit
23
- * requires. Follow Foldkit's naming convention: past-tense facts like
24
- * `SucceededSaveNote` / `FailedSaveNote`.
20
+ * Maps a Confect function's outcome into the app's Messages. Every failure—the
21
+ * ref's typed error, a transport error, or a codec error—arrives via `onError`,
22
+ * so the resulting Command's error channel is `never`, as Foldkit requires.
23
+ * Follow Foldkit's naming convention: past-tense facts like
24
+ * `SucceededSaveNote`/`FailedSaveNote`.
25
25
  */
26
26
  export interface Handlers<
27
27
  Ref_ extends Ref.AnyConfect,
@@ -50,13 +50,13 @@ type SchemaArgs<Ref_ extends Ref.AnyConfect> = Schema.Schema.Type<
50
50
  >;
51
51
 
52
52
  /**
53
- * A Foldkit Command definition whose args are the ref's args: our
54
- * ref-derived call signature (args optional when the ref declares none)
55
- * intersected with Foldkit's own `CommandDefinitionWithArgs`, which supplies
56
- * the `CommandDefinitionTypeId` brand and makes the definition assignable
57
- * wherever Foldkit accepts one — including Story/Scene `Command.resolve`
58
- * and `expectExact` matchers. Call it from `update` to construct a Command
59
- * instance; nothing runs until the Foldkit runtime executes it.
53
+ * A Foldkit Command definition whose args are the ref's args: our ref-derived
54
+ * call signature (args optional when the ref declares none) intersected with
55
+ * Foldkit's own `CommandDefinitionWithArgs`, which supplies the
56
+ * `CommandDefinitionTypeId` brand and makes the definition assignable wherever
57
+ * Foldkit accepts one—including Story/Scene `Command.resolve` and `expectExact`
58
+ * matchers. Call it from `update` to construct a Command instance; nothing runs
59
+ * until the Foldkit runtime executes it.
60
60
  */
61
61
  export type Definition<
62
62
  Name extends string,
@@ -70,15 +70,15 @@ export type Definition<
70
70
  >;
71
71
 
72
72
  /**
73
- * Makes a factory-built Command interruptible — Foldkit's `InterruptOption`
73
+ * Makes a factory-built Command interruptible—Foldkit's `InterruptOption`
74
74
  * applied to the ref's args. `true` keys every invocation by the Command
75
- * name — right when at most one invocation is meaningfully in flight; a
75
+ * name—right when at most one invocation is meaningfully in flight; a
76
76
  * `KeyedInterrupt` derives the key part from the ref's args, so concurrent
77
77
  * invocations can be targeted independently.
78
78
  *
79
79
  * Interrupting stops the client-side Effect and guarantees the invocation's
80
- * result Messages never dispatch — it does not cancel the Convex function on
81
- * the server, which runs to completion once the call is on the wire.
80
+ * result Messages never dispatch—it does not cancel the Convex function on the
81
+ * server, which runs to completion once the call is on the wire.
82
82
  */
83
83
  export type InterruptOption<
84
84
  Ref_ extends Ref.AnyConfect,
@@ -96,10 +96,10 @@ export type KeyedInterrupt<
96
96
  > = Exclude<InterruptOption<Ref_, KeyField>, true>;
97
97
 
98
98
  /**
99
- * An interruptible Command definition whose key is the Command name — the
99
+ * An interruptible Command definition whose key is the Command name—the
100
100
  * ref-derived call signature intersected with Foldkit's
101
- * `Interruptible.DefinitionWithArgsNameKeyed`, which supplies the brand and
102
- * the `Interrupt` constructor.
101
+ * `Interruptible.DefinitionWithArgsNameKeyed`, which supplies the brand and the
102
+ * `Interrupt` constructor.
103
103
  */
104
104
  export type InterruptibleDefinition<
105
105
  Name extends string,
@@ -116,7 +116,7 @@ export type InterruptibleDefinition<
116
116
 
117
117
  /**
118
118
  * An interruptible Command definition whose key is derived from the ref's
119
- * args — the ref-derived call signature intersected with Foldkit's
119
+ * args—the ref-derived call signature intersected with Foldkit's
120
120
  * `Interruptible.DefinitionWithArgs`, which supplies the brand and the
121
121
  * key-args-taking `Interrupt` constructor.
122
122
  */
@@ -149,9 +149,9 @@ const run = <Ref_ extends Ref.AnyConfect, SuccessMessage, ErrorMessage>(
149
149
  );
150
150
 
151
151
  /**
152
- * An execute body for a hand-written `Command.define` — every failure already
153
- * folded into a Message. Reach for these when the factory below doesn't fit:
154
- * a custom args schema, `interrupt`, or a Command that makes several calls.
152
+ * An execute body for a hand-written `Command.define`—every failure already
153
+ * folded into a Message. Reach for these when the factory below doesn't fit: a
154
+ * custom args schema, `interrupt`, or a Command that makes several calls.
155
155
  */
156
156
  export const queryEffect =
157
157
  <Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage>(
@@ -164,7 +164,7 @@ export const queryEffect =
164
164
  run(handlers, (client) => client.query(ref, ...args));
165
165
 
166
166
  /**
167
- * An execute body for a hand-written `Command.define` — every failure already
167
+ * An execute body for a hand-written `Command.define`—every failure already
168
168
  * folded into a Message. See `queryEffect`.
169
169
  */
170
170
  export const mutationEffect =
@@ -178,7 +178,7 @@ export const mutationEffect =
178
178
  run(handlers, (client) => client.mutation(ref, ...args));
179
179
 
180
180
  /**
181
- * An execute body for a hand-written `Command.define` — every failure already
181
+ * An execute body for a hand-written `Command.define`—every failure already
182
182
  * folded into a Message. See `queryEffect`.
183
183
  */
184
184
  export const actionEffect =
@@ -412,22 +412,26 @@ const makeFactory = <BoundRef extends Ref.AnyConfect>(
412
412
  * messages: [SucceededGetNote, FailedGetNote],
413
413
  * onSuccess: (note) => SucceededGetNote({ note }),
414
414
  * onError: (error) => FailedGetNote({ message: String(error) }),
415
- * })
415
+ * });
416
416
  * // In update:
417
417
  * // [model, [FetchNote({ noteId })]]
418
418
  * ```
419
419
  *
420
420
  * Pass `interrupt` to make invocations interruptible via the returned
421
- * definition's `Interrupt` constructor — `true` keys them by the Command
422
- * name, `{ keyFields, toKey }` by a part derived from the ref's args:
421
+ * definition's `Interrupt` constructor—`true` keys them by the Command name, `{
422
+ * keyFields, toKey }` by a part derived from the ref's args:
423
423
  *
424
424
  * ```ts
425
- * const SaveDraft = Command.mutation("SaveDraft", refs.public.notes.insert, {
426
- * messages: [SucceededSaveDraft, FailedSaveDraft],
427
- * onSuccess: (noteId) => SucceededSaveDraft({ noteId }),
428
- * onError: (error) => FailedSaveDraft({ message: String(error) }),
429
- * interrupt: true,
430
- * })
425
+ * const SaveDraft = Command.mutation(
426
+ * "SaveDraft",
427
+ * refs.public.notes.insert,
428
+ * {
429
+ * messages: [SucceededSaveDraft, FailedSaveDraft],
430
+ * onSuccess: (noteId) => SucceededSaveDraft({ noteId }),
431
+ * onError: (error) => FailedSaveDraft({ message: String(error) }),
432
+ * interrupt: true,
433
+ * },
434
+ * );
431
435
  * // In update:
432
436
  * // [model, [SaveDraft.Interrupt((outcome) => CompletedCancelSaveDraft({ outcome }))]]
433
437
  * ```
@@ -444,8 +448,8 @@ export const mutation: ReturnType<
444
448
  > = makeFactory(mutationEffect);
445
449
 
446
450
  /**
447
- * A Foldkit Command definition for a Confect action whose Command args are
448
- * the ref's args. See `query`.
451
+ * A Foldkit Command definition for a Confect action whose Command args are the
452
+ * ref's args. See `query`.
449
453
  */
450
454
  export const action: ReturnType<
451
455
  typeof makeFactory<Ref.AnyConfectPublicAction>
@@ -11,7 +11,9 @@ import * as SchemaGetter from "effect/SchemaGetter";
11
11
  import * as SchemaIssue from "effect/SchemaIssue";
12
12
  import * as Client from "./Client";
13
13
 
14
- /** Identifies the cursor range fetched for one page. */
14
+ /**
15
+ * Identifies the cursor range fetched for one page.
16
+ */
15
17
  export interface PageDescriptor {
16
18
  readonly cursor: string | null;
17
19
  readonly endCursor: Option.Option<string>;
@@ -22,7 +24,9 @@ export const PageDescriptor = Schema.Struct({
22
24
  endCursor: Schema.Option(Schema.String),
23
25
  });
24
26
 
25
- /** Options that remain fixed for one pagination session. */
27
+ /**
28
+ * Options that remain fixed for one pagination session.
29
+ */
26
30
  export interface Options {
27
31
  readonly initialNumItems: number;
28
32
  readonly maximumRowsRead?: number;
@@ -38,7 +42,9 @@ export const Options = Schema.Struct({
38
42
  maximumBytesRead: Schema.optionalKey(PositiveInt),
39
43
  });
40
44
 
41
- /** Why the machine is fetching its current target. */
45
+ /**
46
+ * Why the machine is fetching its current target.
47
+ */
42
48
  export type Direction =
43
49
  | "Initial"
44
50
  | "Next"
@@ -47,7 +53,9 @@ export type Direction =
47
53
  | "Split"
48
54
  | "Reset";
49
55
 
50
- /** A complete page that can remain on screen while another page is fetched. */
56
+ /**
57
+ * A complete page that can remain on screen while another page is fetched.
58
+ */
51
59
  export interface Page<Item_> {
52
60
  readonly descriptor: PageDescriptor;
53
61
  readonly number: number;
@@ -89,12 +97,16 @@ interface PhaseDefinition extends Data.TaggedEnum.WithGenerics<2> {
89
97
 
90
98
  const Phase = Data.taggedEnum<PhaseDefinition>();
91
99
 
92
- /** A closed machine that retains its generation for stale-result rejection. */
100
+ /**
101
+ * A closed machine that retains its generation for stale-result rejection.
102
+ */
93
103
  export type Idle = Data.TaggedEnum<{
94
104
  Idle: { readonly generation: number };
95
105
  }>;
96
106
 
97
- /** A live cursor-pagination session. */
107
+ /**
108
+ * A live cursor-pagination session.
109
+ */
98
110
  export type Active<Item_, UserArgs_, Error_> = Data.TaggedEnum<{
99
111
  Active: {
100
112
  readonly generation: number;
@@ -108,7 +120,9 @@ export type Active<Item_, UserArgs_, Error_> = Data.TaggedEnum<{
108
120
  };
109
121
  }>;
110
122
 
111
- /** A schema-backed cursor-pagination machine. */
123
+ /**
124
+ * A schema-backed cursor-pagination machine.
125
+ */
112
126
  export type State<Item_, UserArgs_, Error_> =
113
127
  | Idle
114
128
  | Active<Item_, UserArgs_, Error_>;
@@ -119,7 +133,9 @@ interface StateDefinition extends Data.TaggedEnum.WithGenerics<3> {
119
133
 
120
134
  const State = Data.taggedEnum<StateDefinition>();
121
135
 
122
- /** The logical request from which a subscription allocates a session id. */
136
+ /**
137
+ * The logical request from which a subscription allocates a session id.
138
+ */
123
139
  export interface SubscriptionRequest<UserArgs_> {
124
140
  readonly generation: number;
125
141
  readonly args: UserArgs_;
@@ -129,7 +145,9 @@ export interface SubscriptionRequest<UserArgs_> {
129
145
  readonly descriptor: PageDescriptor;
130
146
  }
131
147
 
132
- /** The complete identity and arguments of a subscribed page request. */
148
+ /**
149
+ * The complete identity and arguments of a subscribed page request.
150
+ */
133
151
  export interface Request<UserArgs_> {
134
152
  readonly generation: number;
135
153
  readonly args: UserArgs_;
@@ -139,7 +157,9 @@ export interface Request<UserArgs_> {
139
157
  readonly descriptor: PageDescriptor;
140
158
  }
141
159
 
142
- /** The successful payload returned by a Convex paginated query. */
160
+ /**
161
+ * The successful payload returned by a Convex paginated query.
162
+ */
143
163
  export interface PageResult<Item_> {
144
164
  readonly page: ReadonlyArray<Item_>;
145
165
  readonly isDone: boolean;
@@ -149,8 +169,8 @@ export interface PageResult<Item_> {
149
169
  }
150
170
 
151
171
  /**
152
- * One correlated subscription outcome. Both success and failure travel
153
- * through this value so `settle` can mirror `AsyncData.settle`.
172
+ * One correlated subscription outcome. Both success and failure travel through
173
+ * this value so `settle` can mirror `AsyncData.settle`.
154
174
  */
155
175
  export interface Settlement<Item_, UserArgs_, Error_> {
156
176
  readonly request: Request<UserArgs_>;
@@ -173,18 +193,24 @@ interface FunctionErrorDefinition extends Data.TaggedEnum.WithGenerics<1> {
173
193
  readonly taggedEnum: TaggedFunctionError<this["A"]>;
174
194
  }
175
195
 
176
- /** Constructs a declared function or middleware failure envelope. */
196
+ /**
197
+ * Constructs a declared function or middleware failure envelope.
198
+ */
177
199
  export const FunctionError =
178
200
  Data.taggedEnum<FunctionErrorDefinition>().FunctionError;
179
201
 
180
- /** A declared function or middleware failure, kept distinct from client errors. */
202
+ /**
203
+ * A declared function or middleware failure, kept distinct from client errors.
204
+ */
181
205
  export type FunctionError<Query extends Ref.AnyConfectPublicPaginatedQuery> = [
182
206
  Ref.Error<Query>,
183
207
  ] extends [never]
184
208
  ? never
185
209
  : TaggedFunctionError<Ref.Error<Query>>;
186
210
 
187
- /** Every failure a paginated query subscription can settle with. */
211
+ /**
212
+ * Every failure a paginated query subscription can settle with.
213
+ */
188
214
  export type Error<Query extends Ref.AnyConfectPublicPaginatedQuery> =
189
215
  | FunctionError<Query>
190
216
  | PaginationError.InvalidCursor
@@ -205,7 +231,9 @@ type MachineActive<Query extends Ref.AnyConfectPublicPaginatedQuery> = Active<
205
231
  Error<Query>
206
232
  >;
207
233
 
208
- /** The schema-and-constructor bundle returned by `make`. */
234
+ /**
235
+ * The schema-and-constructor bundle returned by `make`.
236
+ */
209
237
  export interface PaginatedQuery<
210
238
  Query extends Ref.AnyConfectPublicPaginatedQuery,
211
239
  > {
@@ -295,7 +323,9 @@ const SerializableSchemaError = Schema.instanceOf(Schema.SchemaError, {
295
323
  }),
296
324
  });
297
325
 
298
- /** Builds a page machine from a paginated ref. */
326
+ /**
327
+ * Builds a page machine from a paginated ref.
328
+ */
299
329
  export const make = <Query extends Ref.AnyConfectPublicPaginatedQuery>(
300
330
  ref: Query,
301
331
  ): PaginatedQuery<Query> => {
@@ -483,7 +513,9 @@ const descriptorEquals = (a: PageDescriptor, b: PageDescriptor): boolean =>
483
513
  }),
484
514
  });
485
515
 
486
- /** Returns the logical request currently driving the subscription. */
516
+ /**
517
+ * Returns the logical request currently driving the subscription.
518
+ */
487
519
  export const getSubscriptionRequest = <Item_, UserArgs_, Error_>(
488
520
  state: Active<Item_, UserArgs_, Error_>,
489
521
  ): SubscriptionRequest<UserArgs_> => ({
@@ -495,7 +527,9 @@ export const getSubscriptionRequest = <Item_, UserArgs_, Error_>(
495
527
  descriptor: state.current,
496
528
  });
497
529
 
498
- /** Attaches the client-allocated pagination id to a logical request. */
530
+ /**
531
+ * Attaches the client-allocated pagination id to a logical request.
532
+ */
499
533
  export const allocateRequest = <UserArgs_>(
500
534
  request: SubscriptionRequest<UserArgs_>,
501
535
  paginationId: number,
@@ -525,12 +559,16 @@ const pendingPhase = <Item_>(
525
559
  onSome: (page) => Phase.Refreshing<Item_, never>({ data: page, direction }),
526
560
  });
527
561
 
528
- /** Close the subscription while retaining its generation tombstone. */
562
+ /**
563
+ * Close the subscription while retaining its generation tombstone.
564
+ */
529
565
  export const close = <Item_, UserArgs_, Error_>(
530
566
  state: Active<Item_, UserArgs_, Error_>,
531
567
  ): Idle => State.Idle({ generation: state.generation });
532
568
 
533
- /** Start a fresh pagination session at page one while retaining visible data. */
569
+ /**
570
+ * Start a fresh pagination session at page one while retaining visible data.
571
+ */
534
572
  export const reset = <Item_, UserArgs_, Error_>(
535
573
  state: Active<Item_, UserArgs_, Error_>,
536
574
  ): Active<Item_, UserArgs_, Error_> => ({
@@ -543,7 +581,17 @@ export const reset = <Item_, UserArgs_, Error_>(
543
581
  phase: pendingPhase(phaseData(state.phase), "Reset"),
544
582
  });
545
583
 
546
- /** Navigate to the next page, retaining the current page while it loads. */
584
+ /**
585
+ * Navigate to the next page, retaining the current page while it loads.
586
+ *
587
+ * The page being left is pushed onto the stack _pinned_ to the range it
588
+ * displayed—its cursor to its continuation cursor—so `prev` reloads exactly
589
+ * that range rather than the first `initialNumItems` documents after its
590
+ * cursor, however the data has moved meanwhile. Convex's own pagination keeps
591
+ * that range in its query journal; stream-paginated queries have no journal, so
592
+ * the pin is what keeps consecutive pages gap-free and duplicate-free for
593
+ * them.
594
+ */
547
595
  export const next = <Item_, UserArgs_, Error_>(
548
596
  state: Active<Item_, UserArgs_, Error_>,
549
597
  ): Option.Option<Active<Item_, UserArgs_, Error_>> =>
@@ -553,24 +601,25 @@ export const next = <Item_, UserArgs_, Error_>(
553
601
  Match.value(data.isDone).pipe(
554
602
  Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),
555
603
  Match.when(true, () => Option.none()),
556
- Match.when(false, () =>
557
- Option.some({
604
+ Match.when(false, () => {
605
+ const end = Option.getOrElse(
606
+ data.descriptor.endCursor,
607
+ () => data.continueCursor,
608
+ );
609
+ return Option.some({
558
610
  ...state,
559
611
  requestId: state.requestId + 1,
560
- current: {
561
- cursor: Option.getOrElse(
562
- data.descriptor.endCursor,
563
- () => data.continueCursor,
564
- ),
565
- endCursor: Option.none(),
566
- },
567
- prevStack: [...state.prevStack, data.descriptor],
612
+ current: { cursor: end, endCursor: Option.none() },
613
+ prevStack: [
614
+ ...state.prevStack,
615
+ { cursor: data.descriptor.cursor, endCursor: Option.some(end) },
616
+ ],
568
617
  phase: Phase.Refreshing<Item_, Error_>({
569
618
  data,
570
619
  direction: "Next",
571
620
  }),
572
- }),
573
- ),
621
+ });
622
+ }),
574
623
  Match.exhaustive,
575
624
  ),
576
625
  ),
@@ -578,7 +627,9 @@ export const next = <Item_, UserArgs_, Error_>(
578
627
  Match.exhaustive,
579
628
  );
580
629
 
581
- /** Navigate to the previous page, retaining the current page while it loads. */
630
+ /**
631
+ * Navigate to the previous page, retaining the current page while it loads.
632
+ */
582
633
  export const prev = <Item_, UserArgs_, Error_>(
583
634
  state: Active<Item_, UserArgs_, Error_>,
584
635
  ): Option.Option<Active<Item_, UserArgs_, Error_>> =>
@@ -608,7 +659,9 @@ export const prev = <Item_, UserArgs_, Error_>(
608
659
  Match.exhaustive,
609
660
  );
610
661
 
611
- /** Navigate to page one without invalidating the current pagination session. */
662
+ /**
663
+ * Navigate to page one without invalidating the current pagination session.
664
+ */
612
665
  export const first = <Item_, UserArgs_, Error_>(
613
666
  state: Active<Item_, UserArgs_, Error_>,
614
667
  ): Option.Option<Active<Item_, UserArgs_, Error_>> =>
@@ -630,7 +683,9 @@ export const first = <Item_, UserArgs_, Error_>(
630
683
  Match.exhaustive,
631
684
  );
632
685
 
633
- /** Whether a request still names the machine's live pagination session/page. */
686
+ /**
687
+ * Whether a request still names the machine's live pagination session/page.
688
+ */
634
689
  export const isCurrentRequest = <Item_, UserArgs_, Error_>(
635
690
  state: State<Item_, UserArgs_, Error_>,
636
691
  candidate: Request<UserArgs_>,
@@ -799,7 +854,9 @@ export const settle: {
799
854
  ),
800
855
  );
801
856
 
802
- /** The complete page currently available to render. */
857
+ /**
858
+ * The complete page currently available to render.
859
+ */
803
860
  export const getPage = <Item_, UserArgs_, Error_>(
804
861
  state: State<Item_, UserArgs_, Error_>,
805
862
  ): Option.Option<Page<Item_>> =>
@@ -809,13 +866,17 @@ export const getPage = <Item_, UserArgs_, Error_>(
809
866
  Match.exhaustive,
810
867
  );
811
868
 
812
- /** The items currently available to render. */
869
+ /**
870
+ * The items currently available to render.
871
+ */
813
872
  export const getItems = <Item_, UserArgs_, Error_>(
814
873
  state: State<Item_, UserArgs_, Error_>,
815
874
  ): Option.Option<ReadonlyArray<Item_>> =>
816
875
  Option.map(getPage(state), (page) => page.items);
817
876
 
818
- /** The error from the most recent failed request, if any. */
877
+ /**
878
+ * The error from the most recent failed request, if any.
879
+ */
819
880
  export const getError = <Item_, UserArgs_, Error_>(
820
881
  state: State<Item_, UserArgs_, Error_>,
821
882
  ): Option.Option<Error_> =>
@@ -833,7 +894,9 @@ export const getError = <Item_, UserArgs_, Error_>(
833
894
  Match.exhaustive,
834
895
  );
835
896
 
836
- /** The 1-indexed page number currently targeted by the subscription. */
897
+ /**
898
+ * The 1-indexed page number currently targeted by the subscription.
899
+ */
837
900
  export const targetPageNumber = <Item_, UserArgs_, Error_>(
838
901
  state: Active<Item_, UserArgs_, Error_>,
839
902
  ): number => state.prevStack.length + 1;
@@ -948,7 +1011,9 @@ export const canPrev = <Item_, UserArgs_, Error_>(
948
1011
  Match.exhaustive,
949
1012
  );
950
1013
 
951
- /** Pattern-match exhaustively on the machine's AsyncData-style state. */
1014
+ /**
1015
+ * Pattern-match exhaustively on the machine's AsyncData-style state.
1016
+ */
952
1017
  export const match: {
953
1018
  <Item_, Error_, A, B, C, D, E, F>(handlers: {
954
1019
  readonly onIdle: (idle: Idle) => A;
@@ -44,18 +44,17 @@ const paginatedError = <Query extends Ref.AnyConfectPublicPaginatedQuery>(
44
44
 
45
45
  /**
46
46
  * The dependency record of a `reactiveQuery` entry. `None` means the
47
- * subscription is closed; a change from one `Some` to another tears the
48
- * server subscription down and reopens it with the new args.
47
+ * subscription is closed; a change from one `Some` to another tears the server
48
+ * subscription down and reopens it with the new args.
49
49
  */
50
50
  export interface Dependencies<Query extends Ref.AnyConfectPublicQuery> {
51
51
  readonly args: Option.Option<Ref.Args<Query>>;
52
52
  }
53
53
 
54
54
  /**
55
- * Maps a reactive query's emissions into the app's Messages. Every failure —
56
- * the ref's typed error, a transport error, or a codec error — arrives via
57
- * `onError`, so the resulting stream's error channel is `never`, as Foldkit
58
- * requires.
55
+ * Maps a reactive query's emissions into the app's Messages. Every failure—the
56
+ * ref's typed error, a transport error, or a codec error—arrives via `onError`,
57
+ * so the resulting stream's error channel is `never`, as Foldkit requires.
59
58
  */
60
59
  export interface Handlers<
61
60
  Query extends Ref.AnyConfectPublicQuery,
@@ -79,13 +78,13 @@ type ArgsConfig<Query extends Ref.AnyConfectPublicQuery, Model> = {
79
78
  });
80
79
 
81
80
  /**
82
- * A `dependenciesToStream` body for a hand-written subscription entry: runs
83
- * the ref as a reactive query against the `Client` resource and maps
84
- * every emission and every failure into a Message. Query failures are values,
85
- * so the subscription remains live and can later emit a successful result.
81
+ * A `dependenciesToStream` body for a hand-written subscription entry: runs the
82
+ * ref as a reactive query against the `Client` resource and maps every emission
83
+ * and every failure into a Message. Query failures are values, so the
84
+ * subscription remains live and can later emit a successful result.
86
85
  *
87
- * Prefer `reactiveQuery`, which builds the whole entry; reach for this when
88
- * you need control over the entry's dependencies (custom gating, extra
86
+ * Prefer `reactiveQuery`, which builds the whole entry; reach for this when you
87
+ * need control over the entry's dependencies (custom gating, extra
89
88
  * dependencies).
90
89
  */
91
90
  export const reactiveQueryStream =
@@ -109,30 +108,34 @@ export const reactiveQueryStream =
109
108
 
110
109
  /**
111
110
  * A complete Foldkit subscription entry for a Confect reactive query. The
112
- * leading thunk fixes the `Model` type (TypeScript cannot partially infer
113
- * type arguments), so the `args` extractor's parameter is already typed.
114
- * Pass the result as an entry value to `Subscription.make`:
111
+ * leading thunk fixes the `Model` type (TypeScript cannot partially infer type
112
+ * arguments), so the `args` extractor's parameter is already typed. Pass the
113
+ * result as an entry value to `Subscription.make`:
115
114
  *
116
115
  * ```ts
117
- * import * as Confect from "@confect/foldkit"
118
- * import * as Subscription from "foldkit/subscription"
116
+ * import * as Confect from "@confect/foldkit";
117
+ * import * as Subscription from "foldkit/subscription";
119
118
  *
120
119
  * const subscriptions = Subscription.make<
121
120
  * Model,
122
121
  * Message,
123
122
  * Confect.Client.Client
124
123
  * >()(() => ({
125
- * note: Confect.Subscription.reactiveQuery<Model>()(refs.public.notes.get, {
126
- * args: (model) => Option.map(model.noteId, (noteId) => ({ noteId })),
127
- * onSuccess: (note) => SucceededGetNote({ note }),
128
- * onError: (error) => FailedGetNote({ message: String(error) }),
129
- * }),
130
- * }))
124
+ * note: Confect.Subscription.reactiveQuery<Model>()(
125
+ * refs.public.notes.get,
126
+ * {
127
+ * args: (model) =>
128
+ * Option.map(model.noteId, (noteId) => ({ noteId })),
129
+ * onSuccess: (note) => SucceededGetNote({ note }),
130
+ * onError: (error) => FailedGetNote({ message: String(error) }),
131
+ * },
132
+ * ),
133
+ * }));
131
134
  * ```
132
135
  *
133
136
  * The entry's dependencies are the query args wrapped in `Option`: `None`
134
- * closes the subscription, a change from one `Some` to another unsubscribes
135
- * and resubscribes with the new args, and structurally equal args leave the
137
+ * closes the subscription, a change from one `Some` to another unsubscribes and
138
+ * resubscribes with the new args, and structurally equal args leave the
136
139
  * subscription running (equivalence is derived from the ref's args schema).
137
140
  * Queries without args may omit `args`, leaving the subscription always open.
138
141
  */
@@ -170,18 +173,17 @@ export const reactiveQuery =
170
173
 
171
174
  /**
172
175
  * A complete Foldkit subscription entry that keeps exactly one live reactive
173
- * page subscription in sync with a `PaginatedQuery` machine in the Model.
174
- * The machine state is the single source of truth: navigation and
175
- * split-pinning change the derived args, while `Idle` closes the subscription.
176
- * Pagination ids are allocated here and installed by the first settlement.
176
+ * page subscription in sync with a `PaginatedQuery` machine in the Model. The
177
+ * machine state is the single source of truth: navigation and split-pinning
178
+ * change the derived args, while `Idle` closes the subscription. Pagination ids
179
+ * are allocated here and installed by the first settlement.
177
180
  *
178
- * The leading thunk fixes the `Model` type (TypeScript cannot partially
179
- * infer type arguments), so the `state` extractor's parameter is already
180
- * typed:
181
+ * The leading thunk fixes the `Model` type (TypeScript cannot partially infer
182
+ * type arguments), so the `state` extractor's parameter is already typed:
181
183
  *
182
184
  * ```ts
183
- * import * as Confect from "@confect/foldkit"
184
- * import * as Subscription from "foldkit/subscription"
185
+ * import * as Confect from "@confect/foldkit";
186
+ * import * as Subscription from "foldkit/subscription";
185
187
  *
186
188
  * const subscriptions = Subscription.make<
187
189
  * Model,
@@ -192,13 +194,13 @@ export const reactiveQuery =
192
194
  * state: (model) => model.notes,
193
195
  * onSettled: (settlement) => SettledGetNotesPage({ settlement }),
194
196
  * }),
195
- * }))
197
+ * }));
196
198
  * ```
197
199
  *
198
200
  * Pass the settlement to `PaginatedQuery.settle` in `update`. The request
199
201
  * identity is included in both success and failure Messages, so superseded
200
- * outcomes cannot settle a newer page or pagination session. Query failures
201
- * do not close the Convex subscription; a later result can recover naturally.
202
+ * outcomes cannot settle a newer page or pagination session. Query failures do
203
+ * not close the Convex subscription; a later result can recover naturally.
202
204
  */
203
205
  type DependenciesSchema<Dependencies_> = Schema.Schema<Dependencies_> & {
204
206
  readonly fields: Schema.Struct.Fields;