@confect/foldkit 10.0.0-next.22 → 10.0.0-next.24
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/CHANGELOG.md +10 -0
- package/dist/Command.d.ts +36 -31
- package/dist/Command.d.ts.map +1 -1
- package/dist/Command.js +17 -13
- package/dist/Command.js.map +1 -1
- package/dist/PaginatedQuery.d.ts +90 -36
- package/dist/PaginatedQuery.d.ts.map +1 -1
- package/dist/PaginatedQuery.js +49 -21
- package/dist/PaginatedQuery.js.map +1 -1
- package/dist/Subscription.d.ts +39 -36
- package/dist/Subscription.d.ts.map +1 -1
- package/dist/Subscription.js +23 -19
- package/dist/Subscription.js.map +1 -1
- package/package.json +9 -7
- package/src/Command.ts +36 -31
- package/src/PaginatedQuery.ts +90 -36
- package/src/Subscription.ts +39 -36
package/dist/PaginatedQuery.js
CHANGED
|
@@ -60,7 +60,9 @@ const Options = Schema.Struct({
|
|
|
60
60
|
});
|
|
61
61
|
const Phase = Data.taggedEnum();
|
|
62
62
|
const State = Data.taggedEnum();
|
|
63
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* Constructs a declared function or middleware failure envelope.
|
|
65
|
+
*/
|
|
64
66
|
const FunctionError = Data.taggedEnum().FunctionError;
|
|
65
67
|
const firstDescriptor = () => ({
|
|
66
68
|
cursor: null,
|
|
@@ -86,7 +88,9 @@ const SerializableSchemaError = Schema.instanceOf(Schema.SchemaError, { toCodecJ
|
|
|
86
88
|
decode: SchemaGetter.transform(({ message }) => new Schema.SchemaError(new SchemaIssue.InvalidValue({ message }))),
|
|
87
89
|
encode: SchemaGetter.transform((error) => SchemaErrorJson.make({ message: error.message }))
|
|
88
90
|
}) });
|
|
89
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* Builds a page machine from a paginated ref.
|
|
93
|
+
*/
|
|
90
94
|
const make = (ref) => {
|
|
91
95
|
const kind = paginatedKindOrThrow(ref);
|
|
92
96
|
const hasUserArgs = globalThis.Object.keys(kind.userArgs.fields).length > 0;
|
|
@@ -189,7 +193,9 @@ const descriptorEquals = (a, b) => a.cursor === b.cursor && Option.match(a.endCu
|
|
|
189
193
|
onSome: (bEnd) => aEnd === bEnd
|
|
190
194
|
})
|
|
191
195
|
});
|
|
192
|
-
/**
|
|
196
|
+
/**
|
|
197
|
+
* Returns the logical request currently driving the subscription.
|
|
198
|
+
*/
|
|
193
199
|
const getSubscriptionRequest = (state) => ({
|
|
194
200
|
generation: state.generation,
|
|
195
201
|
args: state.args,
|
|
@@ -198,7 +204,9 @@ const getSubscriptionRequest = (state) => ({
|
|
|
198
204
|
requestId: state.requestId,
|
|
199
205
|
descriptor: state.current
|
|
200
206
|
});
|
|
201
|
-
/**
|
|
207
|
+
/**
|
|
208
|
+
* Attaches the client-allocated pagination id to a logical request.
|
|
209
|
+
*/
|
|
202
210
|
const allocateRequest = (request, paginationId) => ({
|
|
203
211
|
...request,
|
|
204
212
|
paginationId
|
|
@@ -211,9 +219,13 @@ const pendingPhase = (data, direction) => Option.match(data, {
|
|
|
211
219
|
direction
|
|
212
220
|
})
|
|
213
221
|
});
|
|
214
|
-
/**
|
|
222
|
+
/**
|
|
223
|
+
* Close the subscription while retaining its generation tombstone.
|
|
224
|
+
*/
|
|
215
225
|
const close = (state) => State.Idle({ generation: state.generation });
|
|
216
|
-
/**
|
|
226
|
+
/**
|
|
227
|
+
* Start a fresh pagination session at page one while retaining visible data.
|
|
228
|
+
*/
|
|
217
229
|
const reset = (state) => ({
|
|
218
230
|
...state,
|
|
219
231
|
generation: state.generation + 1,
|
|
@@ -226,13 +238,13 @@ const reset = (state) => ({
|
|
|
226
238
|
/**
|
|
227
239
|
* Navigate to the next page, retaining the current page while it loads.
|
|
228
240
|
*
|
|
229
|
-
* The page being left is pushed onto the stack
|
|
230
|
-
* displayed—its cursor to its continuation cursor—so `prev` reloads
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
241
|
+
* The page being left is pushed onto the stack _pinned_ to the range it
|
|
242
|
+
* displayed—its cursor to its continuation cursor—so `prev` reloads exactly
|
|
243
|
+
* that range rather than the first `initialNumItems` documents after its
|
|
244
|
+
* cursor, however the data has moved meanwhile. Convex's own pagination keeps
|
|
245
|
+
* that range in its query journal; stream-paginated queries have no journal, so
|
|
246
|
+
* the pin is what keeps consecutive pages gap-free and duplicate-free for
|
|
247
|
+
* them.
|
|
236
248
|
*/
|
|
237
249
|
const next = (state) => Match.value(state.phase).pipe(Match.withReturnType(), Match.tag("Success", ({ data }) => Match.value(data.isDone).pipe(Match.withReturnType(), Match.when(true, () => Option.none()), Match.when(false, () => {
|
|
238
250
|
const end = Option.getOrElse(data.descriptor.endCursor, () => data.continueCursor);
|
|
@@ -253,7 +265,9 @@ const next = (state) => Match.value(state.phase).pipe(Match.withReturnType(), Ma
|
|
|
253
265
|
})
|
|
254
266
|
});
|
|
255
267
|
}), Match.exhaustive)), Match.tag("Loading", "Refreshing", "Failure", "Stale", () => Option.none()), Match.exhaustive);
|
|
256
|
-
/**
|
|
268
|
+
/**
|
|
269
|
+
* Navigate to the previous page, retaining the current page while it loads.
|
|
270
|
+
*/
|
|
257
271
|
const prev = (state) => Match.value(state.phase).pipe(Match.withReturnType(), Match.tag("Success", ({ data }) => {
|
|
258
272
|
const current = state.prevStack.at(-1);
|
|
259
273
|
return Match.value(current).pipe(Match.withReturnType(), Match.when(void 0, () => Option.none()), Match.when(Match.defined, (previous) => Option.some({
|
|
@@ -267,7 +281,9 @@ const prev = (state) => Match.value(state.phase).pipe(Match.withReturnType(), Ma
|
|
|
267
281
|
})
|
|
268
282
|
})), Match.exhaustive);
|
|
269
283
|
}), Match.tag("Loading", "Refreshing", "Failure", "Stale", () => Option.none()), Match.exhaustive);
|
|
270
|
-
/**
|
|
284
|
+
/**
|
|
285
|
+
* Navigate to page one without invalidating the current pagination session.
|
|
286
|
+
*/
|
|
271
287
|
const first = (state) => Match.value(state.prevStack.length === 0 && descriptorEquals(state.current, firstDescriptor())).pipe(Match.withReturnType(), Match.when(true, () => Option.none()), Match.when(false, () => Option.some({
|
|
272
288
|
...state,
|
|
273
289
|
requestId: state.requestId + 1,
|
|
@@ -275,7 +291,9 @@ const first = (state) => Match.value(state.prevStack.length === 0 && descriptorE
|
|
|
275
291
|
prevStack: [],
|
|
276
292
|
phase: pendingPhase(phaseData(state.phase), "First")
|
|
277
293
|
})), Match.exhaustive);
|
|
278
|
-
/**
|
|
294
|
+
/**
|
|
295
|
+
* Whether a request still names the machine's live pagination session/page.
|
|
296
|
+
*/
|
|
279
297
|
const isCurrentRequest = (state, candidate) => Match.value(state).pipe(Match.tag("Idle", () => false), Match.tag("Active", (active) => Match.value(active.paginationId).pipe(Match.tag("None", () => Match.value(active.generation === candidate.generation && active.requestId === candidate.requestId && descriptorEquals(active.current, candidate.descriptor)).pipe(Match.when(true, () => true), Match.when(false, () => false), Match.exhaustive)), Match.tag("Some", ({ value }) => active.generation === candidate.generation && value === candidate.paginationId && active.requestId === candidate.requestId && descriptorEquals(active.current, candidate.descriptor)), Match.exhaustive)), Match.exhaustive);
|
|
280
298
|
const pageFromResult = (state, result) => ({
|
|
281
299
|
descriptor: state.current,
|
|
@@ -338,13 +356,21 @@ const settle = Function.dual(2, (state, settlement) => Match.value(state).pipe(M
|
|
|
338
356
|
onFailure: (error) => Match.value(error).pipe(Match.when(Match.instanceOf(PaginationError.InvalidCursor), () => reset(allocated)), Match.orElse((other) => settleFailure(allocated, other)))
|
|
339
357
|
});
|
|
340
358
|
}), Match.exhaustive)), Match.exhaustive));
|
|
341
|
-
/**
|
|
359
|
+
/**
|
|
360
|
+
* The complete page currently available to render.
|
|
361
|
+
*/
|
|
342
362
|
const getPage = (state) => Match.value(state).pipe(Match.tag("Idle", () => Option.none()), Match.tag("Active", ({ phase }) => phaseData(phase)), Match.exhaustive);
|
|
343
|
-
/**
|
|
363
|
+
/**
|
|
364
|
+
* The items currently available to render.
|
|
365
|
+
*/
|
|
344
366
|
const getItems = (state) => Option.map(getPage(state), (page) => page.items);
|
|
345
|
-
/**
|
|
367
|
+
/**
|
|
368
|
+
* The error from the most recent failed request, if any.
|
|
369
|
+
*/
|
|
346
370
|
const getError = (state) => Match.value(state).pipe(Match.withReturnType(), Match.tag("Idle", () => Option.none()), Match.tag("Active", ({ phase }) => Match.value(phase).pipe(Match.withReturnType(), Match.tag("Failure", "Stale", ({ error }) => Option.some(error)), Match.tag("Loading", "Refreshing", "Success", () => Option.none()), Match.exhaustive)), Match.exhaustive);
|
|
347
|
-
/**
|
|
371
|
+
/**
|
|
372
|
+
* The 1-indexed page number currently targeted by the subscription.
|
|
373
|
+
*/
|
|
348
374
|
const targetPageNumber = (state) => state.prevStack.length + 1;
|
|
349
375
|
const hasPage = (state) => Option.isSome(getPage(state));
|
|
350
376
|
const hasError = (state) => Option.isSome(getError(state));
|
|
@@ -359,7 +385,9 @@ const isStale = (state) => state._tag === "Active" && state.phase._tag === "Stal
|
|
|
359
385
|
const isPending = (state) => Match.value(state).pipe(Match.tag("Idle", () => false), Match.tag("Active", ({ phase }) => Match.value(phase).pipe(Match.tag("Loading", "Refreshing", () => true), Match.tag("Success", "Failure", "Stale", () => false), Match.exhaustive)), Match.exhaustive);
|
|
360
386
|
const canNext = (state) => Match.value(state).pipe(Match.tag("Idle", () => false), Match.tag("Active", ({ phase }) => Match.value(phase).pipe(Match.tag("Success", ({ data }) => !data.isDone), Match.tag("Loading", "Refreshing", "Failure", "Stale", () => false), Match.exhaustive)), Match.exhaustive);
|
|
361
387
|
const canPrev = (state) => Match.value(state).pipe(Match.tag("Idle", () => false), Match.tag("Active", ({ phase, prevStack }) => Match.value(phase).pipe(Match.tag("Success", () => prevStack.length > 0), Match.tag("Loading", "Refreshing", "Failure", "Stale", () => false), Match.exhaustive)), Match.exhaustive);
|
|
362
|
-
/**
|
|
388
|
+
/**
|
|
389
|
+
* Pattern-match exhaustively on the machine's AsyncData-style state.
|
|
390
|
+
*/
|
|
363
391
|
const match = Function.dual(2, (state, handlers) => Match.value(state).pipe(Match.tag("Idle", handlers.onIdle), Match.tag("Active", ({ phase }) => Match.value(phase).pipe(Match.tag("Loading", handlers.onLoading), Match.tag("Refreshing", handlers.onRefreshing), Match.tag("Failure", handlers.onFailure), Match.tag("Stale", handlers.onStale), Match.tag("Success", handlers.onSuccess), Match.exhaustive)), Match.exhaustive));
|
|
364
392
|
//#endregion
|
|
365
393
|
export { FunctionError, InvalidCursor, Options, PageDescriptor, PaginatedQuery_exports, allocateRequest, canNext, canPrev, close, first, getError, getItems, getPage, getSubscriptionRequest, hasError, hasPage, isCurrentRequest, isFailure, isFirst, isIdle, isLast, isLoading, isPending, isRefreshing, isStale, isSuccess, make, match, next, prev, reset, settle, targetPageNumber };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaginatedQuery.js","names":["Client.WebSocketClientError"],"sources":["../src/PaginatedQuery.ts"],"sourcesContent":["import * as MiddlewareSpec from \"@confect/core/MiddlewareSpec\";\nimport * as PaginationError from \"@confect/core/PaginationError\";\nimport * as Ref from \"@confect/core/Ref\";\nimport * as Data from \"effect/Data\";\nimport * as Function from \"effect/Function\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as Result from \"effect/Result\";\nimport * as Schema from \"effect/Schema\";\nimport * as SchemaGetter from \"effect/SchemaGetter\";\nimport * as SchemaIssue from \"effect/SchemaIssue\";\nimport * as Client from \"./Client\";\n\n/** Identifies the cursor range fetched for one page. */\nexport interface PageDescriptor {\n readonly cursor: string | null;\n readonly endCursor: Option.Option<string>;\n}\n\nexport const PageDescriptor = Schema.Struct({\n cursor: Schema.Union([Schema.String, Schema.Null]),\n endCursor: Schema.Option(Schema.String),\n});\n\n/** Options that remain fixed for one pagination session. */\nexport interface Options {\n readonly initialNumItems: number;\n readonly maximumRowsRead?: number;\n readonly maximumBytesRead?: number;\n}\n\nconst PositiveInt = Schema.Int.check(Schema.isGreaterThan(0));\nconst NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));\n\nexport const Options = Schema.Struct({\n initialNumItems: PositiveInt,\n maximumRowsRead: Schema.optionalKey(PositiveInt),\n maximumBytesRead: Schema.optionalKey(PositiveInt),\n});\n\n/** Why the machine is fetching its current target. */\nexport type Direction =\n | \"Initial\"\n | \"Next\"\n | \"Previous\"\n | \"First\"\n | \"Split\"\n | \"Reset\";\n\n/** A complete page that can remain on screen while another page is fetched. */\nexport interface Page<Item_> {\n readonly descriptor: PageDescriptor;\n readonly number: number;\n readonly items: ReadonlyArray<Item_>;\n readonly continueCursor: string;\n readonly isDone: boolean;\n}\n\nexport type Loading = Data.TaggedEnum<{\n Loading: { readonly direction: Direction };\n}>;\n\nexport type Refreshing<Item_> = Data.TaggedEnum<{\n Refreshing: { readonly data: Page<Item_>; readonly direction: Direction };\n}>;\n\nexport type Success<Item_> = Data.TaggedEnum<{\n Success: { readonly data: Page<Item_> };\n}>;\n\nexport type Failure<Error_> = Data.TaggedEnum<{\n Failure: { readonly error: Error_ };\n}>;\n\nexport type Stale<Item_, Error_> = Data.TaggedEnum<{\n Stale: { readonly data: Page<Item_>; readonly error: Error_ };\n}>;\n\nexport type Phase<Item_, Error_> =\n | Loading\n | Refreshing<Item_>\n | Success<Item_>\n | Failure<Error_>\n | Stale<Item_, Error_>;\n\ninterface PhaseDefinition extends Data.TaggedEnum.WithGenerics<2> {\n readonly taggedEnum: Phase<this[\"A\"], this[\"B\"]>;\n}\n\nconst Phase = Data.taggedEnum<PhaseDefinition>();\n\n/** A closed machine that retains its generation for stale-result rejection. */\nexport type Idle = Data.TaggedEnum<{\n Idle: { readonly generation: number };\n}>;\n\n/** A live cursor-pagination session. */\nexport type Active<Item_, UserArgs_, Error_> = Data.TaggedEnum<{\n Active: {\n readonly generation: number;\n readonly args: UserArgs_;\n readonly options: Options;\n readonly paginationId: Option.Option<number>;\n readonly requestId: number;\n readonly current: PageDescriptor;\n readonly prevStack: ReadonlyArray<PageDescriptor>;\n readonly phase: Phase<Item_, Error_>;\n };\n}>;\n\n/** A schema-backed cursor-pagination machine. */\nexport type State<Item_, UserArgs_, Error_> =\n | Idle\n | Active<Item_, UserArgs_, Error_>;\n\ninterface StateDefinition extends Data.TaggedEnum.WithGenerics<3> {\n readonly taggedEnum: State<this[\"A\"], this[\"B\"], this[\"C\"]>;\n}\n\nconst State = Data.taggedEnum<StateDefinition>();\n\n/** The logical request from which a subscription allocates a session id. */\nexport interface SubscriptionRequest<UserArgs_> {\n readonly generation: number;\n readonly args: UserArgs_;\n readonly options: Options;\n readonly paginationId: Option.Option<number>;\n readonly requestId: number;\n readonly descriptor: PageDescriptor;\n}\n\n/** The complete identity and arguments of a subscribed page request. */\nexport interface Request<UserArgs_> {\n readonly generation: number;\n readonly args: UserArgs_;\n readonly options: Options;\n readonly paginationId: number;\n readonly requestId: number;\n readonly descriptor: PageDescriptor;\n}\n\n/** The successful payload returned by a Convex paginated query. */\nexport interface PageResult<Item_> {\n readonly page: ReadonlyArray<Item_>;\n readonly isDone: boolean;\n readonly continueCursor: string;\n readonly splitCursor?: string | null;\n readonly pageStatus?: \"SplitRecommended\" | \"SplitRequired\" | null;\n}\n\n/**\n * One correlated subscription outcome. Both success and failure travel\n * through this value so `settle` can mirror `AsyncData.settle`.\n */\nexport interface Settlement<Item_, UserArgs_, Error_> {\n readonly request: Request<UserArgs_>;\n readonly result: Result.Result<PageResult<Item_>, Error_>;\n}\n\nexport type Item<Query extends Ref.AnyConfectPublicPaginatedQuery> =\n Ref.Returns<Query>[\"page\"][number];\n\nexport type UserArgs<Query extends Ref.AnyConfectPublicPaginatedQuery> = Omit<\n Ref.Args<Query>,\n \"paginationOpts\"\n>;\n\ntype TaggedFunctionError<Error_> = Data.TaggedEnum<{\n FunctionError: { readonly error: Error_ };\n}>;\n\ninterface FunctionErrorDefinition extends Data.TaggedEnum.WithGenerics<1> {\n readonly taggedEnum: TaggedFunctionError<this[\"A\"]>;\n}\n\n/** Constructs a declared function or middleware failure envelope. */\nexport const FunctionError =\n Data.taggedEnum<FunctionErrorDefinition>().FunctionError;\n\n/** A declared function or middleware failure, kept distinct from client errors. */\nexport type FunctionError<Query extends Ref.AnyConfectPublicPaginatedQuery> = [\n Ref.Error<Query>,\n] extends [never]\n ? never\n : TaggedFunctionError<Ref.Error<Query>>;\n\n/** Every failure a paginated query subscription can settle with. */\nexport type Error<Query extends Ref.AnyConfectPublicPaginatedQuery> =\n | FunctionError<Query>\n | PaginationError.InvalidCursor\n | Client.WebSocketClientError\n | Schema.SchemaError;\n\nexport { InvalidCursor } from \"@confect/core/PaginationError\";\n\ntype MachineState<Query extends Ref.AnyConfectPublicPaginatedQuery> = State<\n Item<Query>,\n UserArgs<Query>,\n Error<Query>\n>;\n\ntype MachineActive<Query extends Ref.AnyConfectPublicPaginatedQuery> = Active<\n Item<Query>,\n UserArgs<Query>,\n Error<Query>\n>;\n\n/** The schema-and-constructor bundle returned by `make`. */\nexport interface PaginatedQuery<\n Query extends Ref.AnyConfectPublicPaginatedQuery,\n> {\n readonly ref: Query;\n readonly schema: Schema.Codec<MachineState<Query>, unknown>;\n readonly idle: Idle;\n readonly subscriptionRequestSchema: Schema.Codec<\n SubscriptionRequest<UserArgs<Query>>,\n unknown\n >;\n readonly requestSchema: Schema.Codec<Request<UserArgs<Query>>, unknown>;\n readonly settlement: Schema.Codec<\n Settlement<Item<Query>, UserArgs<Query>, Error<Query>>,\n unknown\n >;\n readonly init: keyof UserArgs<Query> extends never\n ? (state: Idle, options: Options) => MachineActive<Query>\n : (\n state: Idle,\n args: UserArgs<Query>,\n options: Options,\n ) => MachineActive<Query>;\n readonly reinitialize: keyof UserArgs<Query> extends never\n ? (state: MachineActive<Query>, options?: Options) => MachineActive<Query>\n : (\n state: MachineActive<Query>,\n args: UserArgs<Query>,\n options?: Options,\n ) => MachineActive<Query>;\n}\n\nexport type Any = PaginatedQuery<Ref.AnyConfectPublicPaginatedQuery>;\n\nconst firstDescriptor = (): PageDescriptor => ({\n cursor: null,\n endCursor: Option.none(),\n});\n\nconst decodeOptions = Schema.decodeUnknownSync(Options);\n\nconst initialState = <Item_, UserArgs_, Error_>(\n generation: number,\n args: UserArgs_,\n options: Options,\n): Active<Item_, UserArgs_, Error_> =>\n State.Active<Item_, UserArgs_, Error_>({\n generation,\n args,\n options: decodeOptions(options),\n paginationId: Option.none(),\n requestId: 1,\n current: firstDescriptor(),\n prevStack: [],\n phase: Phase.Loading<Item_, Error_>({ direction: \"Initial\" }),\n });\n\nconst missingPaginatedProvenanceError = (ref: Ref.AnyConfect) =>\n new globalThis.Error(\n `Paginated query ref \"${Ref.getConvexFunctionName(ref)}\" was not built ` +\n \"with `FunctionSpec.publicPaginatedQuery`. `PaginatedQuery.make` \" +\n \"requires the user-args and item schemas that constructor stores.\",\n );\n\nconst paginatedKindOrThrow = (ref: Ref.AnyConfectPublicPaginatedQuery) =>\n Match.value(ref.kind).pipe(\n Match.tag(\"Paginated\", (kind) => kind),\n Match.tag(\"Standard\", () => {\n throw missingPaginatedProvenanceError(ref);\n }),\n Match.exhaustive,\n );\n\nconst SchemaErrorJson = Schema.TaggedStruct(\"SchemaError\", {\n message: Schema.String,\n});\n\nconst SerializableSchemaError = Schema.instanceOf(Schema.SchemaError, {\n toCodecJson: () =>\n Schema.link<Schema.SchemaError>()(SchemaErrorJson, {\n decode: SchemaGetter.transform(\n ({ message }) =>\n new Schema.SchemaError(new SchemaIssue.InvalidValue({ message })),\n ),\n encode: SchemaGetter.transform((error) =>\n SchemaErrorJson.make({ message: error.message }),\n ),\n }),\n});\n\n/** Builds a page machine from a paginated ref. */\nexport const make = <Query extends Ref.AnyConfectPublicPaginatedQuery>(\n ref: Query,\n): PaginatedQuery<Query> => {\n const kind = paginatedKindOrThrow(ref);\n const hasUserArgs = globalThis.Object.keys(kind.userArgs.fields).length > 0;\n const functionErrorSchemas = [\n ...(\"error\" in ref && ref.error !== undefined ? [ref.error] : []),\n ...MiddlewareSpec.errorSchemas(ref.middlewareSpecs),\n ];\n const errorSchema = Schema.Union([\n PaginationError.InvalidCursor,\n Client.WebSocketClientError,\n SerializableSchemaError,\n ...(functionErrorSchemas.length === 0\n ? []\n : [\n Schema.TaggedStruct(\"FunctionError\", {\n error:\n functionErrorSchemas.length === 1\n ? functionErrorSchemas[0]!\n : Schema.Union(functionErrorSchemas),\n }),\n ]),\n ]) as Schema.Codec<Error<Query>, unknown>;\n const directions = Schema.Literals([\n \"Initial\",\n \"Next\",\n \"Previous\",\n \"First\",\n \"Split\",\n \"Reset\",\n ]);\n const page = Schema.Struct({\n descriptor: PageDescriptor,\n number: PositiveInt,\n items: kind.page,\n continueCursor: Schema.String,\n isDone: Schema.Boolean,\n });\n const phase = Schema.TaggedUnion({\n Loading: { direction: directions },\n Refreshing: { data: page, direction: directions },\n Success: { data: page },\n Failure: { error: errorSchema },\n Stale: { data: page, error: errorSchema },\n });\n const subscriptionRequestSchema: PaginatedQuery<Query>[\"subscriptionRequestSchema\"] =\n Schema.Struct({\n generation: PositiveInt,\n args: kind.userArgs,\n options: Options,\n paginationId: Schema.Option(PositiveInt),\n requestId: PositiveInt,\n descriptor: PageDescriptor,\n });\n const requestSchema: PaginatedQuery<Query>[\"requestSchema\"] = Schema.Struct({\n generation: PositiveInt,\n args: kind.userArgs,\n options: Options,\n paginationId: PositiveInt,\n requestId: PositiveInt,\n descriptor: PageDescriptor,\n });\n const pageResult = Schema.Struct({\n page: kind.page,\n isDone: Schema.Boolean,\n continueCursor: Schema.String,\n splitCursor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])),\n pageStatus: Schema.optionalKey(\n Schema.Union([\n Schema.Literal(\"SplitRecommended\"),\n Schema.Literal(\"SplitRequired\"),\n Schema.Null,\n ]),\n ),\n });\n const schema: PaginatedQuery<Query>[\"schema\"] = Schema.TaggedUnion({\n Idle: { generation: NonNegativeInt },\n Active: {\n generation: PositiveInt,\n args: kind.userArgs,\n options: Options,\n paginationId: Schema.Option(PositiveInt),\n requestId: PositiveInt,\n current: PageDescriptor,\n prevStack: Schema.Array(PageDescriptor),\n phase,\n },\n });\n const settlement: PaginatedQuery<Query>[\"settlement\"] = Schema.Struct({\n request: requestSchema,\n result: Schema.Result(pageResult, errorSchema),\n });\n\n const init: PaginatedQuery<Query>[\"init\"] = (\n state: Idle,\n argsOrOptions: UserArgs<Query> | Options,\n options?: Options,\n ): MachineActive<Query> =>\n Match.value(options).pipe(\n Match.withReturnType<MachineActive<Query>>(),\n Match.when(undefined, () =>\n initialState(\n state.generation + 1,\n {} as UserArgs<Query>,\n argsOrOptions as Options,\n ),\n ),\n Match.when(Match.defined, (definedOptions) =>\n initialState(\n state.generation + 1,\n argsOrOptions as UserArgs<Query>,\n definedOptions,\n ),\n ),\n Match.exhaustive,\n );\n\n const reinitialize: PaginatedQuery<Query>[\"reinitialize\"] = (\n state: MachineActive<Query>,\n argsOrOptions?: UserArgs<Query> | Options,\n options?: Options,\n ): MachineActive<Query> =>\n Match.value(options).pipe(\n Match.withReturnType<MachineActive<Query>>(),\n Match.when(Match.defined, (definedOptions) =>\n initialState(\n state.generation + 1,\n argsOrOptions as UserArgs<Query>,\n definedOptions,\n ),\n ),\n Match.when(undefined, () =>\n Match.value(argsOrOptions).pipe(\n Match.withReturnType<MachineActive<Query>>(),\n Match.when(undefined, () =>\n initialState(state.generation + 1, state.args, state.options),\n ),\n Match.when(Match.defined, (definedArgsOrOptions) =>\n Match.value(hasUserArgs).pipe(\n Match.withReturnType<MachineActive<Query>>(),\n Match.when(true, () =>\n initialState(\n state.generation + 1,\n definedArgsOrOptions as UserArgs<Query>,\n state.options,\n ),\n ),\n Match.when(false, () =>\n initialState(\n state.generation + 1,\n state.args,\n definedArgsOrOptions as Options,\n ),\n ),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\n return {\n ref,\n schema,\n idle: State.Idle({ generation: 0 }),\n subscriptionRequestSchema,\n requestSchema,\n settlement,\n init,\n reinitialize,\n };\n};\n\nconst descriptorEquals = (a: PageDescriptor, b: PageDescriptor): boolean =>\n a.cursor === b.cursor &&\n Option.match(a.endCursor, {\n onNone: () => Option.isNone(b.endCursor),\n onSome: (aEnd) =>\n Option.match(b.endCursor, {\n onNone: () => false,\n onSome: (bEnd) => aEnd === bEnd,\n }),\n });\n\n/** Returns the logical request currently driving the subscription. */\nexport const getSubscriptionRequest = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): SubscriptionRequest<UserArgs_> => ({\n generation: state.generation,\n args: state.args,\n options: state.options,\n paginationId: state.paginationId,\n requestId: state.requestId,\n descriptor: state.current,\n});\n\n/** Attaches the client-allocated pagination id to a logical request. */\nexport const allocateRequest = <UserArgs_>(\n request: SubscriptionRequest<UserArgs_>,\n paginationId: number,\n): Request<UserArgs_> => ({\n ...request,\n paginationId,\n});\n\nconst phaseData = <Item_, Error_>(\n phase: Phase<Item_, Error_>,\n): Option.Option<Page<Item_>> =>\n Match.value(phase).pipe(\n Match.withReturnType<Option.Option<Page<Item_>>>(),\n Match.tag(\"Refreshing\", \"Success\", \"Stale\", (dataPhase) =>\n Option.some(dataPhase.data),\n ),\n Match.tag(\"Loading\", \"Failure\", () => Option.none()),\n Match.exhaustive,\n );\n\nconst pendingPhase = <Item_>(\n data: Option.Option<Page<Item_>>,\n direction: Direction,\n): Loading | Refreshing<Item_> =>\n Option.match(data, {\n onNone: () => Phase.Loading<Item_, never>({ direction }),\n onSome: (page) => Phase.Refreshing<Item_, never>({ data: page, direction }),\n });\n\n/** Close the subscription while retaining its generation tombstone. */\nexport const close = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Idle => State.Idle({ generation: state.generation });\n\n/** Start a fresh pagination session at page one while retaining visible data. */\nexport const reset = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Active<Item_, UserArgs_, Error_> => ({\n ...state,\n generation: state.generation + 1,\n paginationId: Option.none(),\n requestId: 1,\n current: firstDescriptor(),\n prevStack: [],\n phase: pendingPhase(phaseData(state.phase), \"Reset\"),\n});\n\n/**\n * Navigate to the next page, retaining the current page while it loads.\n *\n * The page being left is pushed onto the stack *pinned* to the range it\n * displayed—its cursor to its continuation cursor—so `prev` reloads\n * exactly that range rather than the first `initialNumItems` documents\n * after its cursor, however the data has moved meanwhile. Convex's own\n * pagination keeps that range in its query journal; stream-paginated\n * queries have no journal, so the pin is what keeps consecutive pages\n * gap-free and duplicate-free for them.\n */\nexport const next = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Option.Option<Active<Item_, UserArgs_, Error_>> =>\n Match.value(state.phase).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.tag(\"Success\", ({ data }) =>\n Match.value(data.isDone).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.when(true, () => Option.none()),\n Match.when(false, () => {\n const end = Option.getOrElse(\n data.descriptor.endCursor,\n () => data.continueCursor,\n );\n return Option.some({\n ...state,\n requestId: state.requestId + 1,\n current: { cursor: end, endCursor: Option.none() },\n prevStack: [\n ...state.prevStack,\n { cursor: data.descriptor.cursor, endCursor: Option.some(end) },\n ],\n phase: Phase.Refreshing<Item_, Error_>({\n data,\n direction: \"Next\",\n }),\n });\n }),\n Match.exhaustive,\n ),\n ),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => Option.none()),\n Match.exhaustive,\n );\n\n/** Navigate to the previous page, retaining the current page while it loads. */\nexport const prev = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Option.Option<Active<Item_, UserArgs_, Error_>> =>\n Match.value(state.phase).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.tag(\"Success\", ({ data }) => {\n const current = state.prevStack.at(-1);\n return Match.value(current).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.when(undefined, () => Option.none()),\n Match.when(Match.defined, (previous) =>\n Option.some({\n ...state,\n requestId: state.requestId + 1,\n current: previous,\n prevStack: state.prevStack.slice(0, -1),\n phase: Phase.Refreshing<Item_, Error_>({\n data,\n direction: \"Previous\",\n }),\n }),\n ),\n Match.exhaustive,\n );\n }),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => Option.none()),\n Match.exhaustive,\n );\n\n/** Navigate to page one without invalidating the current pagination session. */\nexport const first = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Option.Option<Active<Item_, UserArgs_, Error_>> =>\n Match.value(\n state.prevStack.length === 0 &&\n descriptorEquals(state.current, firstDescriptor()),\n ).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.when(true, () => Option.none()),\n Match.when(false, () =>\n Option.some({\n ...state,\n requestId: state.requestId + 1,\n current: firstDescriptor(),\n prevStack: [],\n phase: pendingPhase(phaseData(state.phase), \"First\"),\n }),\n ),\n Match.exhaustive,\n );\n\n/** Whether a request still names the machine's live pagination session/page. */\nexport const isCurrentRequest = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n candidate: Request<UserArgs_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", (active) =>\n Match.value(active.paginationId).pipe(\n Match.tag(\"None\", () =>\n Match.value(\n active.generation === candidate.generation &&\n active.requestId === candidate.requestId &&\n descriptorEquals(active.current, candidate.descriptor),\n ).pipe(\n Match.when(true, () => true),\n Match.when(false, () => false),\n Match.exhaustive,\n ),\n ),\n Match.tag(\n \"Some\",\n ({ value }) =>\n active.generation === candidate.generation &&\n value === candidate.paginationId &&\n active.requestId === candidate.requestId &&\n descriptorEquals(active.current, candidate.descriptor),\n ),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\nconst pageFromResult = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n result: PageResult<Item_>,\n): Page<Item_> => ({\n descriptor: state.current,\n number: state.prevStack.length + 1,\n items: result.page,\n continueCursor: result.continueCursor,\n isDone: result.isDone,\n});\n\nconst settleSuccess = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n result: PageResult<Item_>,\n): Active<Item_, UserArgs_, Error_> => {\n const splitCursor = result.splitCursor;\n const splitSignaled = Match.value(result.pageStatus).pipe(\n Match.whenOr(\"SplitRecommended\", \"SplitRequired\", () => true),\n Match.whenOr(null, undefined, () => false),\n Match.exhaustive,\n );\n const shouldSplit =\n typeof splitCursor === \"string\" &&\n (splitSignaled || result.page.length > 2 * state.options.initialNumItems);\n const shouldRetreat =\n result.page.length === 0 && result.isDone && state.prevStack.length > 0;\n\n return Match.value(shouldSplit).pipe(\n Match.withReturnType<Active<Item_, UserArgs_, Error_>>(),\n Match.when(true, () => {\n const deliveredPage = pageFromResult(state, result);\n const previous = Match.value(result.pageStatus).pipe(\n Match.withReturnType<Option.Option<Page<Item_>>>(),\n Match.when(\"SplitRequired\", () => phaseData(state.phase)),\n Match.whenOr(\"SplitRecommended\", null, undefined, () =>\n Option.some(deliveredPage),\n ),\n Match.exhaustive,\n );\n return {\n ...state,\n requestId: state.requestId + 1,\n current: {\n cursor: state.current.cursor,\n endCursor: Option.fromNullishOr(splitCursor),\n },\n phase: pendingPhase(previous, \"Split\"),\n };\n }),\n Match.when(false, () =>\n Match.value(shouldRetreat).pipe(\n Match.withReturnType<Active<Item_, UserArgs_, Error_>>(),\n Match.when(true, () => ({\n ...state,\n requestId: state.requestId + 1,\n current: state.prevStack[state.prevStack.length - 1],\n prevStack: state.prevStack.slice(0, -1),\n phase: pendingPhase(phaseData(state.phase), \"Previous\"),\n })),\n Match.when(false, () => ({\n ...state,\n phase: Phase.Success<Item_, Error_>({\n data: pageFromResult(state, result),\n }),\n })),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n};\n\nconst settleFailure = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n error: Error_,\n): Active<Item_, UserArgs_, Error_> => ({\n ...state,\n phase: Option.match(phaseData(state.phase), {\n onNone: () => Phase.Failure<Item_, Error_>({ error }),\n onSome: (data) => Phase.Stale<Item_, Error_>({ error, data }),\n }),\n});\n\n/**\n * Fold a correlated `Result` into the machine. Like `AsyncData.settle`, a\n * success becomes `Success`; a failure becomes `Stale` when a page is held,\n * otherwise `Failure`. Outcomes from superseded requests and outcomes that\n * arrive after the subscription closed are ignored.\n */\nexport const settle: {\n <Item_, UserArgs_, Error_>(\n settlement: Settlement<Item_, UserArgs_, Error_>,\n ): (\n state: State<Item_, UserArgs_, Error_>,\n ) => State<Item_, UserArgs_, Error_>;\n <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n settlement: Settlement<Item_, UserArgs_, Error_>,\n ): State<Item_, UserArgs_, Error_>;\n} = Function.dual(\n 2,\n <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n settlement: Settlement<Item_, UserArgs_, Error_>,\n ): State<Item_, UserArgs_, Error_> =>\n Match.value(state).pipe(\n Match.withReturnType<State<Item_, UserArgs_, Error_>>(),\n Match.tag(\"Idle\", () => state),\n Match.tag(\"Active\", (active) =>\n Match.value(isCurrentRequest(active, settlement.request)).pipe(\n Match.when(false, () => active),\n Match.when(true, () => {\n const allocated = {\n ...active,\n paginationId: Option.some(settlement.request.paginationId),\n };\n return Result.match(settlement.result, {\n onSuccess: (result) => settleSuccess(allocated, result),\n onFailure: (error) =>\n Match.value(error).pipe(\n Match.when(\n Match.instanceOf(PaginationError.InvalidCursor),\n () => reset(allocated),\n ),\n Match.orElse((other) => settleFailure(allocated, other)),\n ),\n });\n }),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n ),\n);\n\n/** The complete page currently available to render. */\nexport const getPage = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): Option.Option<Page<Item_>> =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => Option.none()),\n Match.tag(\"Active\", ({ phase }) => phaseData(phase)),\n Match.exhaustive,\n );\n\n/** The items currently available to render. */\nexport const getItems = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): Option.Option<ReadonlyArray<Item_>> =>\n Option.map(getPage(state), (page) => page.items);\n\n/** The error from the most recent failed request, if any. */\nexport const getError = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): Option.Option<Error_> =>\n Match.value(state).pipe(\n Match.withReturnType<Option.Option<Error_>>(),\n Match.tag(\"Idle\", () => Option.none()),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.withReturnType<Option.Option<Error_>>(),\n Match.tag(\"Failure\", \"Stale\", ({ error }) => Option.some(error)),\n Match.tag(\"Loading\", \"Refreshing\", \"Success\", () => Option.none()),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\n/** The 1-indexed page number currently targeted by the subscription. */\nexport const targetPageNumber = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): number => state.prevStack.length + 1;\n\nexport const hasPage = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean => Option.isSome(getPage(state));\n\nexport const hasError = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean => Option.isSome(getError(state));\n\nexport const isFirst = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ prevStack }) => prevStack.length === 0),\n Match.exhaustive,\n );\n\nexport const isLast = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.tag(\"Success\", ({ data }) => data.isDone),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => false),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\ntype WithPhase<State_, Phase_> = Omit<State_, \"phase\"> & {\n readonly phase: Phase_;\n};\n\nexport const isIdle = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is Idle => state._tag === \"Idle\";\n\nexport const isLoading = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Loading> =>\n state._tag === \"Active\" && state.phase._tag === \"Loading\";\n\nexport const isRefreshing = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Refreshing<Item_>> =>\n state._tag === \"Active\" && state.phase._tag === \"Refreshing\";\n\nexport const isSuccess = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Success<Item_>> =>\n state._tag === \"Active\" && state.phase._tag === \"Success\";\n\nexport const isFailure = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Failure<Error_>> =>\n state._tag === \"Active\" && state.phase._tag === \"Failure\";\n\nexport const isStale = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Stale<Item_, Error_>> =>\n state._tag === \"Active\" && state.phase._tag === \"Stale\";\n\nexport const isPending = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.tag(\"Loading\", \"Refreshing\", () => true),\n Match.tag(\"Success\", \"Failure\", \"Stale\", () => false),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\nexport const canNext = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.tag(\"Success\", ({ data }) => !data.isDone),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => false),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\nexport const canPrev = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ phase, prevStack }) =>\n Match.value(phase).pipe(\n Match.tag(\"Success\", () => prevStack.length > 0),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => false),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\n/** Pattern-match exhaustively on the machine's AsyncData-style state. */\nexport const match: {\n <Item_, Error_, A, B, C, D, E, F>(handlers: {\n readonly onIdle: (idle: Idle) => A;\n readonly onLoading: (loading: Loading) => B;\n readonly onRefreshing: (refreshing: Refreshing<Item_>) => C;\n readonly onFailure: (failure: Failure<Error_>) => D;\n readonly onStale: (stale: Stale<Item_, Error_>) => E;\n readonly onSuccess: (success: Success<Item_>) => F;\n }): <UserArgs_>(\n state: State<Item_, UserArgs_, Error_>,\n ) => A | B | C | D | E | F;\n <Item_, UserArgs_, Error_, A, B, C, D, E, F>(\n state: State<Item_, UserArgs_, Error_>,\n handlers: {\n readonly onIdle: (idle: Idle) => A;\n readonly onLoading: (loading: Loading) => B;\n readonly onRefreshing: (refreshing: Refreshing<Item_>) => C;\n readonly onFailure: (failure: Failure<Error_>) => D;\n readonly onStale: (stale: Stale<Item_, Error_>) => E;\n readonly onSuccess: (success: Success<Item_>) => F;\n },\n ): A | B | C | D | E | F;\n} = Function.dual(\n 2,\n <Item_, UserArgs_, Error_, A, B, C, D, E, F>(\n state: State<Item_, UserArgs_, Error_>,\n handlers: {\n readonly onIdle: (idle: Idle) => A;\n readonly onLoading: (loading: Loading) => B;\n readonly onRefreshing: (refreshing: Refreshing<Item_>) => C;\n readonly onFailure: (failure: Failure<Error_>) => D;\n readonly onStale: (stale: Stale<Item_, Error_>) => E;\n readonly onSuccess: (success: Success<Item_>) => F;\n },\n ): A | B | C | D | E | F =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", handlers.onIdle),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.tag(\"Loading\", handlers.onLoading),\n Match.tag(\"Refreshing\", handlers.onRefreshing),\n Match.tag(\"Failure\", handlers.onFailure),\n Match.tag(\"Stale\", handlers.onStale),\n Match.tag(\"Success\", handlers.onSuccess),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n ) as A | B | C | D | E | F,\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PaginatedQuery.js","names":["Client.WebSocketClientError"],"sources":["../src/PaginatedQuery.ts"],"sourcesContent":["import * as MiddlewareSpec from \"@confect/core/MiddlewareSpec\";\nimport * as PaginationError from \"@confect/core/PaginationError\";\nimport * as Ref from \"@confect/core/Ref\";\nimport * as Data from \"effect/Data\";\nimport * as Function from \"effect/Function\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as Result from \"effect/Result\";\nimport * as Schema from \"effect/Schema\";\nimport * as SchemaGetter from \"effect/SchemaGetter\";\nimport * as SchemaIssue from \"effect/SchemaIssue\";\nimport * as Client from \"./Client\";\n\n/**\n * Identifies the cursor range fetched for one page.\n */\nexport interface PageDescriptor {\n readonly cursor: string | null;\n readonly endCursor: Option.Option<string>;\n}\n\nexport const PageDescriptor = Schema.Struct({\n cursor: Schema.Union([Schema.String, Schema.Null]),\n endCursor: Schema.Option(Schema.String),\n});\n\n/**\n * Options that remain fixed for one pagination session.\n */\nexport interface Options {\n readonly initialNumItems: number;\n readonly maximumRowsRead?: number;\n readonly maximumBytesRead?: number;\n}\n\nconst PositiveInt = Schema.Int.check(Schema.isGreaterThan(0));\nconst NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));\n\nexport const Options = Schema.Struct({\n initialNumItems: PositiveInt,\n maximumRowsRead: Schema.optionalKey(PositiveInt),\n maximumBytesRead: Schema.optionalKey(PositiveInt),\n});\n\n/**\n * Why the machine is fetching its current target.\n */\nexport type Direction =\n | \"Initial\"\n | \"Next\"\n | \"Previous\"\n | \"First\"\n | \"Split\"\n | \"Reset\";\n\n/**\n * A complete page that can remain on screen while another page is fetched.\n */\nexport interface Page<Item_> {\n readonly descriptor: PageDescriptor;\n readonly number: number;\n readonly items: ReadonlyArray<Item_>;\n readonly continueCursor: string;\n readonly isDone: boolean;\n}\n\nexport type Loading = Data.TaggedEnum<{\n Loading: { readonly direction: Direction };\n}>;\n\nexport type Refreshing<Item_> = Data.TaggedEnum<{\n Refreshing: { readonly data: Page<Item_>; readonly direction: Direction };\n}>;\n\nexport type Success<Item_> = Data.TaggedEnum<{\n Success: { readonly data: Page<Item_> };\n}>;\n\nexport type Failure<Error_> = Data.TaggedEnum<{\n Failure: { readonly error: Error_ };\n}>;\n\nexport type Stale<Item_, Error_> = Data.TaggedEnum<{\n Stale: { readonly data: Page<Item_>; readonly error: Error_ };\n}>;\n\nexport type Phase<Item_, Error_> =\n | Loading\n | Refreshing<Item_>\n | Success<Item_>\n | Failure<Error_>\n | Stale<Item_, Error_>;\n\ninterface PhaseDefinition extends Data.TaggedEnum.WithGenerics<2> {\n readonly taggedEnum: Phase<this[\"A\"], this[\"B\"]>;\n}\n\nconst Phase = Data.taggedEnum<PhaseDefinition>();\n\n/**\n * A closed machine that retains its generation for stale-result rejection.\n */\nexport type Idle = Data.TaggedEnum<{\n Idle: { readonly generation: number };\n}>;\n\n/**\n * A live cursor-pagination session.\n */\nexport type Active<Item_, UserArgs_, Error_> = Data.TaggedEnum<{\n Active: {\n readonly generation: number;\n readonly args: UserArgs_;\n readonly options: Options;\n readonly paginationId: Option.Option<number>;\n readonly requestId: number;\n readonly current: PageDescriptor;\n readonly prevStack: ReadonlyArray<PageDescriptor>;\n readonly phase: Phase<Item_, Error_>;\n };\n}>;\n\n/**\n * A schema-backed cursor-pagination machine.\n */\nexport type State<Item_, UserArgs_, Error_> =\n | Idle\n | Active<Item_, UserArgs_, Error_>;\n\ninterface StateDefinition extends Data.TaggedEnum.WithGenerics<3> {\n readonly taggedEnum: State<this[\"A\"], this[\"B\"], this[\"C\"]>;\n}\n\nconst State = Data.taggedEnum<StateDefinition>();\n\n/**\n * The logical request from which a subscription allocates a session id.\n */\nexport interface SubscriptionRequest<UserArgs_> {\n readonly generation: number;\n readonly args: UserArgs_;\n readonly options: Options;\n readonly paginationId: Option.Option<number>;\n readonly requestId: number;\n readonly descriptor: PageDescriptor;\n}\n\n/**\n * The complete identity and arguments of a subscribed page request.\n */\nexport interface Request<UserArgs_> {\n readonly generation: number;\n readonly args: UserArgs_;\n readonly options: Options;\n readonly paginationId: number;\n readonly requestId: number;\n readonly descriptor: PageDescriptor;\n}\n\n/**\n * The successful payload returned by a Convex paginated query.\n */\nexport interface PageResult<Item_> {\n readonly page: ReadonlyArray<Item_>;\n readonly isDone: boolean;\n readonly continueCursor: string;\n readonly splitCursor?: string | null;\n readonly pageStatus?: \"SplitRecommended\" | \"SplitRequired\" | null;\n}\n\n/**\n * One correlated subscription outcome. Both success and failure travel through\n * this value so `settle` can mirror `AsyncData.settle`.\n */\nexport interface Settlement<Item_, UserArgs_, Error_> {\n readonly request: Request<UserArgs_>;\n readonly result: Result.Result<PageResult<Item_>, Error_>;\n}\n\nexport type Item<Query extends Ref.AnyConfectPublicPaginatedQuery> =\n Ref.Returns<Query>[\"page\"][number];\n\nexport type UserArgs<Query extends Ref.AnyConfectPublicPaginatedQuery> = Omit<\n Ref.Args<Query>,\n \"paginationOpts\"\n>;\n\ntype TaggedFunctionError<Error_> = Data.TaggedEnum<{\n FunctionError: { readonly error: Error_ };\n}>;\n\ninterface FunctionErrorDefinition extends Data.TaggedEnum.WithGenerics<1> {\n readonly taggedEnum: TaggedFunctionError<this[\"A\"]>;\n}\n\n/**\n * Constructs a declared function or middleware failure envelope.\n */\nexport const FunctionError =\n Data.taggedEnum<FunctionErrorDefinition>().FunctionError;\n\n/**\n * A declared function or middleware failure, kept distinct from client errors.\n */\nexport type FunctionError<Query extends Ref.AnyConfectPublicPaginatedQuery> = [\n Ref.Error<Query>,\n] extends [never]\n ? never\n : TaggedFunctionError<Ref.Error<Query>>;\n\n/**\n * Every failure a paginated query subscription can settle with.\n */\nexport type Error<Query extends Ref.AnyConfectPublicPaginatedQuery> =\n | FunctionError<Query>\n | PaginationError.InvalidCursor\n | Client.WebSocketClientError\n | Schema.SchemaError;\n\nexport { InvalidCursor } from \"@confect/core/PaginationError\";\n\ntype MachineState<Query extends Ref.AnyConfectPublicPaginatedQuery> = State<\n Item<Query>,\n UserArgs<Query>,\n Error<Query>\n>;\n\ntype MachineActive<Query extends Ref.AnyConfectPublicPaginatedQuery> = Active<\n Item<Query>,\n UserArgs<Query>,\n Error<Query>\n>;\n\n/**\n * The schema-and-constructor bundle returned by `make`.\n */\nexport interface PaginatedQuery<\n Query extends Ref.AnyConfectPublicPaginatedQuery,\n> {\n readonly ref: Query;\n readonly schema: Schema.Codec<MachineState<Query>, unknown>;\n readonly idle: Idle;\n readonly subscriptionRequestSchema: Schema.Codec<\n SubscriptionRequest<UserArgs<Query>>,\n unknown\n >;\n readonly requestSchema: Schema.Codec<Request<UserArgs<Query>>, unknown>;\n readonly settlement: Schema.Codec<\n Settlement<Item<Query>, UserArgs<Query>, Error<Query>>,\n unknown\n >;\n readonly init: keyof UserArgs<Query> extends never\n ? (state: Idle, options: Options) => MachineActive<Query>\n : (\n state: Idle,\n args: UserArgs<Query>,\n options: Options,\n ) => MachineActive<Query>;\n readonly reinitialize: keyof UserArgs<Query> extends never\n ? (state: MachineActive<Query>, options?: Options) => MachineActive<Query>\n : (\n state: MachineActive<Query>,\n args: UserArgs<Query>,\n options?: Options,\n ) => MachineActive<Query>;\n}\n\nexport type Any = PaginatedQuery<Ref.AnyConfectPublicPaginatedQuery>;\n\nconst firstDescriptor = (): PageDescriptor => ({\n cursor: null,\n endCursor: Option.none(),\n});\n\nconst decodeOptions = Schema.decodeUnknownSync(Options);\n\nconst initialState = <Item_, UserArgs_, Error_>(\n generation: number,\n args: UserArgs_,\n options: Options,\n): Active<Item_, UserArgs_, Error_> =>\n State.Active<Item_, UserArgs_, Error_>({\n generation,\n args,\n options: decodeOptions(options),\n paginationId: Option.none(),\n requestId: 1,\n current: firstDescriptor(),\n prevStack: [],\n phase: Phase.Loading<Item_, Error_>({ direction: \"Initial\" }),\n });\n\nconst missingPaginatedProvenanceError = (ref: Ref.AnyConfect) =>\n new globalThis.Error(\n `Paginated query ref \"${Ref.getConvexFunctionName(ref)}\" was not built ` +\n \"with `FunctionSpec.publicPaginatedQuery`. `PaginatedQuery.make` \" +\n \"requires the user-args and item schemas that constructor stores.\",\n );\n\nconst paginatedKindOrThrow = (ref: Ref.AnyConfectPublicPaginatedQuery) =>\n Match.value(ref.kind).pipe(\n Match.tag(\"Paginated\", (kind) => kind),\n Match.tag(\"Standard\", () => {\n throw missingPaginatedProvenanceError(ref);\n }),\n Match.exhaustive,\n );\n\nconst SchemaErrorJson = Schema.TaggedStruct(\"SchemaError\", {\n message: Schema.String,\n});\n\nconst SerializableSchemaError = Schema.instanceOf(Schema.SchemaError, {\n toCodecJson: () =>\n Schema.link<Schema.SchemaError>()(SchemaErrorJson, {\n decode: SchemaGetter.transform(\n ({ message }) =>\n new Schema.SchemaError(new SchemaIssue.InvalidValue({ message })),\n ),\n encode: SchemaGetter.transform((error) =>\n SchemaErrorJson.make({ message: error.message }),\n ),\n }),\n});\n\n/**\n * Builds a page machine from a paginated ref.\n */\nexport const make = <Query extends Ref.AnyConfectPublicPaginatedQuery>(\n ref: Query,\n): PaginatedQuery<Query> => {\n const kind = paginatedKindOrThrow(ref);\n const hasUserArgs = globalThis.Object.keys(kind.userArgs.fields).length > 0;\n const functionErrorSchemas = [\n ...(\"error\" in ref && ref.error !== undefined ? [ref.error] : []),\n ...MiddlewareSpec.errorSchemas(ref.middlewareSpecs),\n ];\n const errorSchema = Schema.Union([\n PaginationError.InvalidCursor,\n Client.WebSocketClientError,\n SerializableSchemaError,\n ...(functionErrorSchemas.length === 0\n ? []\n : [\n Schema.TaggedStruct(\"FunctionError\", {\n error:\n functionErrorSchemas.length === 1\n ? functionErrorSchemas[0]!\n : Schema.Union(functionErrorSchemas),\n }),\n ]),\n ]) as Schema.Codec<Error<Query>, unknown>;\n const directions = Schema.Literals([\n \"Initial\",\n \"Next\",\n \"Previous\",\n \"First\",\n \"Split\",\n \"Reset\",\n ]);\n const page = Schema.Struct({\n descriptor: PageDescriptor,\n number: PositiveInt,\n items: kind.page,\n continueCursor: Schema.String,\n isDone: Schema.Boolean,\n });\n const phase = Schema.TaggedUnion({\n Loading: { direction: directions },\n Refreshing: { data: page, direction: directions },\n Success: { data: page },\n Failure: { error: errorSchema },\n Stale: { data: page, error: errorSchema },\n });\n const subscriptionRequestSchema: PaginatedQuery<Query>[\"subscriptionRequestSchema\"] =\n Schema.Struct({\n generation: PositiveInt,\n args: kind.userArgs,\n options: Options,\n paginationId: Schema.Option(PositiveInt),\n requestId: PositiveInt,\n descriptor: PageDescriptor,\n });\n const requestSchema: PaginatedQuery<Query>[\"requestSchema\"] = Schema.Struct({\n generation: PositiveInt,\n args: kind.userArgs,\n options: Options,\n paginationId: PositiveInt,\n requestId: PositiveInt,\n descriptor: PageDescriptor,\n });\n const pageResult = Schema.Struct({\n page: kind.page,\n isDone: Schema.Boolean,\n continueCursor: Schema.String,\n splitCursor: Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])),\n pageStatus: Schema.optionalKey(\n Schema.Union([\n Schema.Literal(\"SplitRecommended\"),\n Schema.Literal(\"SplitRequired\"),\n Schema.Null,\n ]),\n ),\n });\n const schema: PaginatedQuery<Query>[\"schema\"] = Schema.TaggedUnion({\n Idle: { generation: NonNegativeInt },\n Active: {\n generation: PositiveInt,\n args: kind.userArgs,\n options: Options,\n paginationId: Schema.Option(PositiveInt),\n requestId: PositiveInt,\n current: PageDescriptor,\n prevStack: Schema.Array(PageDescriptor),\n phase,\n },\n });\n const settlement: PaginatedQuery<Query>[\"settlement\"] = Schema.Struct({\n request: requestSchema,\n result: Schema.Result(pageResult, errorSchema),\n });\n\n const init: PaginatedQuery<Query>[\"init\"] = (\n state: Idle,\n argsOrOptions: UserArgs<Query> | Options,\n options?: Options,\n ): MachineActive<Query> =>\n Match.value(options).pipe(\n Match.withReturnType<MachineActive<Query>>(),\n Match.when(undefined, () =>\n initialState(\n state.generation + 1,\n {} as UserArgs<Query>,\n argsOrOptions as Options,\n ),\n ),\n Match.when(Match.defined, (definedOptions) =>\n initialState(\n state.generation + 1,\n argsOrOptions as UserArgs<Query>,\n definedOptions,\n ),\n ),\n Match.exhaustive,\n );\n\n const reinitialize: PaginatedQuery<Query>[\"reinitialize\"] = (\n state: MachineActive<Query>,\n argsOrOptions?: UserArgs<Query> | Options,\n options?: Options,\n ): MachineActive<Query> =>\n Match.value(options).pipe(\n Match.withReturnType<MachineActive<Query>>(),\n Match.when(Match.defined, (definedOptions) =>\n initialState(\n state.generation + 1,\n argsOrOptions as UserArgs<Query>,\n definedOptions,\n ),\n ),\n Match.when(undefined, () =>\n Match.value(argsOrOptions).pipe(\n Match.withReturnType<MachineActive<Query>>(),\n Match.when(undefined, () =>\n initialState(state.generation + 1, state.args, state.options),\n ),\n Match.when(Match.defined, (definedArgsOrOptions) =>\n Match.value(hasUserArgs).pipe(\n Match.withReturnType<MachineActive<Query>>(),\n Match.when(true, () =>\n initialState(\n state.generation + 1,\n definedArgsOrOptions as UserArgs<Query>,\n state.options,\n ),\n ),\n Match.when(false, () =>\n initialState(\n state.generation + 1,\n state.args,\n definedArgsOrOptions as Options,\n ),\n ),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\n return {\n ref,\n schema,\n idle: State.Idle({ generation: 0 }),\n subscriptionRequestSchema,\n requestSchema,\n settlement,\n init,\n reinitialize,\n };\n};\n\nconst descriptorEquals = (a: PageDescriptor, b: PageDescriptor): boolean =>\n a.cursor === b.cursor &&\n Option.match(a.endCursor, {\n onNone: () => Option.isNone(b.endCursor),\n onSome: (aEnd) =>\n Option.match(b.endCursor, {\n onNone: () => false,\n onSome: (bEnd) => aEnd === bEnd,\n }),\n });\n\n/**\n * Returns the logical request currently driving the subscription.\n */\nexport const getSubscriptionRequest = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): SubscriptionRequest<UserArgs_> => ({\n generation: state.generation,\n args: state.args,\n options: state.options,\n paginationId: state.paginationId,\n requestId: state.requestId,\n descriptor: state.current,\n});\n\n/**\n * Attaches the client-allocated pagination id to a logical request.\n */\nexport const allocateRequest = <UserArgs_>(\n request: SubscriptionRequest<UserArgs_>,\n paginationId: number,\n): Request<UserArgs_> => ({\n ...request,\n paginationId,\n});\n\nconst phaseData = <Item_, Error_>(\n phase: Phase<Item_, Error_>,\n): Option.Option<Page<Item_>> =>\n Match.value(phase).pipe(\n Match.withReturnType<Option.Option<Page<Item_>>>(),\n Match.tag(\"Refreshing\", \"Success\", \"Stale\", (dataPhase) =>\n Option.some(dataPhase.data),\n ),\n Match.tag(\"Loading\", \"Failure\", () => Option.none()),\n Match.exhaustive,\n );\n\nconst pendingPhase = <Item_>(\n data: Option.Option<Page<Item_>>,\n direction: Direction,\n): Loading | Refreshing<Item_> =>\n Option.match(data, {\n onNone: () => Phase.Loading<Item_, never>({ direction }),\n onSome: (page) => Phase.Refreshing<Item_, never>({ data: page, direction }),\n });\n\n/**\n * Close the subscription while retaining its generation tombstone.\n */\nexport const close = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Idle => State.Idle({ generation: state.generation });\n\n/**\n * Start a fresh pagination session at page one while retaining visible data.\n */\nexport const reset = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Active<Item_, UserArgs_, Error_> => ({\n ...state,\n generation: state.generation + 1,\n paginationId: Option.none(),\n requestId: 1,\n current: firstDescriptor(),\n prevStack: [],\n phase: pendingPhase(phaseData(state.phase), \"Reset\"),\n});\n\n/**\n * Navigate to the next page, retaining the current page while it loads.\n *\n * The page being left is pushed onto the stack _pinned_ to the range it\n * displayed—its cursor to its continuation cursor—so `prev` reloads exactly\n * that range rather than the first `initialNumItems` documents after its\n * cursor, however the data has moved meanwhile. Convex's own pagination keeps\n * that range in its query journal; stream-paginated queries have no journal, so\n * the pin is what keeps consecutive pages gap-free and duplicate-free for\n * them.\n */\nexport const next = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Option.Option<Active<Item_, UserArgs_, Error_>> =>\n Match.value(state.phase).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.tag(\"Success\", ({ data }) =>\n Match.value(data.isDone).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.when(true, () => Option.none()),\n Match.when(false, () => {\n const end = Option.getOrElse(\n data.descriptor.endCursor,\n () => data.continueCursor,\n );\n return Option.some({\n ...state,\n requestId: state.requestId + 1,\n current: { cursor: end, endCursor: Option.none() },\n prevStack: [\n ...state.prevStack,\n { cursor: data.descriptor.cursor, endCursor: Option.some(end) },\n ],\n phase: Phase.Refreshing<Item_, Error_>({\n data,\n direction: \"Next\",\n }),\n });\n }),\n Match.exhaustive,\n ),\n ),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => Option.none()),\n Match.exhaustive,\n );\n\n/**\n * Navigate to the previous page, retaining the current page while it loads.\n */\nexport const prev = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Option.Option<Active<Item_, UserArgs_, Error_>> =>\n Match.value(state.phase).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.tag(\"Success\", ({ data }) => {\n const current = state.prevStack.at(-1);\n return Match.value(current).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.when(undefined, () => Option.none()),\n Match.when(Match.defined, (previous) =>\n Option.some({\n ...state,\n requestId: state.requestId + 1,\n current: previous,\n prevStack: state.prevStack.slice(0, -1),\n phase: Phase.Refreshing<Item_, Error_>({\n data,\n direction: \"Previous\",\n }),\n }),\n ),\n Match.exhaustive,\n );\n }),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => Option.none()),\n Match.exhaustive,\n );\n\n/**\n * Navigate to page one without invalidating the current pagination session.\n */\nexport const first = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): Option.Option<Active<Item_, UserArgs_, Error_>> =>\n Match.value(\n state.prevStack.length === 0 &&\n descriptorEquals(state.current, firstDescriptor()),\n ).pipe(\n Match.withReturnType<Option.Option<Active<Item_, UserArgs_, Error_>>>(),\n Match.when(true, () => Option.none()),\n Match.when(false, () =>\n Option.some({\n ...state,\n requestId: state.requestId + 1,\n current: firstDescriptor(),\n prevStack: [],\n phase: pendingPhase(phaseData(state.phase), \"First\"),\n }),\n ),\n Match.exhaustive,\n );\n\n/**\n * Whether a request still names the machine's live pagination session/page.\n */\nexport const isCurrentRequest = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n candidate: Request<UserArgs_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", (active) =>\n Match.value(active.paginationId).pipe(\n Match.tag(\"None\", () =>\n Match.value(\n active.generation === candidate.generation &&\n active.requestId === candidate.requestId &&\n descriptorEquals(active.current, candidate.descriptor),\n ).pipe(\n Match.when(true, () => true),\n Match.when(false, () => false),\n Match.exhaustive,\n ),\n ),\n Match.tag(\n \"Some\",\n ({ value }) =>\n active.generation === candidate.generation &&\n value === candidate.paginationId &&\n active.requestId === candidate.requestId &&\n descriptorEquals(active.current, candidate.descriptor),\n ),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\nconst pageFromResult = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n result: PageResult<Item_>,\n): Page<Item_> => ({\n descriptor: state.current,\n number: state.prevStack.length + 1,\n items: result.page,\n continueCursor: result.continueCursor,\n isDone: result.isDone,\n});\n\nconst settleSuccess = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n result: PageResult<Item_>,\n): Active<Item_, UserArgs_, Error_> => {\n const splitCursor = result.splitCursor;\n const splitSignaled = Match.value(result.pageStatus).pipe(\n Match.whenOr(\"SplitRecommended\", \"SplitRequired\", () => true),\n Match.whenOr(null, undefined, () => false),\n Match.exhaustive,\n );\n const shouldSplit =\n typeof splitCursor === \"string\" &&\n (splitSignaled || result.page.length > 2 * state.options.initialNumItems);\n const shouldRetreat =\n result.page.length === 0 && result.isDone && state.prevStack.length > 0;\n\n return Match.value(shouldSplit).pipe(\n Match.withReturnType<Active<Item_, UserArgs_, Error_>>(),\n Match.when(true, () => {\n const deliveredPage = pageFromResult(state, result);\n const previous = Match.value(result.pageStatus).pipe(\n Match.withReturnType<Option.Option<Page<Item_>>>(),\n Match.when(\"SplitRequired\", () => phaseData(state.phase)),\n Match.whenOr(\"SplitRecommended\", null, undefined, () =>\n Option.some(deliveredPage),\n ),\n Match.exhaustive,\n );\n return {\n ...state,\n requestId: state.requestId + 1,\n current: {\n cursor: state.current.cursor,\n endCursor: Option.fromNullishOr(splitCursor),\n },\n phase: pendingPhase(previous, \"Split\"),\n };\n }),\n Match.when(false, () =>\n Match.value(shouldRetreat).pipe(\n Match.withReturnType<Active<Item_, UserArgs_, Error_>>(),\n Match.when(true, () => ({\n ...state,\n requestId: state.requestId + 1,\n current: state.prevStack[state.prevStack.length - 1],\n prevStack: state.prevStack.slice(0, -1),\n phase: pendingPhase(phaseData(state.phase), \"Previous\"),\n })),\n Match.when(false, () => ({\n ...state,\n phase: Phase.Success<Item_, Error_>({\n data: pageFromResult(state, result),\n }),\n })),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n};\n\nconst settleFailure = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n error: Error_,\n): Active<Item_, UserArgs_, Error_> => ({\n ...state,\n phase: Option.match(phaseData(state.phase), {\n onNone: () => Phase.Failure<Item_, Error_>({ error }),\n onSome: (data) => Phase.Stale<Item_, Error_>({ error, data }),\n }),\n});\n\n/**\n * Fold a correlated `Result` into the machine. Like `AsyncData.settle`, a\n * success becomes `Success`; a failure becomes `Stale` when a page is held,\n * otherwise `Failure`. Outcomes from superseded requests and outcomes that\n * arrive after the subscription closed are ignored.\n */\nexport const settle: {\n <Item_, UserArgs_, Error_>(\n settlement: Settlement<Item_, UserArgs_, Error_>,\n ): (\n state: State<Item_, UserArgs_, Error_>,\n ) => State<Item_, UserArgs_, Error_>;\n <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n settlement: Settlement<Item_, UserArgs_, Error_>,\n ): State<Item_, UserArgs_, Error_>;\n} = Function.dual(\n 2,\n <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n settlement: Settlement<Item_, UserArgs_, Error_>,\n ): State<Item_, UserArgs_, Error_> =>\n Match.value(state).pipe(\n Match.withReturnType<State<Item_, UserArgs_, Error_>>(),\n Match.tag(\"Idle\", () => state),\n Match.tag(\"Active\", (active) =>\n Match.value(isCurrentRequest(active, settlement.request)).pipe(\n Match.when(false, () => active),\n Match.when(true, () => {\n const allocated = {\n ...active,\n paginationId: Option.some(settlement.request.paginationId),\n };\n return Result.match(settlement.result, {\n onSuccess: (result) => settleSuccess(allocated, result),\n onFailure: (error) =>\n Match.value(error).pipe(\n Match.when(\n Match.instanceOf(PaginationError.InvalidCursor),\n () => reset(allocated),\n ),\n Match.orElse((other) => settleFailure(allocated, other)),\n ),\n });\n }),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n ),\n);\n\n/**\n * The complete page currently available to render.\n */\nexport const getPage = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): Option.Option<Page<Item_>> =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => Option.none()),\n Match.tag(\"Active\", ({ phase }) => phaseData(phase)),\n Match.exhaustive,\n );\n\n/**\n * The items currently available to render.\n */\nexport const getItems = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): Option.Option<ReadonlyArray<Item_>> =>\n Option.map(getPage(state), (page) => page.items);\n\n/**\n * The error from the most recent failed request, if any.\n */\nexport const getError = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): Option.Option<Error_> =>\n Match.value(state).pipe(\n Match.withReturnType<Option.Option<Error_>>(),\n Match.tag(\"Idle\", () => Option.none()),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.withReturnType<Option.Option<Error_>>(),\n Match.tag(\"Failure\", \"Stale\", ({ error }) => Option.some(error)),\n Match.tag(\"Loading\", \"Refreshing\", \"Success\", () => Option.none()),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\n/**\n * The 1-indexed page number currently targeted by the subscription.\n */\nexport const targetPageNumber = <Item_, UserArgs_, Error_>(\n state: Active<Item_, UserArgs_, Error_>,\n): number => state.prevStack.length + 1;\n\nexport const hasPage = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean => Option.isSome(getPage(state));\n\nexport const hasError = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean => Option.isSome(getError(state));\n\nexport const isFirst = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ prevStack }) => prevStack.length === 0),\n Match.exhaustive,\n );\n\nexport const isLast = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.tag(\"Success\", ({ data }) => data.isDone),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => false),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\ntype WithPhase<State_, Phase_> = Omit<State_, \"phase\"> & {\n readonly phase: Phase_;\n};\n\nexport const isIdle = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is Idle => state._tag === \"Idle\";\n\nexport const isLoading = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Loading> =>\n state._tag === \"Active\" && state.phase._tag === \"Loading\";\n\nexport const isRefreshing = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Refreshing<Item_>> =>\n state._tag === \"Active\" && state.phase._tag === \"Refreshing\";\n\nexport const isSuccess = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Success<Item_>> =>\n state._tag === \"Active\" && state.phase._tag === \"Success\";\n\nexport const isFailure = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Failure<Error_>> =>\n state._tag === \"Active\" && state.phase._tag === \"Failure\";\n\nexport const isStale = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): state is WithPhase<Active<Item_, UserArgs_, Error_>, Stale<Item_, Error_>> =>\n state._tag === \"Active\" && state.phase._tag === \"Stale\";\n\nexport const isPending = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.tag(\"Loading\", \"Refreshing\", () => true),\n Match.tag(\"Success\", \"Failure\", \"Stale\", () => false),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\nexport const canNext = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.tag(\"Success\", ({ data }) => !data.isDone),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => false),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\nexport const canPrev = <Item_, UserArgs_, Error_>(\n state: State<Item_, UserArgs_, Error_>,\n): boolean =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", () => false),\n Match.tag(\"Active\", ({ phase, prevStack }) =>\n Match.value(phase).pipe(\n Match.tag(\"Success\", () => prevStack.length > 0),\n Match.tag(\"Loading\", \"Refreshing\", \"Failure\", \"Stale\", () => false),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n );\n\n/**\n * Pattern-match exhaustively on the machine's AsyncData-style state.\n */\nexport const match: {\n <Item_, Error_, A, B, C, D, E, F>(handlers: {\n readonly onIdle: (idle: Idle) => A;\n readonly onLoading: (loading: Loading) => B;\n readonly onRefreshing: (refreshing: Refreshing<Item_>) => C;\n readonly onFailure: (failure: Failure<Error_>) => D;\n readonly onStale: (stale: Stale<Item_, Error_>) => E;\n readonly onSuccess: (success: Success<Item_>) => F;\n }): <UserArgs_>(\n state: State<Item_, UserArgs_, Error_>,\n ) => A | B | C | D | E | F;\n <Item_, UserArgs_, Error_, A, B, C, D, E, F>(\n state: State<Item_, UserArgs_, Error_>,\n handlers: {\n readonly onIdle: (idle: Idle) => A;\n readonly onLoading: (loading: Loading) => B;\n readonly onRefreshing: (refreshing: Refreshing<Item_>) => C;\n readonly onFailure: (failure: Failure<Error_>) => D;\n readonly onStale: (stale: Stale<Item_, Error_>) => E;\n readonly onSuccess: (success: Success<Item_>) => F;\n },\n ): A | B | C | D | E | F;\n} = Function.dual(\n 2,\n <Item_, UserArgs_, Error_, A, B, C, D, E, F>(\n state: State<Item_, UserArgs_, Error_>,\n handlers: {\n readonly onIdle: (idle: Idle) => A;\n readonly onLoading: (loading: Loading) => B;\n readonly onRefreshing: (refreshing: Refreshing<Item_>) => C;\n readonly onFailure: (failure: Failure<Error_>) => D;\n readonly onStale: (stale: Stale<Item_, Error_>) => E;\n readonly onSuccess: (success: Success<Item_>) => F;\n },\n ): A | B | C | D | E | F =>\n Match.value(state).pipe(\n Match.tag(\"Idle\", handlers.onIdle),\n Match.tag(\"Active\", ({ phase }) =>\n Match.value(phase).pipe(\n Match.tag(\"Loading\", handlers.onLoading),\n Match.tag(\"Refreshing\", handlers.onRefreshing),\n Match.tag(\"Failure\", handlers.onFailure),\n Match.tag(\"Stale\", handlers.onStale),\n Match.tag(\"Success\", handlers.onSuccess),\n Match.exhaustive,\n ),\n ),\n Match.exhaustive,\n ) as A | B | C | D | E | F,\n);\n"],"mappings":"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"}
|
package/dist/Subscription.d.ts
CHANGED
|
@@ -15,16 +15,16 @@ import * as Client from "./Client";
|
|
|
15
15
|
export type Error<Query extends Ref.AnyConfectPublicQuery> = Ref.Error<Query> | Client.WebSocketClientError | Schema.SchemaError;
|
|
16
16
|
/**
|
|
17
17
|
* The dependency record of a `reactiveQuery` entry. `None` means the
|
|
18
|
-
* subscription is closed; a change from one `Some` to another tears the
|
|
19
|
-
*
|
|
18
|
+
* subscription is closed; a change from one `Some` to another tears the server
|
|
19
|
+
* subscription down and reopens it with the new args.
|
|
20
20
|
*/
|
|
21
21
|
export interface Dependencies<Query extends Ref.AnyConfectPublicQuery> {
|
|
22
22
|
readonly args: Option.Option<Ref.Args<Query>>;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* Maps a reactive query's emissions into the app's Messages. Every failure—the
|
|
26
|
-
*
|
|
27
|
-
* requires.
|
|
25
|
+
* Maps a reactive query's emissions into the app's Messages. Every failure—the
|
|
26
|
+
* ref's typed error, a transport error, or a codec error—arrives via `onError`,
|
|
27
|
+
* so the resulting stream's error channel is `never`, as Foldkit requires.
|
|
28
28
|
*/
|
|
29
29
|
export interface Handlers<Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage> {
|
|
30
30
|
readonly onSuccess: (returns: Ref.Returns<Query>) => SuccessMessage;
|
|
@@ -40,60 +40,63 @@ type ArgsConfig<Query extends Ref.AnyConfectPublicQuery, Model> = {
|
|
|
40
40
|
readonly args: (model: Model) => Option.Option<Ref.Args<Query>>;
|
|
41
41
|
});
|
|
42
42
|
/**
|
|
43
|
-
* A `dependenciesToStream` body for a hand-written subscription entry: runs
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
43
|
+
* A `dependenciesToStream` body for a hand-written subscription entry: runs the
|
|
44
|
+
* ref as a reactive query against the `Client` resource and maps every emission
|
|
45
|
+
* and every failure into a Message. Query failures are values, so the
|
|
46
|
+
* subscription remains live and can later emit a successful result.
|
|
47
47
|
*
|
|
48
|
-
* Prefer `reactiveQuery`, which builds the whole entry; reach for this when
|
|
49
|
-
*
|
|
48
|
+
* Prefer `reactiveQuery`, which builds the whole entry; reach for this when you
|
|
49
|
+
* need control over the entry's dependencies (custom gating, extra
|
|
50
50
|
* dependencies).
|
|
51
51
|
*/
|
|
52
52
|
export declare const reactiveQueryStream: <Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage>(ref: Query, handlers: Handlers<Query, SuccessMessage, ErrorMessage>) => (...args: Ref.OptionalArgs<Query>) => Stream.Stream<SuccessMessage | ErrorMessage, never, Client.Client>;
|
|
53
53
|
/**
|
|
54
54
|
* A complete Foldkit subscription entry for a Confect reactive query. The
|
|
55
|
-
* leading thunk fixes the `Model` type (TypeScript cannot partially infer
|
|
56
|
-
*
|
|
57
|
-
*
|
|
55
|
+
* leading thunk fixes the `Model` type (TypeScript cannot partially infer type
|
|
56
|
+
* arguments), so the `args` extractor's parameter is already typed. Pass the
|
|
57
|
+
* result as an entry value to `Subscription.make`:
|
|
58
58
|
*
|
|
59
59
|
* ```ts
|
|
60
|
-
* import * as Confect from "@confect/foldkit"
|
|
61
|
-
* import * as Subscription from "foldkit/subscription"
|
|
60
|
+
* import * as Confect from "@confect/foldkit";
|
|
61
|
+
* import * as Subscription from "foldkit/subscription";
|
|
62
62
|
*
|
|
63
63
|
* const subscriptions = Subscription.make<
|
|
64
64
|
* Model,
|
|
65
65
|
* Message,
|
|
66
66
|
* Confect.Client.Client
|
|
67
67
|
* >()(() => ({
|
|
68
|
-
* note: Confect.Subscription.reactiveQuery<Model>()(
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* })
|
|
68
|
+
* note: Confect.Subscription.reactiveQuery<Model>()(
|
|
69
|
+
* refs.public.notes.get,
|
|
70
|
+
* {
|
|
71
|
+
* args: (model) =>
|
|
72
|
+
* Option.map(model.noteId, (noteId) => ({ noteId })),
|
|
73
|
+
* onSuccess: (note) => SucceededGetNote({ note }),
|
|
74
|
+
* onError: (error) => FailedGetNote({ message: String(error) }),
|
|
75
|
+
* },
|
|
76
|
+
* ),
|
|
77
|
+
* }));
|
|
74
78
|
* ```
|
|
75
79
|
*
|
|
76
80
|
* The entry's dependencies are the query args wrapped in `Option`: `None`
|
|
77
|
-
* closes the subscription, a change from one `Some` to another unsubscribes
|
|
78
|
-
*
|
|
81
|
+
* closes the subscription, a change from one `Some` to another unsubscribes and
|
|
82
|
+
* resubscribes with the new args, and structurally equal args leave the
|
|
79
83
|
* subscription running (equivalence is derived from the ref's args schema).
|
|
80
84
|
* Queries without args may omit `args`, leaving the subscription always open.
|
|
81
85
|
*/
|
|
82
86
|
export declare const reactiveQuery: <Model>() => <Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage>(ref: Query, config: Handlers<Query, SuccessMessage, ErrorMessage> & ArgsConfig<Query, Model>) => FoldkitSubscription.EntryWithoutKeepAlive<Model, SuccessMessage | ErrorMessage, Dependencies<Query>, Client.Client>;
|
|
83
87
|
/**
|
|
84
88
|
* A complete Foldkit subscription entry that keeps exactly one live reactive
|
|
85
|
-
* page subscription in sync with a `PaginatedQuery` machine in the Model.
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
+
* page subscription in sync with a `PaginatedQuery` machine in the Model. The
|
|
90
|
+
* machine state is the single source of truth: navigation and split-pinning
|
|
91
|
+
* change the derived args, while `Idle` closes the subscription. Pagination ids
|
|
92
|
+
* are allocated here and installed by the first settlement.
|
|
89
93
|
*
|
|
90
|
-
* The leading thunk fixes the `Model` type (TypeScript cannot partially
|
|
91
|
-
*
|
|
92
|
-
* typed:
|
|
94
|
+
* The leading thunk fixes the `Model` type (TypeScript cannot partially infer
|
|
95
|
+
* type arguments), so the `state` extractor's parameter is already typed:
|
|
93
96
|
*
|
|
94
97
|
* ```ts
|
|
95
|
-
* import * as Confect from "@confect/foldkit"
|
|
96
|
-
* import * as Subscription from "foldkit/subscription"
|
|
98
|
+
* import * as Confect from "@confect/foldkit";
|
|
99
|
+
* import * as Subscription from "foldkit/subscription";
|
|
97
100
|
*
|
|
98
101
|
* const subscriptions = Subscription.make<
|
|
99
102
|
* Model,
|
|
@@ -104,13 +107,13 @@ export declare const reactiveQuery: <Model>() => <Query extends Ref.AnyConfectPu
|
|
|
104
107
|
* state: (model) => model.notes,
|
|
105
108
|
* onSettled: (settlement) => SettledGetNotesPage({ settlement }),
|
|
106
109
|
* }),
|
|
107
|
-
* }))
|
|
110
|
+
* }));
|
|
108
111
|
* ```
|
|
109
112
|
*
|
|
110
113
|
* Pass the settlement to `PaginatedQuery.settle` in `update`. The request
|
|
111
114
|
* identity is included in both success and failure Messages, so superseded
|
|
112
|
-
* outcomes cannot settle a newer page or pagination session. Query failures
|
|
113
|
-
*
|
|
115
|
+
* outcomes cannot settle a newer page or pagination session. Query failures do
|
|
116
|
+
* not close the Convex subscription; a later result can recover naturally.
|
|
114
117
|
*/
|
|
115
118
|
type DependenciesSchema<Dependencies_> = Schema.Schema<Dependencies_> & {
|
|
116
119
|
readonly fields: Schema.Struct.Fields;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Subscription.d.ts","sourceRoot":"","sources":["../src/Subscription.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,GAAG,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,KAAK,WAAW,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,mBAAmB,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,cAAc,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,MAAM,KAAK,CAAC,KAAK,SAAS,GAAG,CAAC,qBAAqB,IACrD,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAChB,MAAM,CAAC,oBAAoB,GAC3B,MAAM,CAAC,WAAW,CAAC;AAsBvB;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,KAAK,SAAS,GAAG,CAAC,qBAAqB;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ,CACvB,KAAK,SAAS,GAAG,CAAC,qBAAqB,EACvC,cAAc,EACd,YAAY;IAEZ,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,cAAc,CAAC;IACpE,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,YAAY,CAAC;CACzD;AAED;;;GAGG;AACH,KAAK,UAAU,CAAC,KAAK,SAAS,GAAG,CAAC,qBAAqB,EAAE,KAAK,IAAI;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;CAClE,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,KAAK,GACpC,OAAO,GACP;IACE,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;CACjE,CAAC,CAAC;AAEP;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAC7B,KAAK,SAAS,GAAG,CAAC,qBAAqB,EAAE,cAAc,EAAE,YAAY,OAC/D,KAAK,YACA,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,YAAY,CAAC,eAG9C,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,KAC/B,MAAM,CAAC,MAAM,CAAC,cAAc,GAAG,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAUjE,CAAC;AAEN
|
|
1
|
+
{"version":3,"file":"Subscription.d.ts","sourceRoot":"","sources":["../src/Subscription.ts"],"names":[],"mappings":"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"}
|
package/dist/Subscription.js
CHANGED
|
@@ -16,13 +16,13 @@ var Subscription_exports = /* @__PURE__ */ __exportAll({
|
|
|
16
16
|
});
|
|
17
17
|
const paginatedError = (error) => Match.value(error).pipe(Match.when(Schema.isSchemaError, (schemaError) => schemaError), Match.when(Match.instanceOf(WebSocketClientError), (clientError) => PaginationError.fromConvexQueryError(clientError.cause).pipe(Option.getOrElse(() => clientError))), Match.when(Match.any, (functionError) => PaginationError.fromConvexErrorData(functionError).pipe(Option.getOrElse(() => FunctionError({ error: functionError })))), Match.exhaustive);
|
|
18
18
|
/**
|
|
19
|
-
* A `dependenciesToStream` body for a hand-written subscription entry: runs
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* A `dependenciesToStream` body for a hand-written subscription entry: runs the
|
|
20
|
+
* ref as a reactive query against the `Client` resource and maps every emission
|
|
21
|
+
* and every failure into a Message. Query failures are values, so the
|
|
22
|
+
* subscription remains live and can later emit a successful result.
|
|
23
23
|
*
|
|
24
|
-
* Prefer `reactiveQuery`, which builds the whole entry; reach for this when
|
|
25
|
-
*
|
|
24
|
+
* Prefer `reactiveQuery`, which builds the whole entry; reach for this when you
|
|
25
|
+
* need control over the entry's dependencies (custom gating, extra
|
|
26
26
|
* dependencies).
|
|
27
27
|
*/
|
|
28
28
|
const reactiveQueryStream = (ref, handlers) => (...args) => Client.pipe(Effect.map((client) => client.reactiveQueryResult(ref, ...args)), Stream.unwrap, Stream.map(Result.match({
|
|
@@ -31,30 +31,34 @@ const reactiveQueryStream = (ref, handlers) => (...args) => Client.pipe(Effect.m
|
|
|
31
31
|
})));
|
|
32
32
|
/**
|
|
33
33
|
* A complete Foldkit subscription entry for a Confect reactive query. The
|
|
34
|
-
* leading thunk fixes the `Model` type (TypeScript cannot partially infer
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* leading thunk fixes the `Model` type (TypeScript cannot partially infer type
|
|
35
|
+
* arguments), so the `args` extractor's parameter is already typed. Pass the
|
|
36
|
+
* result as an entry value to `Subscription.make`:
|
|
37
37
|
*
|
|
38
38
|
* ```ts
|
|
39
|
-
* import * as Confect from "@confect/foldkit"
|
|
40
|
-
* import * as Subscription from "foldkit/subscription"
|
|
39
|
+
* import * as Confect from "@confect/foldkit";
|
|
40
|
+
* import * as Subscription from "foldkit/subscription";
|
|
41
41
|
*
|
|
42
42
|
* const subscriptions = Subscription.make<
|
|
43
43
|
* Model,
|
|
44
44
|
* Message,
|
|
45
45
|
* Confect.Client.Client
|
|
46
46
|
* >()(() => ({
|
|
47
|
-
* note: Confect.Subscription.reactiveQuery<Model>()(
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* })
|
|
47
|
+
* note: Confect.Subscription.reactiveQuery<Model>()(
|
|
48
|
+
* refs.public.notes.get,
|
|
49
|
+
* {
|
|
50
|
+
* args: (model) =>
|
|
51
|
+
* Option.map(model.noteId, (noteId) => ({ noteId })),
|
|
52
|
+
* onSuccess: (note) => SucceededGetNote({ note }),
|
|
53
|
+
* onError: (error) => FailedGetNote({ message: String(error) }),
|
|
54
|
+
* },
|
|
55
|
+
* ),
|
|
56
|
+
* }));
|
|
53
57
|
* ```
|
|
54
58
|
*
|
|
55
59
|
* The entry's dependencies are the query args wrapped in `Option`: `None`
|
|
56
|
-
* closes the subscription, a change from one `Some` to another unsubscribes
|
|
57
|
-
*
|
|
60
|
+
* closes the subscription, a change from one `Some` to another unsubscribes and
|
|
61
|
+
* resubscribes with the new args, and structurally equal args leave the
|
|
58
62
|
* subscription running (equivalence is derived from the ref's args schema).
|
|
59
63
|
* Queries without args may omit `args`, leaving the subscription always open.
|
|
60
64
|
*/
|