@confect/react 9.2.5 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  # @confect/react
2
2
 
3
+ ## 9.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 16b5ad6: Add first-class paginated queries: declare one with `FunctionSpec.publicPaginatedQuery` (or `internalPaginatedQuery`) and read it with the new `usePaginatedQuery` hook from `@confect/react`.
8
+
9
+ Pass an `item` schema — the type of one element in a page — in place of `returns`, plus an optional `args` struct for your own arguments. The handler receives `paginationOpts` alongside them and forwards it to `paginate`.
10
+
11
+ ```ts
12
+ // confect/notes.spec.ts
13
+ FunctionSpec.publicPaginatedQuery({
14
+ name: "listByAuthor",
15
+ args: () => Schema.Struct({ author: Schema.String }),
16
+ item: () => notes.Doc,
17
+ });
18
+
19
+ // confect/notes.impl.ts
20
+ ({ author, paginationOpts }) =>
21
+ Effect.gen(function* () {
22
+ const reader = yield* DatabaseReader;
23
+
24
+ return yield* reader
25
+ .table("notes")
26
+ .index("by_creation_time", "desc")
27
+ .paginate(paginationOpts, (q) => q.eq(q.field("author"), author));
28
+ }).pipe(Effect.orDie);
29
+ ```
30
+
31
+ Declaring `paginationOpts` in `args` yourself is a type and runtime error.
32
+
33
+ ```tsx
34
+ import { PaginatedQueryResult, usePaginatedQuery } from "@confect/react";
35
+
36
+ const notes = usePaginatedQuery(
37
+ refs.public.notes.listByAuthor,
38
+ { author },
39
+ { initialNumItems: 10 },
40
+ );
41
+
42
+ // `notes.results` holds the pages decoded through `item`.
43
+ if (PaginatedQueryResult.isCanLoadMore(notes)) {
44
+ notes.loadMore(10);
45
+ }
46
+ ```
47
+
48
+ The hook returns a `PaginatedQueryResult<Item, E>`. `LoadingFirstPage`, `LoadingMore`, `CanLoadMore`, and `Exhausted` all carry `results` and `isLoading`; `loadMore` lives only on `CanLoadMore`, the one state it can make progress from. A declared `error` schema surfaces as a `Failure` variant carrying the decoded error instead of throwing during render, and `Failure` carries `results` too, so the pages loaded before it can still be rendered. Without an `error` schema, `Failure` is absent from the type entirely.
49
+
50
+ `paginate` in `@confect/server` now accepts Convex's full `PaginationOptions`, so a handler's `paginationOpts` passes straight through. `@confect/react` now requires `convex` >= 1.36.0.
51
+
3
52
  ## 9.2.5
4
53
 
5
54
  ## 9.2.4
@@ -0,0 +1,118 @@
1
+ import * as Pipeable from "effect/Pipeable";
2
+ declare const TypeId = "@confect/react/PaginatedQueryResult";
3
+ type TypeId = typeof TypeId;
4
+ /**
5
+ * A `PaginatedQueryResult` represents the result of a Confect paginated query.
6
+ * The non-`Failure` variants mirror the statuses of `usePaginatedQuery` from
7
+ * `convex/react` and all carry `results` and `isLoading`, so the common UI
8
+ * shape — render the list, show a spinner while loading — needs only an
9
+ * {@link isFailure} early-out and plain field access.
10
+ *
11
+ * Every variant carries `results`, including `Failure`: when a later page
12
+ * fails, the pages already loaded are still worth rendering alongside the
13
+ * error, so they are not discarded. `Failure` additionally carries the
14
+ * query's decoded typed error.
15
+ *
16
+ * `loadMore` appears only on `CanLoadMore`, the one state it can make
17
+ * progress from. The underlying Convex hook exposes it on every status, but
18
+ * calling it while a page is in flight, once the list is exhausted, or after
19
+ * a failure is an intentional no-op there; narrowing to `CanLoadMore` — via
20
+ * {@link isCanLoadMore} or {@link match} — makes that statically apparent
21
+ * instead of silently dropping the call.
22
+ *
23
+ * When the query declares no `error` schema (`E` is `never`), the `Failure`
24
+ * variant is excluded from the type entirely, so `isLoading` is accessible
25
+ * without any narrowing.
26
+ *
27
+ * @typeParam Item - The type of a decoded page item.
28
+ * @typeParam E - The type of the decoded typed error in the `Failure` variant.
29
+ */
30
+ export type PaginatedQueryResult<Item, E = never> = [E] extends [never] ? LoadingFirstPage<Item, E> | LoadingMore<Item, E> | CanLoadMore<Item, E> | Exhausted<Item, E> : LoadingFirstPage<Item, E> | LoadingMore<Item, E> | CanLoadMore<Item, E> | Exhausted<Item, E> | Failure<Item, E>;
31
+ /**
32
+ * Every variant regardless of `E` — the parameter type for guards and
33
+ * {@link match}, since `PaginatedQueryResult` itself excludes `Failure` when
34
+ * `E` is `never`.
35
+ */
36
+ export type Variants<Item, E = never> = LoadingFirstPage<Item, E> | LoadingMore<Item, E> | CanLoadMore<Item, E> | Exhausted<Item, E> | Failure<Item, E>;
37
+ export declare namespace PaginatedQueryResult {
38
+ interface Proto<Item, E> extends Pipeable.Pipeable {
39
+ readonly [TypeId]: {
40
+ readonly E: (_: never) => E;
41
+ readonly Item: (_: never) => Item;
42
+ };
43
+ }
44
+ type Item<R> = R extends Proto<infer Item_, infer _E> ? Item_ : never;
45
+ type Failure<R> = R extends Proto<infer _Item, infer E> ? E : never;
46
+ }
47
+ export interface LoadingFirstPage<Item, E = never> extends PaginatedQueryResult.Proto<Item, E> {
48
+ readonly _tag: "LoadingFirstPage";
49
+ readonly skipped: boolean;
50
+ readonly results: ReadonlyArray<Item>;
51
+ readonly isLoading: true;
52
+ }
53
+ export interface LoadingMore<Item, E = never> extends PaginatedQueryResult.Proto<Item, E> {
54
+ readonly _tag: "LoadingMore";
55
+ readonly results: ReadonlyArray<Item>;
56
+ readonly isLoading: true;
57
+ }
58
+ export interface CanLoadMore<Item, E = never> extends PaginatedQueryResult.Proto<Item, E> {
59
+ readonly _tag: "CanLoadMore";
60
+ readonly results: ReadonlyArray<Item>;
61
+ readonly isLoading: false;
62
+ readonly loadMore: (numItems: number) => void;
63
+ }
64
+ export interface Exhausted<Item, E = never> extends PaginatedQueryResult.Proto<Item, E> {
65
+ readonly _tag: "Exhausted";
66
+ readonly results: ReadonlyArray<Item>;
67
+ readonly isLoading: false;
68
+ }
69
+ export interface Failure<Item, E = never> extends PaginatedQueryResult.Proto<Item, E> {
70
+ readonly _tag: "Failure";
71
+ readonly error: E;
72
+ /** The pages loaded before the failure. */
73
+ readonly results: ReadonlyArray<Item>;
74
+ }
75
+ export declare const isPaginatedQueryResult: (u: unknown) => u is Variants<unknown, unknown>;
76
+ export declare const loadingFirstPage: <Item = never, E = never>(options: {
77
+ skipped: boolean;
78
+ }) => LoadingFirstPage<Item, E>;
79
+ export declare const loadingMore: <Item, E = never>(options: {
80
+ results: ReadonlyArray<Item>;
81
+ }) => LoadingMore<Item, E>;
82
+ export declare const canLoadMore: <Item, E = never>(options: {
83
+ results: ReadonlyArray<Item>;
84
+ loadMore: (numItems: number) => void;
85
+ }) => CanLoadMore<Item, E>;
86
+ export declare const exhausted: <Item, E = never>(options: {
87
+ results: ReadonlyArray<Item>;
88
+ }) => Exhausted<Item, E>;
89
+ export declare const failure: <E, Item = never>(options: {
90
+ error: E;
91
+ results: ReadonlyArray<Item>;
92
+ }) => Failure<Item, E>;
93
+ export declare const isLoadingFirstPage: <Item, E>(result: Variants<Item, E>) => result is LoadingFirstPage<Item, E>;
94
+ export declare const isLoadingMore: <Item, E>(result: Variants<Item, E>) => result is LoadingMore<Item, E>;
95
+ export declare const isCanLoadMore: <Item, E>(result: Variants<Item, E>) => result is CanLoadMore<Item, E>;
96
+ export declare const isExhausted: <Item, E>(result: Variants<Item, E>) => result is Exhausted<Item, E>;
97
+ export declare const isFailure: <Item, E>(result: Variants<Item, E>) => result is Failure<Item, E>;
98
+ export declare const isLoading: <Item, E>(result: Variants<Item, E>) => result is LoadingFirstPage<Item, E> | LoadingMore<Item, E>;
99
+ type MatchOptions<Item, E, V, W, X, Y, Z> = {
100
+ readonly onLoadingFirstPage: (skipped: boolean) => V;
101
+ readonly onLoadingMore: (results: ReadonlyArray<Item>) => W;
102
+ readonly onCanLoadMore: (results: ReadonlyArray<Item>, loadMore: (numItems: number) => void) => X;
103
+ readonly onExhausted: (results: ReadonlyArray<Item>) => Y;
104
+ } & ([E] extends [never] ? {} : {
105
+ readonly onFailure: (error: E, results: ReadonlyArray<Item>) => Z;
106
+ });
107
+ type MatchReturns<E, V, W, X, Y, Z> = [E] extends [never] ? V | W | X | Y : V | W | X | Y | Z;
108
+ /**
109
+ * Matches a {@link PaginatedQueryResult} to the appropriate handler based on
110
+ * its tag. If the provided result cannot fail (i.e. `E` is `never`),
111
+ * `onFailure` is not required.
112
+ */
113
+ export declare const match: {
114
+ <Item, E, V, W, X, Y, Z = never>(options: MatchOptions<Item, E, V, W, X, Y, Z>): (self: Variants<Item, E>) => MatchReturns<E, V, W, X, Y, Z>;
115
+ <Item, E, V, W, X, Y, Z = never>(self: Variants<Item, E>, options: MatchOptions<Item, E, V, W, X, Y, Z>): MatchReturns<E, V, W, X, Y, Z>;
116
+ };
117
+ export {};
118
+ //# sourceMappingURL=PaginatedQueryResult.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaginatedQueryResult.d.ts","sourceRoot":"","sources":["../src/PaginatedQueryResult.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ import * as Match from "effect/Match";
3
+ import * as Function from "effect/Function";
4
+ import { identity } from "effect/Function";
5
+ import * as Equal from "effect/Equal";
6
+ import * as Hash from "effect/Hash";
7
+ import * as Pipeable from "effect/Pipeable";
8
+ import * as Predicate from "effect/Predicate";
9
+ //#region src/PaginatedQueryResult.ts
10
+ var PaginatedQueryResult_exports = /* @__PURE__ */ __exportAll({
11
+ canLoadMore: () => canLoadMore,
12
+ exhausted: () => exhausted,
13
+ failure: () => failure,
14
+ isCanLoadMore: () => isCanLoadMore,
15
+ isExhausted: () => isExhausted,
16
+ isFailure: () => isFailure,
17
+ isLoading: () => isLoading,
18
+ isLoadingFirstPage: () => isLoadingFirstPage,
19
+ isLoadingMore: () => isLoadingMore,
20
+ isPaginatedQueryResult: () => isPaginatedQueryResult,
21
+ loadingFirstPage: () => loadingFirstPage,
22
+ loadingMore: () => loadingMore,
23
+ match: () => match
24
+ });
25
+ const TypeId = "@confect/react/PaginatedQueryResult";
26
+ const isPaginatedQueryResult = (u) => Predicate.hasProperty(u, TypeId);
27
+ const PaginatedQueryResultProto = {
28
+ [TypeId]: {
29
+ E: identity,
30
+ Item: identity
31
+ },
32
+ pipe(...args) {
33
+ return Pipeable.pipeArguments(this, args);
34
+ },
35
+ /**
36
+ * `CanLoadMore`'s `loadMore` is excluded from equality and hashing, like
37
+ * function fields generally: two results that render identically are equal
38
+ * even though their callbacks differ by identity.
39
+ */
40
+ [Equal.symbol](that) {
41
+ if (this._tag !== that._tag) return false;
42
+ return Match.value(this).pipe(Match.tag("LoadingFirstPage", (self) => self.skipped === that.skipped), Match.tag("LoadingMore", "CanLoadMore", "Exhausted", (self) => Equal.equals(self.results, that.results)), Match.tag("Failure", (self) => Equal.equals(self.error, that.error) && Equal.equals(self.results, that.results)), Match.exhaustive);
43
+ },
44
+ [Hash.symbol]() {
45
+ const tagHash = Hash.string(this._tag);
46
+ return Match.value(this).pipe(Match.tag("LoadingFirstPage", (self) => Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.skipped)))), Match.tag("LoadingMore", "CanLoadMore", "Exhausted", (self) => Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.results)))), Match.tag("Failure", (self) => Hash.cached(self, Hash.combine(tagHash)(Hash.combine(Hash.hash(self.error))(Hash.hash(self.results))))), Match.exhaustive);
47
+ }
48
+ };
49
+ const noResults = [];
50
+ const loadingFirstPage = (options) => Object.assign(Object.create(PaginatedQueryResultProto), {
51
+ _tag: "LoadingFirstPage",
52
+ skipped: options.skipped,
53
+ results: noResults,
54
+ isLoading: true
55
+ });
56
+ const loadingMore = (options) => Object.assign(Object.create(PaginatedQueryResultProto), {
57
+ _tag: "LoadingMore",
58
+ results: options.results,
59
+ isLoading: true
60
+ });
61
+ const canLoadMore = (options) => Object.assign(Object.create(PaginatedQueryResultProto), {
62
+ _tag: "CanLoadMore",
63
+ results: options.results,
64
+ isLoading: false,
65
+ loadMore: options.loadMore
66
+ });
67
+ const exhausted = (options) => Object.assign(Object.create(PaginatedQueryResultProto), {
68
+ _tag: "Exhausted",
69
+ results: options.results,
70
+ isLoading: false
71
+ });
72
+ const failure = (options) => Object.assign(Object.create(PaginatedQueryResultProto), {
73
+ _tag: "Failure",
74
+ error: options.error,
75
+ results: options.results
76
+ });
77
+ const isLoadingFirstPage = (result) => result._tag === "LoadingFirstPage";
78
+ const isLoadingMore = (result) => result._tag === "LoadingMore";
79
+ const isCanLoadMore = (result) => result._tag === "CanLoadMore";
80
+ const isExhausted = (result) => result._tag === "Exhausted";
81
+ const isFailure = (result) => result._tag === "Failure";
82
+ const isLoading = (result) => result._tag === "LoadingFirstPage" || result._tag === "LoadingMore";
83
+ /**
84
+ * Matches a {@link PaginatedQueryResult} to the appropriate handler based on
85
+ * its tag. If the provided result cannot fail (i.e. `E` is `never`),
86
+ * `onFailure` is not required.
87
+ */
88
+ const match = Function.dual(2, (self, options) => Match.value(self).pipe(Match.tag("LoadingFirstPage", (loadingFirstPage_) => options.onLoadingFirstPage(loadingFirstPage_.skipped)), Match.tag("LoadingMore", (loadingMore_) => options.onLoadingMore(loadingMore_.results)), Match.tag("CanLoadMore", (canLoadMore_) => options.onCanLoadMore(canLoadMore_.results, canLoadMore_.loadMore)), Match.tag("Exhausted", (exhausted_) => options.onExhausted(exhausted_.results)), Match.tag("Failure", (failure_) => {
89
+ if (Predicate.hasProperty(options, "onFailure")) return options.onFailure(failure_.error, failure_.results);
90
+ throw new Error("`onFailure` is required when error schema is provided");
91
+ }), Match.exhaustive));
92
+ //#endregion
93
+ export { PaginatedQueryResult_exports, canLoadMore, exhausted, failure, isCanLoadMore, isExhausted, isFailure, isLoading, isLoadingFirstPage, isLoadingMore, isPaginatedQueryResult, loadingFirstPage, loadingMore, match };
94
+
95
+ //# sourceMappingURL=PaginatedQueryResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaginatedQueryResult.js","names":[],"sources":["../src/PaginatedQueryResult.ts"],"sourcesContent":["import { identity } from \"effect/Function\";\nimport * as Equal from \"effect/Equal\";\nimport * as Function from \"effect/Function\";\nimport * as Hash from \"effect/Hash\";\nimport * as Match from \"effect/Match\";\nimport * as Pipeable from \"effect/Pipeable\";\nimport * as Predicate from \"effect/Predicate\";\n\nconst TypeId = \"@confect/react/PaginatedQueryResult\";\ntype TypeId = typeof TypeId;\n\n/**\n * A `PaginatedQueryResult` represents the result of a Confect paginated query.\n * The non-`Failure` variants mirror the statuses of `usePaginatedQuery` from\n * `convex/react` and all carry `results` and `isLoading`, so the common UI\n * shape — render the list, show a spinner while loading — needs only an\n * {@link isFailure} early-out and plain field access.\n *\n * Every variant carries `results`, including `Failure`: when a later page\n * fails, the pages already loaded are still worth rendering alongside the\n * error, so they are not discarded. `Failure` additionally carries the\n * query's decoded typed error.\n *\n * `loadMore` appears only on `CanLoadMore`, the one state it can make\n * progress from. The underlying Convex hook exposes it on every status, but\n * calling it while a page is in flight, once the list is exhausted, or after\n * a failure is an intentional no-op there; narrowing to `CanLoadMore` — via\n * {@link isCanLoadMore} or {@link match} — makes that statically apparent\n * instead of silently dropping the call.\n *\n * When the query declares no `error` schema (`E` is `never`), the `Failure`\n * variant is excluded from the type entirely, so `isLoading` is accessible\n * without any narrowing.\n *\n * @typeParam Item - The type of a decoded page item.\n * @typeParam E - The type of the decoded typed error in the `Failure` variant.\n */\nexport type PaginatedQueryResult<Item, E = never> = [E] extends [never]\n ?\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n :\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n | Failure<Item, E>;\n\n/**\n * Every variant regardless of `E` — the parameter type for guards and\n * {@link match}, since `PaginatedQueryResult` itself excludes `Failure` when\n * `E` is `never`.\n */\nexport type Variants<Item, E = never> =\n | LoadingFirstPage<Item, E>\n | LoadingMore<Item, E>\n | CanLoadMore<Item, E>\n | Exhausted<Item, E>\n | Failure<Item, E>;\n\nexport declare namespace PaginatedQueryResult {\n // eslint-disable-next-line @typescript-eslint/no-shadow, import/namespace -- oxlint's namespace resolution misses type-only exports, and `Pipeable` is an interface\n export interface Proto<Item, E> extends Pipeable.Pipeable {\n readonly [TypeId]: {\n readonly E: (_: never) => E;\n readonly Item: (_: never) => Item;\n };\n }\n\n export type Item<R> = R extends Proto<infer Item_, infer _E> ? Item_ : never;\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Failure<R> = R extends Proto<infer _Item, infer E> ? E : never;\n}\n\nexport interface LoadingFirstPage<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"LoadingFirstPage\";\n readonly skipped: boolean;\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: true;\n}\n\nexport interface LoadingMore<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"LoadingMore\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: true;\n}\n\nexport interface CanLoadMore<\n Item,\n E = never,\n> extends PaginatedQueryResult.Proto<Item, E> {\n readonly _tag: \"CanLoadMore\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: false;\n readonly loadMore: (numItems: number) => void;\n}\n\nexport interface Exhausted<Item, E = never> extends PaginatedQueryResult.Proto<\n Item,\n E\n> {\n readonly _tag: \"Exhausted\";\n readonly results: ReadonlyArray<Item>;\n readonly isLoading: false;\n}\n\nexport interface Failure<Item, E = never> extends PaginatedQueryResult.Proto<\n Item,\n E\n> {\n readonly _tag: \"Failure\";\n readonly error: E;\n /** The pages loaded before the failure. */\n readonly results: ReadonlyArray<Item>;\n}\n\nexport const isPaginatedQueryResult = (\n u: unknown,\n): u is Variants<unknown, unknown> => Predicate.hasProperty(u, TypeId);\n\nconst PaginatedQueryResultProto = {\n [TypeId]: {\n E: identity,\n Item: identity,\n },\n pipe(this: Variants<any, any>, ...args: ReadonlyArray<unknown>) {\n return Pipeable.pipeArguments(\n this,\n args as unknown as Parameters<typeof Pipeable.pipeArguments>[1],\n );\n },\n /**\n * `CanLoadMore`'s `loadMore` is excluded from equality and hashing, like\n * function fields generally: two results that render identically are equal\n * even though their callbacks differ by identity.\n */\n [Equal.symbol](this: Variants<any, any>, that: Variants<any, any>): boolean {\n if (this._tag !== that._tag) {\n return false;\n }\n return Match.value(this).pipe(\n Match.tag(\n \"LoadingFirstPage\",\n (self) => self.skipped === (that as LoadingFirstPage<any, any>).skipped,\n ),\n Match.tag(\"LoadingMore\", \"CanLoadMore\", \"Exhausted\", (self) =>\n Equal.equals(self.results, that.results),\n ),\n Match.tag(\n \"Failure\",\n (self) =>\n Equal.equals(self.error, (that as Failure<any, any>).error) &&\n Equal.equals(self.results, (that as Failure<any, any>).results),\n ),\n Match.exhaustive,\n );\n },\n [Hash.symbol](this: Variants<any, any>): number {\n const tagHash = Hash.string(this._tag);\n return Match.value(this).pipe(\n Match.tag(\"LoadingFirstPage\", (self) =>\n Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.skipped))),\n ),\n Match.tag(\"LoadingMore\", \"CanLoadMore\", \"Exhausted\", (self) =>\n Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.results))),\n ),\n Match.tag(\"Failure\", (self) =>\n Hash.cached(\n self,\n Hash.combine(tagHash)(\n Hash.combine(Hash.hash(self.error))(Hash.hash(self.results)),\n ),\n ),\n ),\n Match.exhaustive,\n );\n },\n};\n\nconst noResults: ReadonlyArray<never> = [];\n\nexport const loadingFirstPage = <Item = never, E = never>(options: {\n skipped: boolean;\n}): LoadingFirstPage<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"LoadingFirstPage\" as const,\n skipped: options.skipped,\n results: noResults,\n isLoading: true as const,\n });\n\nexport const loadingMore = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n}): LoadingMore<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"LoadingMore\" as const,\n results: options.results,\n isLoading: true as const,\n });\n\nexport const canLoadMore = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n loadMore: (numItems: number) => void;\n}): CanLoadMore<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"CanLoadMore\" as const,\n results: options.results,\n isLoading: false as const,\n loadMore: options.loadMore,\n });\n\nexport const exhausted = <Item, E = never>(options: {\n results: ReadonlyArray<Item>;\n}): Exhausted<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"Exhausted\" as const,\n results: options.results,\n isLoading: false as const,\n });\n\nexport const failure = <E, Item = never>(options: {\n error: E;\n results: ReadonlyArray<Item>;\n}): Failure<Item, E> =>\n Object.assign(Object.create(PaginatedQueryResultProto), {\n _tag: \"Failure\" as const,\n error: options.error,\n results: options.results,\n });\n\nexport const isLoadingFirstPage = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingFirstPage<Item, E> => result._tag === \"LoadingFirstPage\";\n\nexport const isLoadingMore = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingMore<Item, E> => result._tag === \"LoadingMore\";\n\nexport const isCanLoadMore = <Item, E>(\n result: Variants<Item, E>,\n): result is CanLoadMore<Item, E> => result._tag === \"CanLoadMore\";\n\nexport const isExhausted = <Item, E>(\n result: Variants<Item, E>,\n): result is Exhausted<Item, E> => result._tag === \"Exhausted\";\n\nexport const isFailure = <Item, E>(\n result: Variants<Item, E>,\n): result is Failure<Item, E> => result._tag === \"Failure\";\n\nexport const isLoading = <Item, E>(\n result: Variants<Item, E>,\n): result is LoadingFirstPage<Item, E> | LoadingMore<Item, E> =>\n result._tag === \"LoadingFirstPage\" || result._tag === \"LoadingMore\";\n\ntype MatchOptions<Item, E, V, W, X, Y, Z> = {\n readonly onLoadingFirstPage: (skipped: boolean) => V;\n readonly onLoadingMore: (results: ReadonlyArray<Item>) => W;\n readonly onCanLoadMore: (\n results: ReadonlyArray<Item>,\n loadMore: (numItems: number) => void,\n ) => X;\n readonly onExhausted: (results: ReadonlyArray<Item>) => Y;\n} & ([E] extends [never]\n ? {}\n : {\n readonly onFailure: (error: E, results: ReadonlyArray<Item>) => Z;\n });\n\ntype MatchReturns<E, V, W, X, Y, Z> = [E] extends [never]\n ? V | W | X | Y\n : V | W | X | Y | Z;\n\n/**\n * Matches a {@link PaginatedQueryResult} to the appropriate handler based on\n * its tag. If the provided result cannot fail (i.e. `E` is `never`),\n * `onFailure` is not required.\n */\nexport const match: {\n <Item, E, V, W, X, Y, Z = never>(\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): (self: Variants<Item, E>) => MatchReturns<E, V, W, X, Y, Z>;\n <Item, E, V, W, X, Y, Z = never>(\n self: Variants<Item, E>,\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): MatchReturns<E, V, W, X, Y, Z>;\n} = Function.dual(\n 2,\n <Item, E, V, W, X, Y, Z = never>(\n self: Variants<Item, E>,\n options: MatchOptions<Item, E, V, W, X, Y, Z>,\n ): MatchReturns<E, V, W, X, Y, Z> =>\n Match.value(self).pipe(\n Match.tag(\"LoadingFirstPage\", (loadingFirstPage_) =>\n options.onLoadingFirstPage(loadingFirstPage_.skipped),\n ),\n Match.tag(\"LoadingMore\", (loadingMore_) =>\n options.onLoadingMore(loadingMore_.results),\n ),\n Match.tag(\"CanLoadMore\", (canLoadMore_) =>\n options.onCanLoadMore(canLoadMore_.results, canLoadMore_.loadMore),\n ),\n Match.tag(\"Exhausted\", (exhausted_) =>\n options.onExhausted(exhausted_.results),\n ),\n Match.tag(\"Failure\", (failure_) => {\n if (Predicate.hasProperty(options, \"onFailure\")) {\n return options.onFailure(failure_.error, failure_.results);\n }\n throw new Error(\n \"`onFailure` is required when error schema is provided\",\n );\n }),\n Match.exhaustive,\n ) as MatchReturns<E, V, W, X, Y, Z>,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAQA,MAAM,SAAS;AAqHf,MAAa,0BACX,MACoC,UAAU,YAAY,GAAG,MAAM;AAErE,MAAM,4BAA4B;EAC/B,SAAS;EACR,GAAG;EACH,MAAM;CACR;CACA,KAA+B,GAAG,MAA8B;EAC9D,OAAO,SAAS,cACd,MACA,IACF;CACF;;;;;;CAMA,CAAC,MAAM,QAAkC,MAAmC;EAC1E,IAAI,KAAK,SAAS,KAAK,MACrB,OAAO;EAET,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KACvB,MAAM,IACJ,qBACC,SAAS,KAAK,YAAa,KAAoC,OAClE,GACA,MAAM,IAAI,eAAe,eAAe,cAAc,SACpD,MAAM,OAAO,KAAK,SAAS,KAAK,OAAO,CACzC,GACA,MAAM,IACJ,YACC,SACC,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK,KAC1D,MAAM,OAAO,KAAK,SAAU,KAA2B,OAAO,CAClE,GACA,MAAM,UACR;CACF;CACA,CAAC,KAAK,UAA0C;EAC9C,MAAM,UAAU,KAAK,OAAO,KAAK,IAAI;EACrC,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KACvB,MAAM,IAAI,qBAAqB,SAC7B,KAAK,OAAO,MAAM,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,CAAC,CAAC,CAClE,GACA,MAAM,IAAI,eAAe,eAAe,cAAc,SACpD,KAAK,OAAO,MAAM,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,CAAC,CAAC,CAClE,GACA,MAAM,IAAI,YAAY,SACpB,KAAK,OACH,MACA,KAAK,QAAQ,OAAO,CAAC,CACnB,KAAK,QAAQ,KAAK,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,CAAC,CAC7D,CACF,CACF,GACA,MAAM,UACR;CACF;AACF;AAEA,MAAM,YAAkC,CAAC;AAEzC,MAAa,oBAA6C,YAGxD,OAAO,OAAO,OAAO,OAAO,yBAAyB,GAAG;CACtD,MAAM;CACN,SAAS,QAAQ;CACjB,SAAS;CACT,WAAW;AACb,CAAC;AAEH,MAAa,eAAgC,YAG3C,OAAO,OAAO,OAAO,OAAO,yBAAyB,GAAG;CACtD,MAAM;CACN,SAAS,QAAQ;CACjB,WAAW;AACb,CAAC;AAEH,MAAa,eAAgC,YAI3C,OAAO,OAAO,OAAO,OAAO,yBAAyB,GAAG;CACtD,MAAM;CACN,SAAS,QAAQ;CACjB,WAAW;CACX,UAAU,QAAQ;AACpB,CAAC;AAEH,MAAa,aAA8B,YAGzC,OAAO,OAAO,OAAO,OAAO,yBAAyB,GAAG;CACtD,MAAM;CACN,SAAS,QAAQ;CACjB,WAAW;AACb,CAAC;AAEH,MAAa,WAA4B,YAIvC,OAAO,OAAO,OAAO,OAAO,yBAAyB,GAAG;CACtD,MAAM;CACN,OAAO,QAAQ;CACf,SAAS,QAAQ;AACnB,CAAC;AAEH,MAAa,sBACX,WACwC,OAAO,SAAS;AAE1D,MAAa,iBACX,WACmC,OAAO,SAAS;AAErD,MAAa,iBACX,WACmC,OAAO,SAAS;AAErD,MAAa,eACX,WACiC,OAAO,SAAS;AAEnD,MAAa,aACX,WAC+B,OAAO,SAAS;AAEjD,MAAa,aACX,WAEA,OAAO,SAAS,sBAAsB,OAAO,SAAS;;;;;;AAyBxD,MAAa,QAQT,SAAS,KACX,IAEE,MACA,YAEA,MAAM,MAAM,IAAI,CAAC,CAAC,KAChB,MAAM,IAAI,qBAAqB,sBAC7B,QAAQ,mBAAmB,kBAAkB,OAAO,CACtD,GACA,MAAM,IAAI,gBAAgB,iBACxB,QAAQ,cAAc,aAAa,OAAO,CAC5C,GACA,MAAM,IAAI,gBAAgB,iBACxB,QAAQ,cAAc,aAAa,SAAS,aAAa,QAAQ,CACnE,GACA,MAAM,IAAI,cAAc,eACtB,QAAQ,YAAY,WAAW,OAAO,CACxC,GACA,MAAM,IAAI,YAAY,aAAa;CACjC,IAAI,UAAU,YAAY,SAAS,WAAW,GAC5C,OAAO,QAAQ,UAAU,SAAS,OAAO,SAAS,OAAO;CAE3D,MAAM,IAAI,MACR,uDACF;AACF,CAAC,GACD,MAAM,UACR,CACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"QueryResult.d.ts","sourceRoot":"","sources":["../src/QueryResult.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QueryResult.d.ts","sourceRoot":"","sources":["../src/QueryResult.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAG5C,QAAA,MAAM,MAAM,+BAA+B,CAAC;AAC5C,KAAK,MAAM,GAAG,OAAO,MAAM,CAAC;AAE5B;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,IAChC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,GACb,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,GACb,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAElB,MAAM,CAAC,OAAO,WAAW,WAAW,CAAC;IAEnC,UAAiB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,QAAQ,CAAC,QAAQ;QACpD,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE;YACjB,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;YAC5B,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;SAC7B,CAAC;KACH;IAGD,KAAY,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAG9E,KAAY,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,WAAW,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;CAC/E;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAE,SAAQ,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;IACpE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAE,SAAQ,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;IACpE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAE,SAAQ,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;IACpE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED,eAAO,MAAM,aAAa,GAAI,GAAG,OAAO,KAAG,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,OAAO,CAC1C,CAAC;AAmDnC,eAAO,MAAM,IAAI,GAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,SAAS,OAAO,KAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAItE,CAAC;AAEL,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,KAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAIzD,CAAC;AAEL,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,KAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAItD,CAAC;AAEL,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAC5B,aAAa,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,KAC7B,WAAW,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAmC,CAAC;AAElE,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAC5B,aAAa,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,KAC7B,WAAW,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAmC,CAAC;AAElE,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAC5B,aAAa,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,KAC7B,WAAW,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAmC,CAAC;AAElE,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI;IACjC,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,CAAC,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;CACrC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAA;CAAE,CAAC,CAAC;AAEzE,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAExE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK,EAAE;IAClB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,EACpB,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GACnC,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,EACpB,IAAI,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,EACvB,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GACnC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAoB7B,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ import * as Match from "effect/Match";
2
3
  import * as Function from "effect/Function";
3
4
  import { identity } from "effect/Function";
4
5
  import * as Equal from "effect/Equal";
@@ -28,19 +29,11 @@ const QueryResultProto = {
28
29
  },
29
30
  [Equal.symbol](that) {
30
31
  if (this._tag !== that._tag) return false;
31
- switch (this._tag) {
32
- case "Loading": return this.skipped === that.skipped;
33
- case "Success": return Equal.equals(this.value, that.value);
34
- case "Failure": return Equal.equals(this.error, that.error);
35
- }
32
+ return Match.value(this).pipe(Match.tag("Loading", (self) => self.skipped === that.skipped), Match.tag("Success", (self) => Equal.equals(self.value, that.value)), Match.tag("Failure", (self) => Equal.equals(self.error, that.error)), Match.exhaustive);
36
33
  },
37
34
  [Hash.symbol]() {
38
35
  const tagHash = Hash.string(this._tag);
39
- switch (this._tag) {
40
- case "Loading": return Hash.cached(this, Hash.combine(tagHash)(Hash.hash(this.skipped)));
41
- case "Success": return Hash.cached(this, Hash.combine(tagHash)(Hash.hash(this.value)));
42
- case "Failure": return Hash.cached(this, Hash.combine(tagHash)(Hash.hash(this.error)));
43
- }
36
+ return Match.value(this).pipe(Match.tag("Loading", (self) => Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.skipped)))), Match.tag("Success", (self) => Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.value)))), Match.tag("Failure", (self) => Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.error)))), Match.exhaustive);
44
37
  }
45
38
  };
46
39
  const load = (skipped) => Object.assign(Object.create(QueryResultProto), {
@@ -71,15 +64,10 @@ const isFailure = (queryResult) => queryResult._tag === "Failure";
71
64
  * onFailure: (error) => <p>Error: {error.message}</p>,
72
65
  * });
73
66
  */
74
- const match = Function.dual(2, (self, options) => {
75
- switch (self._tag) {
76
- case "Loading": return options.onLoading(self.skipped);
77
- case "Success": return options.onSuccess(self.value);
78
- case "Failure":
79
- if (Predicate.hasProperty(options, "onFailure")) return options.onFailure(self.error);
80
- throw new Error("`onFailure` is required when error schema is provided");
81
- }
82
- });
67
+ const match = Function.dual(2, (self, options) => Match.value(self).pipe(Match.tag("Loading", (loading) => options.onLoading(loading.skipped)), Match.tag("Success", (success) => options.onSuccess(success.value)), Match.tag("Failure", (failure) => {
68
+ if (Predicate.hasProperty(options, "onFailure")) return options.onFailure(failure.error);
69
+ throw new Error("`onFailure` is required when error schema is provided");
70
+ }), Match.exhaustive));
83
71
  //#endregion
84
72
  export { QueryResult_exports, fail, isFailure, isLoading, isQueryResult, isSuccess, load, match, succeed };
85
73
 
@@ -1 +1 @@
1
- {"version":3,"file":"QueryResult.js","names":[],"sources":["../src/QueryResult.ts"],"sourcesContent":["import { identity } from \"effect/Function\";\nimport * as Equal from \"effect/Equal\";\nimport * as Function from \"effect/Function\";\nimport * as Hash from \"effect/Hash\";\nimport * as Pipeable from \"effect/Pipeable\";\nimport * as Predicate from \"effect/Predicate\";\n\nconst TypeId = \"@confect/react/QueryResult\";\ntype TypeId = typeof TypeId;\n\n/**\n * A `QueryResult` represents the result of a Confect query.\n *\n * @typeParam A - The type of the decoded `returns` value in the `Success` variant.\n * @typeParam E - The type of the decoded typed error in the `Failure` variant.\n */\nexport type QueryResult<A, E = never> =\n | Loading<A, E>\n | Success<A, E>\n | Failure<A, E>;\n\nexport declare namespace QueryResult {\n export interface Proto<A, E> extends Pipeable.Pipeable {\n readonly [TypeId]: {\n readonly E: (_: never) => E;\n readonly A: (_: never) => A;\n };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Success<R> = R extends QueryResult<infer A, infer _E> ? A : never;\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Failure<R> = R extends QueryResult<infer _A, infer E> ? E : never;\n}\n\nexport interface Loading<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Loading\";\n readonly skipped: boolean;\n}\n\nexport interface Success<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Success\";\n readonly value: A;\n}\n\nexport interface Failure<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Failure\";\n readonly error: E;\n}\n\nexport const isQueryResult = (u: unknown): u is QueryResult<unknown, unknown> =>\n Predicate.hasProperty(u, TypeId);\n\nconst QueryResultProto = {\n [TypeId]: {\n E: identity,\n A: identity,\n },\n pipe(this: QueryResult<any, any>, ...args: ReadonlyArray<unknown>) {\n return Pipeable.pipeArguments(\n this,\n args as unknown as Parameters<typeof Pipeable.pipeArguments>[1],\n );\n },\n [Equal.symbol](\n this: QueryResult<any, any>,\n that: QueryResult<any, any>,\n ): boolean {\n if (this._tag !== that._tag) {\n return false;\n }\n switch (this._tag) {\n case \"Loading\":\n return this.skipped === (that as Loading<any, any>).skipped;\n case \"Success\":\n return Equal.equals(this.value, (that as Success<any, any>).value);\n case \"Failure\":\n return Equal.equals(this.error, (that as Failure<any, any>).error);\n }\n },\n [Hash.symbol](this: QueryResult<any, any>): number {\n const tagHash = Hash.string(this._tag);\n switch (this._tag) {\n case \"Loading\":\n return Hash.cached(\n this,\n Hash.combine(tagHash)(Hash.hash(this.skipped)),\n );\n case \"Success\":\n return Hash.cached(this, Hash.combine(tagHash)(Hash.hash(this.value)));\n case \"Failure\":\n return Hash.cached(this, Hash.combine(tagHash)(Hash.hash(this.error)));\n }\n },\n};\n\nexport const load = <A = never, E = never>(skipped: boolean): Loading<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Loading\" as const,\n skipped,\n });\n\nexport const succeed = <A, E = never>(value: A): Success<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Success\" as const,\n value,\n });\n\nexport const fail = <E, A = never>(error: E): Failure<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Failure\" as const,\n error,\n });\n\nexport const isLoading = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Loading<A, E> => queryResult._tag === \"Loading\";\n\nexport const isSuccess = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Success<A, E> => queryResult._tag === \"Success\";\n\nexport const isFailure = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Failure<A, E> => queryResult._tag === \"Failure\";\n\ntype MatchOptions<A, E, X, Y, Z> = {\n readonly onLoading: (skipped: boolean) => X;\n readonly onSuccess: (value: A) => Y;\n} & ([E] extends [never] ? {} : { readonly onFailure: (error: E) => Z });\n\ntype MatchReturns<E, X, Y, Z> = [E] extends [never] ? X | Y : X | Y | Z;\n\n/**\n * Matches a {@link QueryResult} to the appropriate handler based on its tag. If\n * the provided `QueryResult` cannot fail (i.e. `E` is `never`), `onFailure` is\n * not required.\n *\n * @example\n * ```tsx\n * const result = QueryResult.match(queryResult, {\n * onLoading: (skipped) => skipped ? null : <p>Loading…</p>,\n * onSuccess: (value) => <p>{value.text}</p>,\n * onFailure: (error) => <p>Error: {error.message}</p>,\n * });\n */\nexport const match: {\n <A, E, X, Y, Z = never>(\n options: MatchOptions<A, E, X, Y, Z>,\n ): (self: QueryResult<A, E>) => MatchReturns<E, X, Y, Z>;\n <A, E, X, Y, Z = never>(\n self: QueryResult<A, E>,\n options: MatchOptions<A, E, X, Y, Z>,\n ): MatchReturns<E, X, Y, Z>;\n} = Function.dual(\n 2,\n <A, E, X, Y, Z = never>(\n self: QueryResult<A, E>,\n options: MatchOptions<A, E, X, Y, Z>,\n ): MatchReturns<E, X, Y, Z> => {\n switch (self._tag) {\n case \"Loading\":\n return options.onLoading(self.skipped);\n case \"Success\":\n return options.onSuccess(self.value);\n case \"Failure\": {\n if (Predicate.hasProperty(options, \"onFailure\")) {\n return options.onFailure(self.error) as MatchReturns<E, X, Y, Z>;\n }\n throw new Error(\n \"`onFailure` is required when error schema is provided\",\n );\n }\n }\n },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAOA,MAAM,SAAS;AA4Cf,MAAa,iBAAiB,MAC5B,UAAU,YAAY,GAAG,MAAM;AAEjC,MAAM,mBAAmB;EACtB,SAAS;EACR,GAAG;EACH,GAAG;CACL;CACA,KAAkC,GAAG,MAA8B;EACjE,OAAO,SAAS,cACd,MACA,IACF;CACF;CACA,CAAC,MAAM,QAEL,MACS;EACT,IAAI,KAAK,SAAS,KAAK,MACrB,OAAO;EAET,QAAQ,KAAK,MAAb;GACE,KAAK,WACH,OAAO,KAAK,YAAa,KAA2B;GACtD,KAAK,WACH,OAAO,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK;GACnE,KAAK,WACH,OAAO,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK;EACrE;CACF;CACA,CAAC,KAAK,UAA6C;EACjD,MAAM,UAAU,KAAK,OAAO,KAAK,IAAI;EACrC,QAAQ,KAAK,MAAb;GACE,KAAK,WACH,OAAO,KAAK,OACV,MACA,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,CAAC,CAC/C;GACF,KAAK,WACH,OAAO,KAAK,OAAO,MAAM,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAAC;GACvE,KAAK,WACH,OAAO,KAAK,OAAO,MAAM,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAAC;EACzE;CACF;AACF;AAEA,MAAa,QAA8B,YACzC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,WAAyB,UACpC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,QAAsB,UACjC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,aACX,gBACiC,YAAY,SAAS;AAExD,MAAa,aACX,gBACiC,YAAY,SAAS;AAExD,MAAa,aACX,gBACiC,YAAY,SAAS;;;;;;;;;;;;;;AAsBxD,MAAa,QAQT,SAAS,KACX,IAEE,MACA,YAC6B;CAC7B,QAAQ,KAAK,MAAb;EACE,KAAK,WACH,OAAO,QAAQ,UAAU,KAAK,OAAO;EACvC,KAAK,WACH,OAAO,QAAQ,UAAU,KAAK,KAAK;EACrC,KAAK;GACH,IAAI,UAAU,YAAY,SAAS,WAAW,GAC5C,OAAO,QAAQ,UAAU,KAAK,KAAK;GAErC,MAAM,IAAI,MACR,uDACF;CAEJ;AACF,CACF"}
1
+ {"version":3,"file":"QueryResult.js","names":[],"sources":["../src/QueryResult.ts"],"sourcesContent":["import { identity } from \"effect/Function\";\nimport * as Equal from \"effect/Equal\";\nimport * as Function from \"effect/Function\";\nimport * as Hash from \"effect/Hash\";\nimport * as Match from \"effect/Match\";\nimport * as Pipeable from \"effect/Pipeable\";\nimport * as Predicate from \"effect/Predicate\";\n\nconst TypeId = \"@confect/react/QueryResult\";\ntype TypeId = typeof TypeId;\n\n/**\n * A `QueryResult` represents the result of a Confect query.\n *\n * @typeParam A - The type of the decoded `returns` value in the `Success` variant.\n * @typeParam E - The type of the decoded typed error in the `Failure` variant.\n */\nexport type QueryResult<A, E = never> =\n | Loading<A, E>\n | Success<A, E>\n | Failure<A, E>;\n\nexport declare namespace QueryResult {\n // eslint-disable-next-line import/namespace -- oxlint's namespace resolution misses type-only exports, and `Pipeable` is an interface\n export interface Proto<A, E> extends Pipeable.Pipeable {\n readonly [TypeId]: {\n readonly E: (_: never) => E;\n readonly A: (_: never) => A;\n };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Success<R> = R extends QueryResult<infer A, infer _E> ? A : never;\n\n // eslint-disable-next-line @typescript-eslint/no-shadow\n export type Failure<R> = R extends QueryResult<infer _A, infer E> ? E : never;\n}\n\nexport interface Loading<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Loading\";\n readonly skipped: boolean;\n}\n\nexport interface Success<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Success\";\n readonly value: A;\n}\n\nexport interface Failure<A, E = never> extends QueryResult.Proto<A, E> {\n readonly _tag: \"Failure\";\n readonly error: E;\n}\n\nexport const isQueryResult = (u: unknown): u is QueryResult<unknown, unknown> =>\n Predicate.hasProperty(u, TypeId);\n\nconst QueryResultProto = {\n [TypeId]: {\n E: identity,\n A: identity,\n },\n pipe(this: QueryResult<any, any>, ...args: ReadonlyArray<unknown>) {\n return Pipeable.pipeArguments(\n this,\n args as unknown as Parameters<typeof Pipeable.pipeArguments>[1],\n );\n },\n [Equal.symbol](\n this: QueryResult<any, any>,\n that: QueryResult<any, any>,\n ): boolean {\n if (this._tag !== that._tag) {\n return false;\n }\n return Match.value(this).pipe(\n Match.tag(\n \"Loading\",\n (self) => self.skipped === (that as Loading<any, any>).skipped,\n ),\n Match.tag(\"Success\", (self) =>\n Equal.equals(self.value, (that as Success<any, any>).value),\n ),\n Match.tag(\"Failure\", (self) =>\n Equal.equals(self.error, (that as Failure<any, any>).error),\n ),\n Match.exhaustive,\n );\n },\n [Hash.symbol](this: QueryResult<any, any>): number {\n const tagHash = Hash.string(this._tag);\n return Match.value(this).pipe(\n Match.tag(\"Loading\", (self) =>\n Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.skipped))),\n ),\n Match.tag(\"Success\", (self) =>\n Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.value))),\n ),\n Match.tag(\"Failure\", (self) =>\n Hash.cached(self, Hash.combine(tagHash)(Hash.hash(self.error))),\n ),\n Match.exhaustive,\n );\n },\n};\n\nexport const load = <A = never, E = never>(skipped: boolean): Loading<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Loading\" as const,\n skipped,\n });\n\nexport const succeed = <A, E = never>(value: A): Success<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Success\" as const,\n value,\n });\n\nexport const fail = <E, A = never>(error: E): Failure<A, E> =>\n Object.assign(Object.create(QueryResultProto), {\n _tag: \"Failure\" as const,\n error,\n });\n\nexport const isLoading = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Loading<A, E> => queryResult._tag === \"Loading\";\n\nexport const isSuccess = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Success<A, E> => queryResult._tag === \"Success\";\n\nexport const isFailure = <A, E>(\n queryResult: QueryResult<A, E>,\n): queryResult is Failure<A, E> => queryResult._tag === \"Failure\";\n\ntype MatchOptions<A, E, X, Y, Z> = {\n readonly onLoading: (skipped: boolean) => X;\n readonly onSuccess: (value: A) => Y;\n} & ([E] extends [never] ? {} : { readonly onFailure: (error: E) => Z });\n\ntype MatchReturns<E, X, Y, Z> = [E] extends [never] ? X | Y : X | Y | Z;\n\n/**\n * Matches a {@link QueryResult} to the appropriate handler based on its tag. If\n * the provided `QueryResult` cannot fail (i.e. `E` is `never`), `onFailure` is\n * not required.\n *\n * @example\n * ```tsx\n * const result = QueryResult.match(queryResult, {\n * onLoading: (skipped) => skipped ? null : <p>Loading…</p>,\n * onSuccess: (value) => <p>{value.text}</p>,\n * onFailure: (error) => <p>Error: {error.message}</p>,\n * });\n */\nexport const match: {\n <A, E, X, Y, Z = never>(\n options: MatchOptions<A, E, X, Y, Z>,\n ): (self: QueryResult<A, E>) => MatchReturns<E, X, Y, Z>;\n <A, E, X, Y, Z = never>(\n self: QueryResult<A, E>,\n options: MatchOptions<A, E, X, Y, Z>,\n ): MatchReturns<E, X, Y, Z>;\n} = Function.dual(\n 2,\n <A, E, X, Y, Z = never>(\n self: QueryResult<A, E>,\n options: MatchOptions<A, E, X, Y, Z>,\n ): MatchReturns<E, X, Y, Z> =>\n Match.value(self).pipe(\n Match.tag(\"Loading\", (loading) => options.onLoading(loading.skipped)),\n Match.tag(\"Success\", (success) => options.onSuccess(success.value)),\n Match.tag(\"Failure\", (failure) => {\n if (Predicate.hasProperty(options, \"onFailure\")) {\n return options.onFailure(failure.error);\n }\n throw new Error(\n \"`onFailure` is required when error schema is provided\",\n );\n }),\n Match.exhaustive,\n ) as MatchReturns<E, X, Y, Z>,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAQA,MAAM,SAAS;AA6Cf,MAAa,iBAAiB,MAC5B,UAAU,YAAY,GAAG,MAAM;AAEjC,MAAM,mBAAmB;EACtB,SAAS;EACR,GAAG;EACH,GAAG;CACL;CACA,KAAkC,GAAG,MAA8B;EACjE,OAAO,SAAS,cACd,MACA,IACF;CACF;CACA,CAAC,MAAM,QAEL,MACS;EACT,IAAI,KAAK,SAAS,KAAK,MACrB,OAAO;EAET,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KACvB,MAAM,IACJ,YACC,SAAS,KAAK,YAAa,KAA2B,OACzD,GACA,MAAM,IAAI,YAAY,SACpB,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK,CAC5D,GACA,MAAM,IAAI,YAAY,SACpB,MAAM,OAAO,KAAK,OAAQ,KAA2B,KAAK,CAC5D,GACA,MAAM,UACR;CACF;CACA,CAAC,KAAK,UAA6C;EACjD,MAAM,UAAU,KAAK,OAAO,KAAK,IAAI;EACrC,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KACvB,MAAM,IAAI,YAAY,SACpB,KAAK,OAAO,MAAM,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,CAAC,CAAC,CAClE,GACA,MAAM,IAAI,YAAY,SACpB,KAAK,OAAO,MAAM,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAAC,CAChE,GACA,MAAM,IAAI,YAAY,SACpB,KAAK,OAAO,MAAM,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,CAAC,CAChE,GACA,MAAM,UACR;CACF;AACF;AAEA,MAAa,QAA8B,YACzC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,WAAyB,UACpC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,QAAsB,UACjC,OAAO,OAAO,OAAO,OAAO,gBAAgB,GAAG;CAC7C,MAAM;CACN;AACF,CAAC;AAEH,MAAa,aACX,gBACiC,YAAY,SAAS;AAExD,MAAa,aACX,gBACiC,YAAY,SAAS;AAExD,MAAa,aACX,gBACiC,YAAY,SAAS;;;;;;;;;;;;;;AAsBxD,MAAa,QAQT,SAAS,KACX,IAEE,MACA,YAEA,MAAM,MAAM,IAAI,CAAC,CAAC,KAChB,MAAM,IAAI,YAAY,YAAY,QAAQ,UAAU,QAAQ,OAAO,CAAC,GACpE,MAAM,IAAI,YAAY,YAAY,QAAQ,UAAU,QAAQ,KAAK,CAAC,GAClE,MAAM,IAAI,YAAY,YAAY;CAChC,IAAI,UAAU,YAAY,SAAS,WAAW,GAC5C,OAAO,QAAQ,UAAU,QAAQ,KAAK;CAExC,MAAM,IAAI,MACR,uDACF;AACF,CAAC,GACD,MAAM,UACR,CACJ"}
package/dist/index.d.ts CHANGED
@@ -1,13 +1,58 @@
1
1
  import { Ref } from "@confect/core";
2
+ import type { usePaginatedQuery as useConvexPaginatedQuery } from "convex/react";
2
3
  import * as Either from "effect/Either";
3
4
  import * as OptimisticLocalStore from "./OptimisticLocalStore";
5
+ import * as PaginatedQueryResult from "./PaginatedQueryResult";
4
6
  import * as QueryResult from "./QueryResult";
5
- export { OptimisticLocalStore, QueryResult };
7
+ export { OptimisticLocalStore, PaginatedQueryResult, QueryResult };
6
8
  export type InvokeReturn<Ref_ extends Ref.Any> = [Ref.Error<Ref_>] extends [
7
9
  never
8
10
  ] ? Promise<Ref.Returns<Ref_>> : Promise<Either.Either<Ref.Returns<Ref_>, Ref.Error<Ref_>>>;
9
11
  type UseQueryArgs<Query extends Ref.AnyPublicQuery> = keyof Ref.Args<Query> extends never ? [args?: Ref.Args<Query> | "skip"] : [args: Ref.Args<Query> | "skip"];
10
12
  export declare const useQuery: <Query extends Ref.AnyPublicQuery>(ref: Query, ...rest: UseQueryArgs<Query>) => QueryResult.QueryResult<Ref.Returns<Query>, Ref.Error<Query>>;
13
+ /**
14
+ * Like `Omit`, but implemented with key remapping so that optional modifiers
15
+ * are preserved and index signatures don't reintroduce the omitted key's
16
+ * literal type. Mirrors `BetterOmit` from `convex/server`.
17
+ */
18
+ type OmitKey<T, K extends PropertyKey> = {
19
+ [P in keyof T as P extends K ? never : P]: T[P];
20
+ };
21
+ /**
22
+ * The args accepted by {@link usePaginatedQuery}: the ref's args without
23
+ * `paginationOpts`, which the underlying Convex hook manages itself. When no
24
+ * args remain, resolves to `Record<string, never>` (only the empty object is
25
+ * accepted) rather than `{}`, which would accept any non-nullish value.
26
+ */
27
+ export type PaginatedQueryArgs<Query extends Ref.AnyPublicPaginatedQuery> = OmitKey<Ref.Args<Query>, "paginationOpts"> extends infer Args_ ? keyof Args_ extends never ? Record<string, never> : Args_ : never;
28
+ /**
29
+ * The item type for a paginated query: the element type of the `page` field
30
+ * of the ref's returns.
31
+ */
32
+ export type PaginatedQueryItem<Query extends Ref.AnyPublicPaginatedQuery> = Ref.Returns<Query>["page"][number];
33
+ /**
34
+ * The args parameter of {@link usePaginatedQuery}: the ref's args without
35
+ * `paginationOpts`, or `"skip"` to skip the query.
36
+ */
37
+ export type UsePaginatedQueryArgs<Query extends Ref.AnyPublicPaginatedQuery> = PaginatedQueryArgs<Query> | "skip";
38
+ export type PaginatedQueryOptions = Parameters<typeof useConvexPaginatedQuery>[2];
39
+ /**
40
+ * Load data reactively from a paginated query defined with
41
+ * `FunctionSpec.publicPaginatedQuery`, mirroring the ergonomics of
42
+ * `usePaginatedQuery` from `convex/react`.
43
+ *
44
+ * Args are encoded via the ref's user-args schema (`paginationOpts` is managed
45
+ * by the Convex hook, not the caller), and each loaded page is decoded via the
46
+ * ref's item schema.
47
+ *
48
+ * Returns a {@link PaginatedQueryResult.PaginatedQueryResult}: the loaded
49
+ * variants carry `results` and `isLoading`, and `CanLoadMore` additionally
50
+ * carries `loadMore`; if the `Ref` declares an `error` schema and the query
51
+ * fails with that typed error, the decoded error is returned as the `Failure`
52
+ * variant, which also carries the pages loaded before the failure. Unknown
53
+ * errors are thrown, to be caught by an error boundary.
54
+ */
55
+ export declare const usePaginatedQuery: <Query extends Ref.AnyPublicPaginatedQuery>(ref: Query, args: UsePaginatedQueryArgs<Query>, options: PaginatedQueryOptions) => PaginatedQueryResult.PaginatedQueryResult<PaginatedQueryItem<Query>, Ref.Error<Query>>;
11
56
  /**
12
57
  * An optimistic update for a Confect mutation. Mirrors Convex's
13
58
  * `OptimisticUpdate`, but receives a Confect {@link OptimisticLocalStore} and
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAYpC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAKxC,OAAO,KAAK,oBAAoB,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,WAAW,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC;AAE7C,MAAM,MAAM,YAAY,CAAC,IAAI,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS;IACzE,KAAK;CACN,GACG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE/D,KAAK,YAAY,CAAC,KAAK,SAAS,GAAG,CAAC,cAAc,IAChD,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,KAAK,GAC/B,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,GACjC,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC;AAEvC,eAAO,MAAM,QAAQ,GAAI,KAAK,SAAS,GAAG,CAAC,cAAc,EACvD,KAAK,KAAK,EACV,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,KAC3B,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CA4C9D,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,CAAC,QAAQ,SAAS,GAAG,CAAC,iBAAiB,IAAI,CACrE,UAAU,EAAE,oBAAoB,CAAC,oBAAoB,EACrD,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,KACrB,IAAI,CAAC;AAEV;;;;;GAKG;AACH,MAAM,WAAW,aAAa,CAAC,QAAQ,SAAS,GAAG,CAAC,iBAAiB;IACnE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC9D,oBAAoB,CAClB,gBAAgB,EAAE,gBAAgB,CAAC,QAAQ,CAAC,GAC3C,aAAa,CAAC,QAAQ,CAAC,CAAC;CAC5B;AAsCD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,SAAS,GAAG,CAAC,iBAAiB,EAChE,KAAK,QAAQ,KACZ,aAAa,CAAC,QAAQ,CAcxB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,GAAG,CAAC,eAAe,EAC1D,KAAK,MAAM,KACV,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,YAAY,CAAC,MAAM,CAAC,CAe9D,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,11 +1,15 @@
1
1
  import { OptimisticLocalStore_exports, make } from "./OptimisticLocalStore.js";
2
+ import { PaginatedQueryResult_exports, canLoadMore, exhausted, failure, loadingFirstPage, loadingMore } from "./PaginatedQueryResult.js";
2
3
  import { QueryResult_exports, fail, load, succeed } from "./QueryResult.js";
3
4
  import { Ref } from "@confect/core";
5
+ import { version } from "convex";
6
+ import * as ConvexReact from "convex/react";
4
7
  import { useAction as useAction$1, useMutation as useMutation$1, useQuery as useQuery$1 } from "convex/react";
5
8
  import * as Cause from "effect/Cause";
6
9
  import * as Effect from "effect/Effect";
7
10
  import * as Either from "effect/Either";
8
11
  import * as Exit from "effect/Exit";
12
+ import * as Match from "effect/Match";
9
13
  import * as Option from "effect/Option";
10
14
  import { useCallback, useMemo } from "react";
11
15
  //#region src/index.ts
@@ -19,7 +23,7 @@ const useQuery = (ref, ...rest) => {
19
23
  onRight: (encodedReturnsOrUndefined) => encodedReturnsOrUndefined === void 0 ? load(skipped) : succeed(Ref.decodeReturnsSync(ref, encodedReturnsOrUndefined)),
20
24
  onLeft: (error) => {
21
25
  if (Ref.isConvexError(error)) {
22
- const decoded = Ref.decodeErrorSync(ref, error.data);
26
+ const decoded = Ref.decodeErrorOption(ref, error.data);
23
27
  if (Option.isSome(decoded)) return fail(decoded.value);
24
28
  }
25
29
  throw error;
@@ -30,6 +34,72 @@ const useQuery = (ref, ...rest) => {
30
34
  Either.merge(encodedReturnsOrError)
31
35
  ]);
32
36
  };
37
+ const useConvexPaginatedQueryInternal = ConvexReact.usePaginatedQueryInternal;
38
+ const MINIMUM_CONVEX_VERSION = "1.36.0";
39
+ /**
40
+ * The non-throwing mode of `usePaginatedQueryInternal` — its fourth,
41
+ * `throwOnError` parameter — arrived in convex 1.36.0. Convex 1.32 through
42
+ * 1.35 export the same symbol taking only three parameters, where a fourth
43
+ * argument is silently ignored and errors are always thrown.
44
+ *
45
+ * The function itself cannot be interrogated for this: `Function.length`
46
+ * counts parameters up to the first one with a default, and 1.36.0 declares
47
+ * `throwOnError = true`, so both shapes report an arity of 3. The package
48
+ * version is the only reliable signal.
49
+ */
50
+ const supportsErrorsAsValues = (() => {
51
+ const [major, minor] = String(version).split(".").map(Number);
52
+ if (major === void 0 || minor === void 0 || Number.isNaN(major) || Number.isNaN(minor)) return false;
53
+ const [minimumMajor, minimumMinor] = MINIMUM_CONVEX_VERSION.split(".").map(Number);
54
+ return major > minimumMajor || major === minimumMajor && minor >= minimumMinor;
55
+ })();
56
+ /**
57
+ * Load data reactively from a paginated query defined with
58
+ * `FunctionSpec.publicPaginatedQuery`, mirroring the ergonomics of
59
+ * `usePaginatedQuery` from `convex/react`.
60
+ *
61
+ * Args are encoded via the ref's user-args schema (`paginationOpts` is managed
62
+ * by the Convex hook, not the caller), and each loaded page is decoded via the
63
+ * ref's item schema.
64
+ *
65
+ * Returns a {@link PaginatedQueryResult.PaginatedQueryResult}: the loaded
66
+ * variants carry `results` and `isLoading`, and `CanLoadMore` additionally
67
+ * carries `loadMore`; if the `Ref` declares an `error` schema and the query
68
+ * fails with that typed error, the decoded error is returned as the `Failure`
69
+ * variant, which also carries the pages loaded before the failure. Unknown
70
+ * errors are thrown, to be caught by an error boundary.
71
+ */
72
+ const usePaginatedQuery = (ref, args, options) => {
73
+ if (useConvexPaginatedQueryInternal === void 0 || !supportsErrorsAsValues) throw new Error(`usePaginatedQuery requires convex >= ${MINIMUM_CONVEX_VERSION}, but found ${version}. Earlier versions always throw paginated query errors instead of returning them, so a declared \`error\` schema cannot be surfaced as a \`Failure\` — upgrade the \`convex\` package.`);
74
+ const functionReference = Ref.getFunctionReference(ref);
75
+ const skipped = args === "skip";
76
+ const encodedArgs = useMemo(() => args === "skip" ? "skip" : Ref.encodePaginatedQueryArgsSync(ref, args), [ref, args]);
77
+ const { user: convexResult } = useConvexPaginatedQueryInternal(functionReference, encodedArgs, options, false);
78
+ const { results: encodedResults } = convexResult;
79
+ const decodedResults = useMemo(() => Ref.decodePaginationPageSync(ref, encodedResults), [ref, encodedResults]);
80
+ const { status, loadMore } = convexResult;
81
+ const error = status === "Error" ? convexResult.error : void 0;
82
+ return useMemo(() => Match.value(status).pipe(Match.when("Error", () => {
83
+ if (Ref.isConvexError(error)) {
84
+ const decoded = Ref.decodeErrorOption(ref, error.data);
85
+ if (Option.isSome(decoded)) return failure({
86
+ error: decoded.value,
87
+ results: decodedResults
88
+ });
89
+ }
90
+ throw error;
91
+ }), Match.when("LoadingFirstPage", () => loadingFirstPage({ skipped })), Match.when("LoadingMore", () => loadingMore({ results: decodedResults })), Match.when("CanLoadMore", () => canLoadMore({
92
+ results: decodedResults,
93
+ loadMore
94
+ })), Match.when("Exhausted", () => exhausted({ results: decodedResults })), Match.exhaustive), [
95
+ ref,
96
+ skipped,
97
+ decodedResults,
98
+ status,
99
+ loadMore,
100
+ error
101
+ ]);
102
+ };
33
103
  const makeReactMutation = (ref, convexReactMutation) => {
34
104
  const callable = ((...args) => invokeAsEither(ref, (_, encodedArgs) => convexReactMutation(encodedArgs), args).then((either) => Ref.hasErrorSchema(ref) ? either : Either.getOrThrow(either)));
35
105
  const withOptimisticUpdate = (optimisticUpdate) => {
@@ -85,6 +155,6 @@ const invokeAsEither = async (ref, invoke, args) => {
85
155
  throw Cause.squash(exit.cause);
86
156
  };
87
157
  //#endregion
88
- export { OptimisticLocalStore_exports as OptimisticLocalStore, QueryResult_exports as QueryResult, useAction, useMutation, useQuery };
158
+ export { OptimisticLocalStore_exports as OptimisticLocalStore, PaginatedQueryResult_exports as PaginatedQueryResult, QueryResult_exports as QueryResult, useAction, useMutation, usePaginatedQuery, useQuery };
89
159
 
90
160
  //# sourceMappingURL=index.js.map