@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/CHANGELOG.md +76 -3
- package/dist/Command.d.ts +44 -40
- package/dist/Command.d.ts.map +1 -1
- package/dist/Command.js +20 -16
- package/dist/Command.js.map +1 -1
- package/dist/PaginatedQuery.d.ts +94 -30
- package/dist/PaginatedQuery.d.ts.map +1 -1
- package/dist/PaginatedQuery.js +72 -28
- package/dist/PaginatedQuery.js.map +1 -1
- package/dist/Subscription.d.ts +39 -37
- package/dist/Subscription.d.ts.map +1 -1
- package/dist/Subscription.js +23 -19
- package/dist/Subscription.js.map +1 -1
- package/package.json +11 -9
- package/src/Command.ts +44 -40
- package/src/PaginatedQuery.ts +107 -42
- package/src/Subscription.ts +39 -37
|
@@ -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/** Navigate to the next page, retaining the current page while it loads. */\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 Option.some({\n ...state,\n requestId: state.requestId + 1,\n current: {\n cursor: Option.getOrElse(\n data.descriptor.endCursor,\n () => data.continueCursor,\n ),\n endCursor: Option.none(),\n },\n prevStack: [...state.prevStack, data.descriptor],\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,17 +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
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* 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.
|
|
29
28
|
*/
|
|
30
29
|
export interface Handlers<Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage> {
|
|
31
30
|
readonly onSuccess: (returns: Ref.Returns<Query>) => SuccessMessage;
|
|
@@ -41,60 +40,63 @@ type ArgsConfig<Query extends Ref.AnyConfectPublicQuery, Model> = {
|
|
|
41
40
|
readonly args: (model: Model) => Option.Option<Ref.Args<Query>>;
|
|
42
41
|
});
|
|
43
42
|
/**
|
|
44
|
-
* A `dependenciesToStream` body for a hand-written subscription entry: runs
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
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.
|
|
48
47
|
*
|
|
49
|
-
* Prefer `reactiveQuery`, which builds the whole entry; reach for this when
|
|
50
|
-
*
|
|
48
|
+
* Prefer `reactiveQuery`, which builds the whole entry; reach for this when you
|
|
49
|
+
* need control over the entry's dependencies (custom gating, extra
|
|
51
50
|
* dependencies).
|
|
52
51
|
*/
|
|
53
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>;
|
|
54
53
|
/**
|
|
55
54
|
* A complete Foldkit subscription entry for a Confect reactive query. The
|
|
56
|
-
* leading thunk fixes the `Model` type (TypeScript cannot partially infer
|
|
57
|
-
*
|
|
58
|
-
*
|
|
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`:
|
|
59
58
|
*
|
|
60
59
|
* ```ts
|
|
61
|
-
* import * as Confect from "@confect/foldkit"
|
|
62
|
-
* import * as Subscription from "foldkit/subscription"
|
|
60
|
+
* import * as Confect from "@confect/foldkit";
|
|
61
|
+
* import * as Subscription from "foldkit/subscription";
|
|
63
62
|
*
|
|
64
63
|
* const subscriptions = Subscription.make<
|
|
65
64
|
* Model,
|
|
66
65
|
* Message,
|
|
67
66
|
* Confect.Client.Client
|
|
68
67
|
* >()(() => ({
|
|
69
|
-
* note: Confect.Subscription.reactiveQuery<Model>()(
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* })
|
|
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
|
+
* }));
|
|
75
78
|
* ```
|
|
76
79
|
*
|
|
77
80
|
* The entry's dependencies are the query args wrapped in `Option`: `None`
|
|
78
|
-
* closes the subscription, a change from one `Some` to another unsubscribes
|
|
79
|
-
*
|
|
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
|
|
80
83
|
* subscription running (equivalence is derived from the ref's args schema).
|
|
81
84
|
* Queries without args may omit `args`, leaving the subscription always open.
|
|
82
85
|
*/
|
|
83
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>;
|
|
84
87
|
/**
|
|
85
88
|
* A complete Foldkit subscription entry that keeps exactly one live reactive
|
|
86
|
-
* page subscription in sync with a `PaginatedQuery` machine in the Model.
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
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.
|
|
90
93
|
*
|
|
91
|
-
* The leading thunk fixes the `Model` type (TypeScript cannot partially
|
|
92
|
-
*
|
|
93
|
-
* 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:
|
|
94
96
|
*
|
|
95
97
|
* ```ts
|
|
96
|
-
* import * as Confect from "@confect/foldkit"
|
|
97
|
-
* import * as Subscription from "foldkit/subscription"
|
|
98
|
+
* import * as Confect from "@confect/foldkit";
|
|
99
|
+
* import * as Subscription from "foldkit/subscription";
|
|
98
100
|
*
|
|
99
101
|
* const subscriptions = Subscription.make<
|
|
100
102
|
* Model,
|
|
@@ -105,13 +107,13 @@ export declare const reactiveQuery: <Model>() => <Query extends Ref.AnyConfectPu
|
|
|
105
107
|
* state: (model) => model.notes,
|
|
106
108
|
* onSettled: (settlement) => SettledGetNotesPage({ settlement }),
|
|
107
109
|
* }),
|
|
108
|
-
* }))
|
|
110
|
+
* }));
|
|
109
111
|
* ```
|
|
110
112
|
*
|
|
111
113
|
* Pass the settlement to `PaginatedQuery.settle` in `update`. The request
|
|
112
114
|
* identity is included in both success and failure Messages, so superseded
|
|
113
|
-
* outcomes cannot settle a newer page or pagination session. Query failures
|
|
114
|
-
*
|
|
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.
|
|
115
117
|
*/
|
|
116
118
|
type DependenciesSchema<Dependencies_> = Schema.Schema<Dependencies_> & {
|
|
117
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
|
|
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
|
*/
|
package/dist/Subscription.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Subscription.js","names":["Client.WebSocketClientError","PaginatedQuery.FunctionError","PaginatedQuery.getSubscriptionRequest","Client.Client","PaginatedQuery.allocateRequest"],"sources":["../src/Subscription.ts"],"sourcesContent":["import * as PaginationError from \"@confect/core/PaginationError\";\nimport type * as Ref from \"@confect/core/Ref\";\nimport * as Effect from \"effect/Effect\";\nimport type * as Equivalence from \"effect/Equivalence\";\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 Stream from \"effect/Stream\";\nimport type * as FoldkitSubscription from \"foldkit/subscription\";\nimport * as PaginatedQuery from \"./PaginatedQuery\";\nimport * as Client from \"./Client\";\n\n/**\n * Everything a reactive query subscription against `Query` can fail with: the\n * ref's typed error (if it declares an `error` schema), a transport-level\n * `WebSocketClientError`, or a `SchemaError` from encoding args or decoding\n * returns.\n */\nexport type Error<Query extends Ref.AnyConfectPublicQuery> =\n | Ref.Error<Query>\n | Client.WebSocketClientError\n | Schema.SchemaError;\n\nconst paginatedError = <Query extends Ref.AnyConfectPublicPaginatedQuery>(\n error: Error<Query>,\n): PaginatedQuery.Error<Query> =>\n Match.value(error).pipe(\n Match.when(Schema.isSchemaError, (schemaError) => schemaError),\n Match.when(Match.instanceOf(Client.WebSocketClientError), (clientError) =>\n PaginationError.fromConvexQueryError(clientError.cause).pipe(\n Option.getOrElse(() => clientError),\n ),\n ),\n Match.when(Match.any, (functionError) =>\n PaginationError.fromConvexErrorData(functionError).pipe(\n Option.getOrElse(() =>\n PaginatedQuery.FunctionError({ error: functionError }),\n ),\n ),\n ),\n Match.exhaustive,\n ) as PaginatedQuery.Error<Query>;\n\n/**\n * The dependency record of a `reactiveQuery` entry. `None` means the\n * subscription is closed; a change from one `Some` to another tears the\n * server subscription down and reopens it with the new args.\n */\nexport interface Dependencies<Query extends Ref.AnyConfectPublicQuery> {\n readonly args: Option.Option<Ref.Args<Query>>;\n}\n\n/**\n * Maps a reactive query's emissions into the app's Messages. Every failure —\n * the ref's typed error, a transport error, or a codec error — arrives via\n * `onError`, so the resulting stream's error channel is `never`, as Foldkit\n * requires.\n */\nexport interface Handlers<\n Query extends Ref.AnyConfectPublicQuery,\n SuccessMessage,\n ErrorMessage,\n> {\n readonly onSuccess: (returns: Ref.Returns<Query>) => SuccessMessage;\n readonly onError: (error: Error<Query>) => ErrorMessage;\n}\n\n/**\n * The `args` extractor is required whenever the query declares args; queries\n * without args may omit it, in which case the subscription is always open.\n */\ntype ArgsConfig<Query extends Ref.AnyConfectPublicQuery, Model> = {\n readonly args?: (model: Model) => Option.Option<Ref.Args<Query>>;\n} & (keyof Ref.Args<Query> extends never\n ? unknown\n : {\n readonly args: (model: Model) => Option.Option<Ref.Args<Query>>;\n });\n\n/**\n * A `dependenciesToStream` body for a hand-written subscription entry: runs\n * the ref as a reactive query against the `Client` resource and maps\n * every emission and every failure into a Message. Query failures are values,\n * so the subscription remains live and can later emit a successful result.\n *\n * Prefer `reactiveQuery`, which builds the whole entry; reach for this when\n * you need control over the entry's dependencies (custom gating, extra\n * dependencies).\n */\nexport const reactiveQueryStream =\n <Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage>(\n ref: Query,\n handlers: Handlers<Query, SuccessMessage, ErrorMessage>,\n ) =>\n (\n ...args: Ref.OptionalArgs<Query>\n ): Stream.Stream<SuccessMessage | ErrorMessage, never, Client.Client> =>\n Client.Client.pipe(\n Effect.map((client) => client.reactiveQueryResult(ref, ...args)),\n Stream.unwrap,\n Stream.map(\n Result.match({\n onSuccess: handlers.onSuccess,\n onFailure: handlers.onError,\n }),\n ),\n );\n\n/**\n * A complete Foldkit subscription entry for a Confect reactive query. The\n * leading thunk fixes the `Model` type (TypeScript cannot partially infer\n * type arguments), so the `args` extractor's parameter is already typed.\n * Pass the result as an entry value to `Subscription.make`:\n *\n * ```ts\n * import * as Confect from \"@confect/foldkit\"\n * import * as Subscription from \"foldkit/subscription\"\n *\n * const subscriptions = Subscription.make<\n * Model,\n * Message,\n * Confect.Client.Client\n * >()(() => ({\n * note: Confect.Subscription.reactiveQuery<Model>()(refs.public.notes.get, {\n * args: (model) => Option.map(model.noteId, (noteId) => ({ noteId })),\n * onSuccess: (note) => SucceededGetNote({ note }),\n * onError: (error) => FailedGetNote({ message: String(error) }),\n * }),\n * }))\n * ```\n *\n * The entry's dependencies are the query args wrapped in `Option`: `None`\n * closes the subscription, a change from one `Some` to another unsubscribes\n * and resubscribes with the new args, and structurally equal args leave the\n * subscription running (equivalence is derived from the ref's args schema).\n * Queries without args may omit `args`, leaving the subscription always open.\n */\nexport const reactiveQuery =\n <Model>() =>\n <Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage>(\n ref: Query,\n config: Handlers<Query, SuccessMessage, ErrorMessage> &\n ArgsConfig<Query, Model>,\n ): FoldkitSubscription.EntryWithoutKeepAlive<\n Model,\n SuccessMessage | ErrorMessage,\n Dependencies<Query>,\n Client.Client\n > => {\n const modelToArgs = config.args;\n\n return {\n dependenciesSchema: Schema.Struct({\n args: Schema.Option(ref.args),\n }),\n modelToDependencies: (model) => ({\n args:\n modelToArgs === undefined\n ? Option.some({} as Ref.Args<Query>)\n : modelToArgs(model),\n }),\n dependenciesToStream: ({ args }) =>\n Option.match(args, {\n onNone: () => Stream.empty,\n onSome: (someArgs) => reactiveQueryStream(ref, config)(someArgs),\n }),\n };\n };\n\n/**\n * A complete Foldkit subscription entry that keeps exactly one live reactive\n * page subscription in sync with a `PaginatedQuery` machine in the Model.\n * The machine state is the single source of truth: navigation and\n * split-pinning change the derived args, while `Idle` closes the subscription.\n * Pagination ids are allocated here and installed by the first settlement.\n *\n * The leading thunk fixes the `Model` type (TypeScript cannot partially\n * infer type arguments), so the `state` extractor's parameter is already\n * typed:\n *\n * ```ts\n * import * as Confect from \"@confect/foldkit\"\n * import * as Subscription from \"foldkit/subscription\"\n *\n * const subscriptions = Subscription.make<\n * Model,\n * Message,\n * Confect.Client.Client\n * >()(() => ({\n * notesPage: Confect.Subscription.paginatedQuery<Model>()(Notes, {\n * state: (model) => model.notes,\n * onSettled: (settlement) => SettledGetNotesPage({ settlement }),\n * }),\n * }))\n * ```\n *\n * Pass the settlement to `PaginatedQuery.settle` in `update`. The request\n * identity is included in both success and failure Messages, so superseded\n * outcomes cannot settle a newer page or pagination session. Query failures\n * do not close the Convex subscription; a later result can recover naturally.\n */\ntype DependenciesSchema<Dependencies_> = Schema.Schema<Dependencies_> & {\n readonly fields: Schema.Struct.Fields;\n};\n\ntype EntryWithKeepAlive<Model, Message, Dependencies_, Services> = {\n readonly dependenciesSchema: DependenciesSchema<Dependencies_>;\n readonly modelToDependencies: (model: Model) => Dependencies_;\n readonly keepAliveEquivalence: Equivalence.Equivalence<Dependencies_>;\n readonly dependenciesToStream: (\n dependencies: Dependencies_,\n readDependencies: () => Dependencies_,\n ) => Stream.Stream<Message, never, Services>;\n};\n\nexport const paginatedQuery =\n <Model>() =>\n <\n PaginatedQueryRef extends Ref.AnyConfectPublicPaginatedQuery,\n SettledMessage,\n >(\n machine: PaginatedQuery.PaginatedQuery<PaginatedQueryRef>,\n config: {\n readonly state: (\n model: Model,\n ) => PaginatedQuery.State<\n PaginatedQuery.Item<PaginatedQueryRef>,\n PaginatedQuery.UserArgs<PaginatedQueryRef>,\n PaginatedQuery.Error<PaginatedQueryRef>\n >;\n readonly onSettled: (\n settlement: PaginatedQuery.Settlement<\n PaginatedQuery.Item<PaginatedQueryRef>,\n PaginatedQuery.UserArgs<PaginatedQueryRef>,\n PaginatedQuery.Error<PaginatedQueryRef>\n >,\n ) => SettledMessage;\n },\n ): EntryWithKeepAlive<\n Model,\n SettledMessage,\n {\n readonly request: Option.Option<\n PaginatedQuery.SubscriptionRequest<\n PaginatedQuery.UserArgs<PaginatedQueryRef>\n >\n >;\n },\n Client.Client\n > => {\n const ref = machine.ref;\n const composedArgsSchema = ref.args;\n const requestEquivalence = Schema.toEquivalence(\n machine.subscriptionRequestSchema,\n );\n const optionalRequestEquivalence = Option.makeEquivalence<\n PaginatedQuery.SubscriptionRequest<\n PaginatedQuery.UserArgs<PaginatedQueryRef>\n >\n >((left, right) =>\n requestEquivalence(\n { ...left, paginationId: Option.none() },\n { ...right, paginationId: Option.none() },\n ),\n );\n\n return {\n dependenciesSchema: Schema.Struct({\n request: Schema.Option(machine.subscriptionRequestSchema),\n }),\n modelToDependencies: (model) => ({\n request: Match.value(config.state(model)).pipe(\n Match.tag(\"Idle\", () => Option.none()),\n Match.tag(\"Active\", (state) =>\n Option.some(PaginatedQuery.getSubscriptionRequest(state)),\n ),\n Match.exhaustive,\n ),\n }),\n keepAliveEquivalence: (left, right) =>\n optionalRequestEquivalence(left.request, right.request),\n dependenciesToStream: ({\n request,\n }): Stream.Stream<SettledMessage, never, Client.Client> =>\n Option.match(request, {\n onNone: () => Stream.empty,\n onSome: (subscriptionRequest) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const client = yield* Client.Client;\n const paginationId = yield* client.resolvePaginationId(\n subscriptionRequest.paginationId,\n );\n const allocatedRequest = PaginatedQuery.allocateRequest(\n subscriptionRequest,\n paginationId,\n );\n const { descriptor, options } = allocatedRequest;\n const composedArgs = composedArgsSchema.make({\n ...allocatedRequest.args,\n paginationOpts: {\n numItems: options.initialNumItems,\n cursor: descriptor.cursor,\n id: paginationId,\n ...Match.value(options.maximumRowsRead).pipe(\n Match.when(undefined, () => ({})),\n Match.when(Match.defined, (maximumRowsRead) => ({\n maximumRowsRead,\n })),\n Match.exhaustive,\n ),\n ...Match.value(options.maximumBytesRead).pipe(\n Match.when(undefined, () => ({})),\n Match.when(Match.defined, (maximumBytesRead) => ({\n maximumBytesRead,\n })),\n Match.exhaustive,\n ),\n ...Option.match(descriptor.endCursor, {\n onNone: () => ({}),\n onSome: (endCursor) => ({ endCursor }),\n }),\n },\n });\n return client.reactiveQueryResult(ref, composedArgs).pipe(\n Stream.map((result) =>\n config.onSettled({\n request: allocatedRequest,\n result: Result.mapError(result, paginatedError),\n }),\n ),\n );\n }),\n ),\n }),\n };\n };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Subscription.js","names":["Client.WebSocketClientError","PaginatedQuery.FunctionError","PaginatedQuery.getSubscriptionRequest","Client.Client","PaginatedQuery.allocateRequest"],"sources":["../src/Subscription.ts"],"sourcesContent":["import * as PaginationError from \"@confect/core/PaginationError\";\nimport type * as Ref from \"@confect/core/Ref\";\nimport * as Effect from \"effect/Effect\";\nimport type * as Equivalence from \"effect/Equivalence\";\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 Stream from \"effect/Stream\";\nimport type * as FoldkitSubscription from \"foldkit/subscription\";\nimport * as PaginatedQuery from \"./PaginatedQuery\";\nimport * as Client from \"./Client\";\n\n/**\n * Everything a reactive query subscription against `Query` can fail with: the\n * ref's typed error (if it declares an `error` schema), a transport-level\n * `WebSocketClientError`, or a `SchemaError` from encoding args or decoding\n * returns.\n */\nexport type Error<Query extends Ref.AnyConfectPublicQuery> =\n | Ref.Error<Query>\n | Client.WebSocketClientError\n | Schema.SchemaError;\n\nconst paginatedError = <Query extends Ref.AnyConfectPublicPaginatedQuery>(\n error: Error<Query>,\n): PaginatedQuery.Error<Query> =>\n Match.value(error).pipe(\n Match.when(Schema.isSchemaError, (schemaError) => schemaError),\n Match.when(Match.instanceOf(Client.WebSocketClientError), (clientError) =>\n PaginationError.fromConvexQueryError(clientError.cause).pipe(\n Option.getOrElse(() => clientError),\n ),\n ),\n Match.when(Match.any, (functionError) =>\n PaginationError.fromConvexErrorData(functionError).pipe(\n Option.getOrElse(() =>\n PaginatedQuery.FunctionError({ error: functionError }),\n ),\n ),\n ),\n Match.exhaustive,\n ) as PaginatedQuery.Error<Query>;\n\n/**\n * The dependency record of a `reactiveQuery` entry. `None` means the\n * subscription is closed; a change from one `Some` to another tears the server\n * subscription down and reopens it with the new args.\n */\nexport interface Dependencies<Query extends Ref.AnyConfectPublicQuery> {\n readonly args: Option.Option<Ref.Args<Query>>;\n}\n\n/**\n * Maps a reactive query's emissions into the app's Messages. Every failure—the\n * ref's typed error, a transport error, or a codec error—arrives via `onError`,\n * so the resulting stream's error channel is `never`, as Foldkit requires.\n */\nexport interface Handlers<\n Query extends Ref.AnyConfectPublicQuery,\n SuccessMessage,\n ErrorMessage,\n> {\n readonly onSuccess: (returns: Ref.Returns<Query>) => SuccessMessage;\n readonly onError: (error: Error<Query>) => ErrorMessage;\n}\n\n/**\n * The `args` extractor is required whenever the query declares args; queries\n * without args may omit it, in which case the subscription is always open.\n */\ntype ArgsConfig<Query extends Ref.AnyConfectPublicQuery, Model> = {\n readonly args?: (model: Model) => Option.Option<Ref.Args<Query>>;\n} & (keyof Ref.Args<Query> extends never\n ? unknown\n : {\n readonly args: (model: Model) => Option.Option<Ref.Args<Query>>;\n });\n\n/**\n * A `dependenciesToStream` body for a hand-written subscription entry: runs the\n * ref as a reactive query against the `Client` resource and maps every emission\n * and every failure into a Message. Query failures are values, so the\n * subscription remains live and can later emit a successful result.\n *\n * Prefer `reactiveQuery`, which builds the whole entry; reach for this when you\n * need control over the entry's dependencies (custom gating, extra\n * dependencies).\n */\nexport const reactiveQueryStream =\n <Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage>(\n ref: Query,\n handlers: Handlers<Query, SuccessMessage, ErrorMessage>,\n ) =>\n (\n ...args: Ref.OptionalArgs<Query>\n ): Stream.Stream<SuccessMessage | ErrorMessage, never, Client.Client> =>\n Client.Client.pipe(\n Effect.map((client) => client.reactiveQueryResult(ref, ...args)),\n Stream.unwrap,\n Stream.map(\n Result.match({\n onSuccess: handlers.onSuccess,\n onFailure: handlers.onError,\n }),\n ),\n );\n\n/**\n * A complete Foldkit subscription entry for a Confect reactive query. The\n * leading thunk fixes the `Model` type (TypeScript cannot partially infer type\n * arguments), so the `args` extractor's parameter is already typed. Pass the\n * result as an entry value to `Subscription.make`:\n *\n * ```ts\n * import * as Confect from \"@confect/foldkit\";\n * import * as Subscription from \"foldkit/subscription\";\n *\n * const subscriptions = Subscription.make<\n * Model,\n * Message,\n * Confect.Client.Client\n * >()(() => ({\n * note: Confect.Subscription.reactiveQuery<Model>()(\n * refs.public.notes.get,\n * {\n * args: (model) =>\n * Option.map(model.noteId, (noteId) => ({ noteId })),\n * onSuccess: (note) => SucceededGetNote({ note }),\n * onError: (error) => FailedGetNote({ message: String(error) }),\n * },\n * ),\n * }));\n * ```\n *\n * The entry's dependencies are the query args wrapped in `Option`: `None`\n * closes the subscription, a change from one `Some` to another unsubscribes and\n * resubscribes with the new args, and structurally equal args leave the\n * subscription running (equivalence is derived from the ref's args schema).\n * Queries without args may omit `args`, leaving the subscription always open.\n */\nexport const reactiveQuery =\n <Model>() =>\n <Query extends Ref.AnyConfectPublicQuery, SuccessMessage, ErrorMessage>(\n ref: Query,\n config: Handlers<Query, SuccessMessage, ErrorMessage> &\n ArgsConfig<Query, Model>,\n ): FoldkitSubscription.EntryWithoutKeepAlive<\n Model,\n SuccessMessage | ErrorMessage,\n Dependencies<Query>,\n Client.Client\n > => {\n const modelToArgs = config.args;\n\n return {\n dependenciesSchema: Schema.Struct({\n args: Schema.Option(ref.args),\n }),\n modelToDependencies: (model) => ({\n args:\n modelToArgs === undefined\n ? Option.some({} as Ref.Args<Query>)\n : modelToArgs(model),\n }),\n dependenciesToStream: ({ args }) =>\n Option.match(args, {\n onNone: () => Stream.empty,\n onSome: (someArgs) => reactiveQueryStream(ref, config)(someArgs),\n }),\n };\n };\n\n/**\n * A complete Foldkit subscription entry that keeps exactly one live reactive\n * page subscription in sync with a `PaginatedQuery` machine in the Model. The\n * machine state is the single source of truth: navigation and split-pinning\n * change the derived args, while `Idle` closes the subscription. Pagination ids\n * are allocated here and installed by the first settlement.\n *\n * The leading thunk fixes the `Model` type (TypeScript cannot partially infer\n * type arguments), so the `state` extractor's parameter is already typed:\n *\n * ```ts\n * import * as Confect from \"@confect/foldkit\";\n * import * as Subscription from \"foldkit/subscription\";\n *\n * const subscriptions = Subscription.make<\n * Model,\n * Message,\n * Confect.Client.Client\n * >()(() => ({\n * notesPage: Confect.Subscription.paginatedQuery<Model>()(Notes, {\n * state: (model) => model.notes,\n * onSettled: (settlement) => SettledGetNotesPage({ settlement }),\n * }),\n * }));\n * ```\n *\n * Pass the settlement to `PaginatedQuery.settle` in `update`. The request\n * identity is included in both success and failure Messages, so superseded\n * outcomes cannot settle a newer page or pagination session. Query failures do\n * not close the Convex subscription; a later result can recover naturally.\n */\ntype DependenciesSchema<Dependencies_> = Schema.Schema<Dependencies_> & {\n readonly fields: Schema.Struct.Fields;\n};\n\ntype EntryWithKeepAlive<Model, Message, Dependencies_, Services> = {\n readonly dependenciesSchema: DependenciesSchema<Dependencies_>;\n readonly modelToDependencies: (model: Model) => Dependencies_;\n readonly keepAliveEquivalence: Equivalence.Equivalence<Dependencies_>;\n readonly dependenciesToStream: (\n dependencies: Dependencies_,\n readDependencies: () => Dependencies_,\n ) => Stream.Stream<Message, never, Services>;\n};\n\nexport const paginatedQuery =\n <Model>() =>\n <\n PaginatedQueryRef extends Ref.AnyConfectPublicPaginatedQuery,\n SettledMessage,\n >(\n machine: PaginatedQuery.PaginatedQuery<PaginatedQueryRef>,\n config: {\n readonly state: (\n model: Model,\n ) => PaginatedQuery.State<\n PaginatedQuery.Item<PaginatedQueryRef>,\n PaginatedQuery.UserArgs<PaginatedQueryRef>,\n PaginatedQuery.Error<PaginatedQueryRef>\n >;\n readonly onSettled: (\n settlement: PaginatedQuery.Settlement<\n PaginatedQuery.Item<PaginatedQueryRef>,\n PaginatedQuery.UserArgs<PaginatedQueryRef>,\n PaginatedQuery.Error<PaginatedQueryRef>\n >,\n ) => SettledMessage;\n },\n ): EntryWithKeepAlive<\n Model,\n SettledMessage,\n {\n readonly request: Option.Option<\n PaginatedQuery.SubscriptionRequest<\n PaginatedQuery.UserArgs<PaginatedQueryRef>\n >\n >;\n },\n Client.Client\n > => {\n const ref = machine.ref;\n const composedArgsSchema = ref.args;\n const requestEquivalence = Schema.toEquivalence(\n machine.subscriptionRequestSchema,\n );\n const optionalRequestEquivalence = Option.makeEquivalence<\n PaginatedQuery.SubscriptionRequest<\n PaginatedQuery.UserArgs<PaginatedQueryRef>\n >\n >((left, right) =>\n requestEquivalence(\n { ...left, paginationId: Option.none() },\n { ...right, paginationId: Option.none() },\n ),\n );\n\n return {\n dependenciesSchema: Schema.Struct({\n request: Schema.Option(machine.subscriptionRequestSchema),\n }),\n modelToDependencies: (model) => ({\n request: Match.value(config.state(model)).pipe(\n Match.tag(\"Idle\", () => Option.none()),\n Match.tag(\"Active\", (state) =>\n Option.some(PaginatedQuery.getSubscriptionRequest(state)),\n ),\n Match.exhaustive,\n ),\n }),\n keepAliveEquivalence: (left, right) =>\n optionalRequestEquivalence(left.request, right.request),\n dependenciesToStream: ({\n request,\n }): Stream.Stream<SettledMessage, never, Client.Client> =>\n Option.match(request, {\n onNone: () => Stream.empty,\n onSome: (subscriptionRequest) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const client = yield* Client.Client;\n const paginationId = yield* client.resolvePaginationId(\n subscriptionRequest.paginationId,\n );\n const allocatedRequest = PaginatedQuery.allocateRequest(\n subscriptionRequest,\n paginationId,\n );\n const { descriptor, options } = allocatedRequest;\n const composedArgs = composedArgsSchema.make({\n ...allocatedRequest.args,\n paginationOpts: {\n numItems: options.initialNumItems,\n cursor: descriptor.cursor,\n id: paginationId,\n ...Match.value(options.maximumRowsRead).pipe(\n Match.when(undefined, () => ({})),\n Match.when(Match.defined, (maximumRowsRead) => ({\n maximumRowsRead,\n })),\n Match.exhaustive,\n ),\n ...Match.value(options.maximumBytesRead).pipe(\n Match.when(undefined, () => ({})),\n Match.when(Match.defined, (maximumBytesRead) => ({\n maximumBytesRead,\n })),\n Match.exhaustive,\n ),\n ...Option.match(descriptor.endCursor, {\n onNone: () => ({}),\n onSome: (endCursor) => ({ endCursor }),\n }),\n },\n });\n return client.reactiveQueryResult(ref, composedArgs).pipe(\n Stream.map((result) =>\n config.onSettled({\n request: allocatedRequest,\n result: Result.mapError(result, paginatedError),\n }),\n ),\n );\n }),\n ),\n }),\n };\n };\n"],"mappings":";;;;;;;;;;;;;;;;AAwBA,MAAM,kBACJ,UAEA,MAAM,MAAM,KAAK,CAAC,CAAC,KACjB,MAAM,KAAK,OAAO,gBAAgB,gBAAgB,WAAW,GAC7D,MAAM,KAAK,MAAM,WAAWA,oBAA2B,IAAI,gBACzD,gBAAgB,qBAAqB,YAAY,KAAK,CAAC,CAAC,KACtD,OAAO,gBAAgB,WAAW,CACpC,CACF,GACA,MAAM,KAAK,MAAM,MAAM,kBACrB,gBAAgB,oBAAoB,aAAa,CAAC,CAAC,KACjD,OAAO,gBACLC,cAA6B,EAAE,OAAO,cAAc,CAAC,CACvD,CACF,CACF,GACA,MAAM,UACR;;;;;;;;;;;AA+CF,MAAa,uBAET,KACA,cAGA,GAAG,SAAA,OAEW,KACZ,OAAO,KAAK,WAAW,OAAO,oBAAoB,KAAK,GAAG,IAAI,CAAC,GAC/D,OAAO,QACP,OAAO,IACL,OAAO,MAAM;CACX,WAAW,SAAS;CACpB,WAAW,SAAS;AACtB,CAAC,CACH,CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCJ,MAAa,uBAGT,KACA,WAOG;CACH,MAAM,cAAc,OAAO;CAE3B,OAAO;EACL,oBAAoB,OAAO,OAAO,EAChC,MAAM,OAAO,OAAO,IAAI,IAAI,EAC9B,CAAC;EACD,sBAAsB,WAAW,EAC/B,MACE,gBAAgB,KAAA,IACZ,OAAO,KAAK,CAAC,CAAoB,IACjC,YAAY,KAAK,EACzB;EACA,uBAAuB,EAAE,WACvB,OAAO,MAAM,MAAM;GACjB,cAAc,OAAO;GACrB,SAAS,aAAa,oBAAoB,KAAK,MAAM,CAAC,CAAC,QAAQ;EACjE,CAAC;CACL;AACF;AA+CF,MAAa,wBAMT,SACA,WA2BG;CACH,MAAM,MAAM,QAAQ;CACpB,MAAM,qBAAqB,IAAI;CAC/B,MAAM,qBAAqB,OAAO,cAChC,QAAQ,yBACV;CACA,MAAM,6BAA6B,OAAO,iBAIvC,MAAM,UACP,mBACE;EAAE,GAAG;EAAM,cAAc,OAAO,KAAK;CAAE,GACvC;EAAE,GAAG;EAAO,cAAc,OAAO,KAAK;CAAE,CAC1C,CACF;CAEA,OAAO;EACL,oBAAoB,OAAO,OAAO,EAChC,SAAS,OAAO,OAAO,QAAQ,yBAAyB,EAC1D,CAAC;EACD,sBAAsB,WAAW,EAC/B,SAAS,MAAM,MAAM,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,KACxC,MAAM,IAAI,cAAc,OAAO,KAAK,CAAC,GACrC,MAAM,IAAI,WAAW,UACnB,OAAO,KAAKC,uBAAsC,KAAK,CAAC,CAC1D,GACA,MAAM,UACR,EACF;EACA,uBAAuB,MAAM,UAC3B,2BAA2B,KAAK,SAAS,MAAM,OAAO;EACxD,uBAAuB,EACrB,cAEA,OAAO,MAAM,SAAS;GACpB,cAAc,OAAO;GACrB,SAAS,wBACP,OAAO,OACL,OAAO,IAAI,aAAa;IACtB,MAAM,SAAS,OAAOC;IACtB,MAAM,eAAe,OAAO,OAAO,oBACjC,oBAAoB,YACtB;IACA,MAAM,mBAAmBC,gBACvB,qBACA,YACF;IACA,MAAM,EAAE,YAAY,YAAY;IAChC,MAAM,eAAe,mBAAmB,KAAK;KAC3C,GAAG,iBAAiB;KACpB,gBAAgB;MACd,UAAU,QAAQ;MAClB,QAAQ,WAAW;MACnB,IAAI;MACJ,GAAG,MAAM,MAAM,QAAQ,eAAe,CAAC,CAAC,KACtC,MAAM,KAAK,KAAA,UAAkB,CAAC,EAAE,GAChC,MAAM,KAAK,MAAM,UAAU,qBAAqB,EAC9C,gBACF,EAAE,GACF,MAAM,UACR;MACA,GAAG,MAAM,MAAM,QAAQ,gBAAgB,CAAC,CAAC,KACvC,MAAM,KAAK,KAAA,UAAkB,CAAC,EAAE,GAChC,MAAM,KAAK,MAAM,UAAU,sBAAsB,EAC/C,iBACF,EAAE,GACF,MAAM,UACR;MACA,GAAG,OAAO,MAAM,WAAW,WAAW;OACpC,eAAe,CAAC;OAChB,SAAS,eAAe,EAAE,UAAU;MACtC,CAAC;KACH;IACF,CAAC;IACD,OAAO,OAAO,oBAAoB,KAAK,YAAY,CAAC,CAAC,KACnD,OAAO,KAAK,WACV,OAAO,UAAU;KACf,SAAS;KACT,QAAQ,OAAO,SAAS,QAAQ,cAAc;IAChD,CAAC,CACH,CACF;GACF,CAAC,CACH;EACJ,CAAC;CACL;AACF"}
|
package/package.json
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@confect/foldkit",
|
|
3
3
|
"description": "Client-side bindings for Foldkit apps",
|
|
4
|
-
"version": "10.0.0-next.
|
|
4
|
+
"version": "10.0.0-next.23",
|
|
5
5
|
"author": "RJ Dellecese",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/rjdellecese/confect/issues"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@effect/vitest": "4.0.0-rc.
|
|
10
|
+
"@effect/vitest": "4.0.0-rc.115",
|
|
11
11
|
"@types/node": "24.13.3",
|
|
12
|
+
"confect-test-types": "0.0.0",
|
|
12
13
|
"convex": "1.45.0",
|
|
13
|
-
"effect": "4.0.0-rc.
|
|
14
|
+
"effect": "4.0.0-rc.115",
|
|
14
15
|
"foldkit": "0.148.1",
|
|
15
|
-
"tsdown": "0.
|
|
16
|
+
"tsdown": "0.23.0",
|
|
16
17
|
"typescript": "7.0.2",
|
|
17
18
|
"unrun": "0.3.1",
|
|
18
|
-
"vitest": "
|
|
19
|
+
"vitest": "5.0.0"
|
|
19
20
|
},
|
|
20
21
|
"engines": {
|
|
21
22
|
"node": ">=24"
|
|
@@ -50,9 +51,9 @@
|
|
|
50
51
|
"main": "./dist/index.js",
|
|
51
52
|
"module": "./dist/index.js",
|
|
52
53
|
"peerDependencies": {
|
|
53
|
-
"@confect/core": "^10.0.0-next.
|
|
54
|
-
"@confect/js": "^10.0.0-next.
|
|
55
|
-
"effect": "^4.0.0-rc.
|
|
54
|
+
"@confect/core": "^10.0.0-next.23",
|
|
55
|
+
"@confect/js": "^10.0.0-next.23",
|
|
56
|
+
"effect": "^4.0.0-rc.115",
|
|
56
57
|
"foldkit": "^0.148.0"
|
|
57
58
|
},
|
|
58
59
|
"repository": {
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
"clean": "shx rm -rf dist coverage node_modules",
|
|
67
68
|
"dev": "tsdown --watch --no-clean --config-loader unrun",
|
|
68
69
|
"test": "vitest run",
|
|
69
|
-
"typecheck": "tsc -b tsconfig.src.json"
|
|
70
|
+
"typecheck": "tsc -b tsconfig.src.json",
|
|
71
|
+
"typecheck:inexact": "tsc --noEmit --project tsconfig.json --exactOptionalPropertyTypes false"
|
|
70
72
|
}
|
|
71
73
|
}
|