kitcn 0.33.0 → 0.33.2
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 +15 -0
- package/dist/aggregate/index.d.ts +1 -1
- package/dist/auth/generated/index.d.ts +1 -1
- package/dist/auth/index.d.ts +16 -16
- package/dist/auth/nextjs/index.d.ts +1 -1
- package/dist/auth/start/server/index.d.ts +1 -1
- package/dist/{builder-Cyd5nCxZ.js → builder-DDYTlmTB.js} +12 -3
- package/dist/cli.mjs +48 -7
- package/dist/crpc/index.d.ts +1 -1
- package/dist/{generated-contract-disabled-PdNGvNYP.d.ts → generated-contract-disabled-CTUQ9nxL.d.ts} +40 -40
- package/dist/{middleware-D61Nm-iB.js → middleware-LvZov-hA.js} +1 -1
- package/dist/orm/index.d.ts +1 -1
- package/dist/orm/migrations/index.d.ts +1 -1
- package/dist/plugins/index.js +1 -1
- package/dist/{procedure-caller-DgMiD0-a.js → procedure-caller-DgGF_hA8.js} +1 -1
- package/dist/{procedure-name-DPYyLiVS.d.ts → procedure-name-DRSOwAJY.d.ts} +7 -3
- package/dist/ratelimit/index.js +2 -2
- package/dist/react/index.d.ts +5 -6
- package/dist/react/index.js +20 -66
- package/dist/rsc/index.d.ts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +2 -2
- package/dist/solid/index.d.ts +5 -6
- package/dist/solid/index.js +20 -66
- package/dist/{types-BXpu7xIU.d.ts → types-C7JkpfeY.d.ts} +2 -2
- package/dist/{where-clause-compiler-DrV6lQg0.d.ts → where-clause-compiler-B0kyVGzW.d.ts} +99 -99
- package/package.json +1 -1
- package/skills/kitcn/SKILL.md +2 -1
- package/skills/kitcn/references/features/auth-admin.md +1 -0
- package/skills/kitcn/references/features/react.md +4 -5
package/dist/react/index.d.ts
CHANGED
|
@@ -487,8 +487,8 @@ type ConvexQueryHookOptions = {
|
|
|
487
487
|
/** Skip query silently when unauthenticated (default: false, calls onQueryUnauthorized) */skipUnauth?: boolean; /** Set to false to fetch once without subscribing (default: true) */
|
|
488
488
|
subscribe?: boolean;
|
|
489
489
|
};
|
|
490
|
-
/** Extract
|
|
491
|
-
type InfiniteQueryInput<TInput> = Omit<TInput, 'cursor' | 'limit'>;
|
|
490
|
+
/** Extract user args without hook-owned pagination transport fields */
|
|
491
|
+
type InfiniteQueryInput<TInput> = Omit<TInput, 'cursor' | 'endCursor' | 'limit'>;
|
|
492
492
|
/** Extract item type from PaginationResult<T> */
|
|
493
493
|
type ExtractPaginatedItem<TOutput> = TOutput extends {
|
|
494
494
|
page: (infer T)[];
|
|
@@ -946,7 +946,7 @@ declare const getConvexQueryClientSingleton: ({
|
|
|
946
946
|
* Pagination state persisted in queryClient.
|
|
947
947
|
* Enables scroll restoration when navigating back to a paginated list.
|
|
948
948
|
*
|
|
949
|
-
* Uses flat { cursor, limit } structure like tRPC.
|
|
949
|
+
* Uses flat { cursor, endCursor, limit } structure like tRPC.
|
|
950
950
|
*/
|
|
951
951
|
type PaginationState = {
|
|
952
952
|
id: number;
|
|
@@ -955,13 +955,12 @@ type PaginationState = {
|
|
|
955
955
|
queries: Record<number, {
|
|
956
956
|
/** Flat pagination args - tRPC style */args: Record<string, unknown> & {
|
|
957
957
|
cursor: string | null;
|
|
958
|
+
endCursor?: string | null;
|
|
958
959
|
limit?: number; /** Internal pagination ID for subscription management */
|
|
959
960
|
__paginationId?: number;
|
|
960
961
|
};
|
|
961
|
-
endCursor?: string | null;
|
|
962
962
|
}>;
|
|
963
|
-
version: number;
|
|
964
|
-
autoRecoveryAttempted?: string;
|
|
963
|
+
version: number;
|
|
965
964
|
};
|
|
966
965
|
type PaginationStatus = 'CanLoadMore' | 'Exhausted' | 'LoadingFirstPage' | 'LoadingMore';
|
|
967
966
|
/** Fields we override or omit from TanStack Query's UseQueryResult */
|
package/dist/react/index.js
CHANGED
|
@@ -2432,6 +2432,12 @@ const getConvexQueryClientSingleton = ({ authStore, convex, queryClient, symbolK
|
|
|
2432
2432
|
//#endregion
|
|
2433
2433
|
//#region src/internal/pagination.ts
|
|
2434
2434
|
const shouldSplitPaginationPage = (page, initialNumItems) => Boolean(page.splitCursor) && (page.pageStatus === "SplitRecommended" || page.pageStatus === "SplitRequired" || initialNumItems !== void 0 && page.page.length > initialNumItems * 2);
|
|
2435
|
+
const isInvalidPaginationCursor = (error) => {
|
|
2436
|
+
if (error instanceof Error && error.message.includes("InvalidCursor")) return true;
|
|
2437
|
+
if (!error || typeof error !== "object" || !("data" in error)) return false;
|
|
2438
|
+
const data = error.data;
|
|
2439
|
+
return Boolean(data && typeof data === "object" && "isConvexSystemError" in data && data.isConvexSystemError === true && "paginationError" in data && data.paginationError === "InvalidCursor");
|
|
2440
|
+
};
|
|
2435
2441
|
|
|
2436
2442
|
//#endregion
|
|
2437
2443
|
//#region src/react/use-infinite-query.ts
|
|
@@ -2439,76 +2445,22 @@ const shouldSplitPaginationPage = (page, initialNumItems) => Boolean(page.splitC
|
|
|
2439
2445
|
const PAGINATION_KEY_PREFIX = "__pagination__";
|
|
2440
2446
|
let paginationIdCounter = 0;
|
|
2441
2447
|
const createPaginationId = () => ++paginationIdCounter;
|
|
2442
|
-
/** Build a unique key for recovery attempt detection */
|
|
2443
|
-
const buildRecoveryKey = (pageKeys, page0Cursor, page0UpdatedAt) => JSON.stringify({
|
|
2444
|
-
pageKeys,
|
|
2445
|
-
page0Cursor,
|
|
2446
|
-
page0UpdatedAt
|
|
2447
|
-
});
|
|
2448
2448
|
/**
|
|
2449
2449
|
* Hook for auto-recovering from stale cursors after WebSocket reconnection.
|
|
2450
2450
|
*
|
|
2451
2451
|
* When Convex WebSocket reconnects, page 0 (cursor: null) resubscribes and
|
|
2452
2452
|
* gets fresh data. However, pages 1+ may have stale cursors that fail.
|
|
2453
2453
|
*
|
|
2454
|
-
* This hook
|
|
2455
|
-
* enough items to cover the lost pages, preserving the user's scroll position.
|
|
2454
|
+
* This hook discards the invalid cursor chain and restarts from page one.
|
|
2456
2455
|
*/
|
|
2457
|
-
const useStaleCursorRecovery = ({
|
|
2456
|
+
const useStaleCursorRecovery = ({ combined, resetPagination }) => {
|
|
2458
2457
|
useEffect(() => {
|
|
2459
2458
|
if (!combined.isFetchNextPageError) return;
|
|
2460
|
-
|
|
2461
|
-
const page0Data = page0Result?.data;
|
|
2462
|
-
const page0UpdatedAt = page0Result?.dataUpdatedAt ?? 0;
|
|
2463
|
-
const hasPage0Data = page0Data !== void 0 && !page0Result?.isError;
|
|
2464
|
-
const hasSubsequentErrors = combined._rawResults.slice(1).some((q) => q?.isError && !q?.isFetching);
|
|
2465
|
-
if (!hasPage0Data || !hasSubsequentErrors || !page0Data?.continueCursor) return;
|
|
2466
|
-
const recoveryKey = buildRecoveryKey(state.pageKeys, page0Data.continueCursor, page0UpdatedAt);
|
|
2467
|
-
if (state.autoRecoveryAttempted === recoveryKey) return;
|
|
2468
|
-
const erroredPageKeys = state.pageKeys.filter((_, i) => i > 0 && combined._rawResults[i]?.isError);
|
|
2469
|
-
const itemsToRecover = erroredPageKeys.reduce((sum, key) => {
|
|
2470
|
-
return sum + (state.queries[key]?.args?.limit ?? limit ?? 20);
|
|
2471
|
-
}, 0);
|
|
2472
|
-
console.warn("[Pagination] Auto-recovering from stale cursors", {
|
|
2473
|
-
erroredPages: erroredPageKeys.length,
|
|
2474
|
-
itemsToRecover
|
|
2475
|
-
});
|
|
2476
|
-
setState((prev) => ({
|
|
2477
|
-
...prev,
|
|
2478
|
-
id: prev.id,
|
|
2479
|
-
nextPageKey: 2,
|
|
2480
|
-
pageKeys: [prev.pageKeys[0], 1],
|
|
2481
|
-
queries: {
|
|
2482
|
-
[prev.pageKeys[0]]: prev.queries[prev.pageKeys[0]],
|
|
2483
|
-
1: { args: {
|
|
2484
|
-
...argsObject,
|
|
2485
|
-
cursor: page0Data.continueCursor,
|
|
2486
|
-
limit: Math.min(itemsToRecover + (limit ?? 20), 500),
|
|
2487
|
-
__paginationId: prev.id
|
|
2488
|
-
} }
|
|
2489
|
-
},
|
|
2490
|
-
version: prev.version + 1,
|
|
2491
|
-
autoRecoveryAttempted: recoveryKey
|
|
2492
|
-
}));
|
|
2459
|
+
if (combined._rawResults.slice(1).some((result) => result?.isError && !result.isFetching && isInvalidPaginationCursor(result.error))) resetPagination();
|
|
2493
2460
|
}, [
|
|
2494
2461
|
combined.isFetchNextPageError,
|
|
2495
2462
|
combined._rawResults,
|
|
2496
|
-
|
|
2497
|
-
state.queries,
|
|
2498
|
-
state.autoRecoveryAttempted,
|
|
2499
|
-
argsObject,
|
|
2500
|
-
limit,
|
|
2501
|
-
setState
|
|
2502
|
-
]);
|
|
2503
|
-
useEffect(() => {
|
|
2504
|
-
if ((combined.status === "CanLoadMore" || combined.status === "Exhausted") && state.autoRecoveryAttempted) setState((prev) => ({
|
|
2505
|
-
...prev,
|
|
2506
|
-
autoRecoveryAttempted: void 0
|
|
2507
|
-
}));
|
|
2508
|
-
}, [
|
|
2509
|
-
combined.status,
|
|
2510
|
-
state.autoRecoveryAttempted,
|
|
2511
|
-
setState
|
|
2463
|
+
resetPagination
|
|
2512
2464
|
]);
|
|
2513
2465
|
};
|
|
2514
2466
|
/**
|
|
@@ -2706,7 +2658,7 @@ const useInfiniteQueryInternal = (query, args, options) => {
|
|
|
2706
2658
|
error: results.find((r) => r.isError)?.error ?? null,
|
|
2707
2659
|
isError: results.some((r) => r.isError),
|
|
2708
2660
|
isFetching,
|
|
2709
|
-
isFetchNextPageError: results.
|
|
2661
|
+
isFetchNextPageError: results.slice(1).some((result) => result.isError),
|
|
2710
2662
|
isPlaceholderData,
|
|
2711
2663
|
isRefetching: isFetching && allItems.length > 0 && !isPlaceholderData,
|
|
2712
2664
|
_rawResults: results
|
|
@@ -2714,11 +2666,8 @@ const useInfiniteQueryInternal = (query, args, options) => {
|
|
|
2714
2666
|
}, [placeholderData])
|
|
2715
2667
|
});
|
|
2716
2668
|
useStaleCursorRecovery({
|
|
2717
|
-
argsObject,
|
|
2718
2669
|
combined,
|
|
2719
|
-
|
|
2720
|
-
setState,
|
|
2721
|
-
state
|
|
2670
|
+
resetPagination: useCallback(() => setState(createInitialState()), [createInitialState, setState])
|
|
2722
2671
|
});
|
|
2723
2672
|
useEffect(() => {
|
|
2724
2673
|
for (let i = 0; i < combined._rawResults.length; i++) {
|
|
@@ -2727,15 +2676,17 @@ const useInfiniteQueryInternal = (query, args, options) => {
|
|
|
2727
2676
|
const page = pageQuery.data;
|
|
2728
2677
|
const pageKey = state.pageKeys[i];
|
|
2729
2678
|
const pageState = state.queries[pageKey];
|
|
2730
|
-
if (shouldSplitPaginationPage(page, limit) && pageState &&
|
|
2679
|
+
if (shouldSplitPaginationPage(page, limit) && pageState && pageState.args.endCursor !== page.splitCursor) {
|
|
2731
2680
|
setState((prev) => {
|
|
2732
2681
|
const currentPageState = prev.queries[pageKey];
|
|
2733
|
-
if (!currentPageState || currentPageState.endCursor) return prev;
|
|
2682
|
+
if (!currentPageState || currentPageState.args.endCursor === page.splitCursor) return prev;
|
|
2734
2683
|
const newKey = prev.nextPageKey;
|
|
2735
2684
|
const splitCursor = page.splitCursor;
|
|
2685
|
+
const endCursor = currentPageState.args.endCursor ?? page.continueCursor;
|
|
2736
2686
|
const splitPageArgs = {
|
|
2737
2687
|
...argsObject,
|
|
2738
2688
|
cursor: splitCursor,
|
|
2689
|
+
endCursor,
|
|
2739
2690
|
limit: currentPageState.args.limit,
|
|
2740
2691
|
__paginationId: prev.id
|
|
2741
2692
|
};
|
|
@@ -2750,7 +2701,10 @@ const useInfiniteQueryInternal = (query, args, options) => {
|
|
|
2750
2701
|
...prev.queries,
|
|
2751
2702
|
[pageKey]: {
|
|
2752
2703
|
...currentPageState,
|
|
2753
|
-
|
|
2704
|
+
args: {
|
|
2705
|
+
...currentPageState.args,
|
|
2706
|
+
endCursor: splitCursor
|
|
2707
|
+
}
|
|
2754
2708
|
},
|
|
2755
2709
|
[newKey]: { args: splitPageArgs }
|
|
2756
2710
|
}
|
package/dist/rsc/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as DeepPartial, o as Simplify, r as DistributiveOmit } from "../types-Bqi_ivSd.js";
|
|
2
2
|
import { L as DataTransformerOptions, _ as CRPCHttpRouter, c as HttpQueryKey, k as HttpProcedure, o as HttpMutationKey, y as HttpRouterRecord } from "../http-types-BhhPZtwa.js";
|
|
3
3
|
import { g as UnsetMarker } from "../types-Bkeicpo6.js";
|
|
4
|
-
import { A as HttpInputArgs, C as ReservedMutationOptions$1, S as ReservedInfiniteQueryOptions, T as StaticQueryOptsParam, _ as IsPaginated, b as PaginatedFnMeta, c as ConvexMutationKey, d as ConvexQueryMeta, f as EmptyObject, g as InfiniteQueryInput, l as ConvexQueryHookOptions, m as FUNC_REF_SYMBOL, o as ConvexActionKey, p as ExtractPaginatedItem, s as ConvexInfiniteQueryMeta, u as ConvexQueryKey, w as ReservedQueryOptions$1, y as MutationVariables } from "../types-
|
|
4
|
+
import { A as HttpInputArgs, C as ReservedMutationOptions$1, S as ReservedInfiniteQueryOptions, T as StaticQueryOptsParam, _ as IsPaginated, b as PaginatedFnMeta, c as ConvexMutationKey, d as ConvexQueryMeta, f as EmptyObject, g as InfiniteQueryInput, l as ConvexQueryHookOptions, m as FUNC_REF_SYMBOL, o as ConvexActionKey, p as ExtractPaginatedItem, s as ConvexInfiniteQueryMeta, u as ConvexQueryKey, w as ReservedQueryOptions$1, y as MutationVariables } from "../types-C7JkpfeY.js";
|
|
5
5
|
import { FunctionArgs, FunctionReference, FunctionReturnType } from "convex/server";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { DefaultError, QueryFilters, SkipToken, UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as ActionProcedureBuilder, A as CRPCError, B as RuntimeEnv, C as createProcedureHandlerFactory, Ct as zCustomQuery, D as WithHttpRouter, Dt as zodToConvex, E as typedProcedureResolver, Et as zodOutputToConvexFields, F as getCRPCErrorFromUnknown, G as createLazyCaller, H as ConvexContext, I as getHTTPStatusCodeFromError, J as ServerCaller, K as CallerMeta, L as isCRPCError, M as CRPCErrorData, N as CRPC_ERROR_CODES_BY_KEY, O as inferApiInputs, Ot as zodToConvexFields, P as CRPC_ERROR_CODE_TO_HTTP, Q as getGeneratedValue, R as toCRPCError, S as createProcedureCallerFactory, St as zCustomMutation, T as getGeneratedFunctionReference, Tt as zodOutputToConvex, U as createCallerFactory, V as createEnv, W as LazyCaller, X as createApiLeaf, Y as createServerCaller, Z as createGeneratedFunctionReference, _ as ProcedureSchedulableCallerFromRegistry, _t as ZodValidatorFromConvex, a as CreateProcedureCallerFactoryOptions, at as initCRPC, b as createGenericCallerFactory, bt as withSystemFields, c as GeneratedRegistryCallerFactory, ct as extractPathParams, d as GeneratedRegistryHandlerForContext, dt as ConvexValidatorFromZod, et as CRPCFunctionTypeHint, f as ProcedureActionCallerFromRegistry, ft as ConvexValidatorFromZodOutput, g as ProcedureFromFunctionReference, gt as ZodFromValidatorBase, h as ProcedureDefinition, ht as Zid, i as registerProcedureNameLookup, it as createMiddlewareFactory, j as CRPCErrorCode, k as inferApiOutputs, l as GeneratedRegistryCallerForContext, lt as handleHttpError, m as ProcedureCallerFromRegistry, mt as ZCustomCtx, n as ProcedureNameLookup, nt as ProcedureBuilder, o as GeneratedProcedureRegistry, ot as HttpProcedureBuilder, p as ProcedureCaller, pt as CustomBuilder, q as CallerOpts, r as inferProcedureNameFromCallsite, rt as QueryProcedureBuilder, s as GeneratedProcedureRegistryEntry, st as createHttpProcedureBuilder, t as ProcedureNameEntry, tt as MutationProcedureBuilder, u as GeneratedRegistryHandlerFactory, ut as matchPathParams, v as ProcedureScheduleCallerFromRegistry, vt as convexToZod, w as defineProcedure, wt as zid, x as createGenericHandlerFactory, xt as zCustomAction, y as createGeneratedRegistryRuntime, yt as convexToZodFields, z as CreateEnvOptions } from "../procedure-name-
|
|
1
|
+
import { $ as ActionProcedureBuilder, A as CRPCError, B as RuntimeEnv, C as createProcedureHandlerFactory, Ct as zCustomQuery, D as WithHttpRouter, Dt as zodToConvex, E as typedProcedureResolver, Et as zodOutputToConvexFields, F as getCRPCErrorFromUnknown, G as createLazyCaller, H as ConvexContext, I as getHTTPStatusCodeFromError, J as ServerCaller, K as CallerMeta, L as isCRPCError, M as CRPCErrorData, N as CRPC_ERROR_CODES_BY_KEY, O as inferApiInputs, Ot as zodToConvexFields, P as CRPC_ERROR_CODE_TO_HTTP, Q as getGeneratedValue, R as toCRPCError, S as createProcedureCallerFactory, St as zCustomMutation, T as getGeneratedFunctionReference, Tt as zodOutputToConvex, U as createCallerFactory, V as createEnv, W as LazyCaller, X as createApiLeaf, Y as createServerCaller, Z as createGeneratedFunctionReference, _ as ProcedureSchedulableCallerFromRegistry, _t as ZodValidatorFromConvex, a as CreateProcedureCallerFactoryOptions, at as initCRPC, b as createGenericCallerFactory, bt as withSystemFields, c as GeneratedRegistryCallerFactory, ct as extractPathParams, d as GeneratedRegistryHandlerForContext, dt as ConvexValidatorFromZod, et as CRPCFunctionTypeHint, f as ProcedureActionCallerFromRegistry, ft as ConvexValidatorFromZodOutput, g as ProcedureFromFunctionReference, gt as ZodFromValidatorBase, h as ProcedureDefinition, ht as Zid, i as registerProcedureNameLookup, it as createMiddlewareFactory, j as CRPCErrorCode, k as inferApiOutputs, l as GeneratedRegistryCallerForContext, lt as handleHttpError, m as ProcedureCallerFromRegistry, mt as ZCustomCtx, n as ProcedureNameLookup, nt as ProcedureBuilder, o as GeneratedProcedureRegistry, ot as HttpProcedureBuilder, p as ProcedureCaller, pt as CustomBuilder, q as CallerOpts, r as inferProcedureNameFromCallsite, rt as QueryProcedureBuilder, s as GeneratedProcedureRegistryEntry, st as createHttpProcedureBuilder, t as ProcedureNameEntry, tt as MutationProcedureBuilder, u as GeneratedRegistryHandlerFactory, ut as matchPathParams, v as ProcedureScheduleCallerFromRegistry, vt as convexToZod, w as defineProcedure, wt as zid, x as createGenericHandlerFactory, xt as zCustomAction, y as createGeneratedRegistryRuntime, yt as convexToZodFields, z as CreateEnvOptions } from "../procedure-name-DRSOwAJY.js";
|
|
2
2
|
import { A as HttpProcedureBuilderDef, C as extractRouteMap, D as HttpHandlerOpts, E as HttpActionHandler, M as InferHttpInput, N as ProcedureMeta, O as HttpMethod, S as createHttpRouterFactory, T as HttpActionConstructor, _ as CRPCHttpRouter, b as HttpRouterWithHono, j as HttpRouteDefinition, k as HttpProcedure, v as HttpRouterDef, w as CRPCHonoHandler, x as createHttpRouter, y as HttpRouterRecord } from "../http-types-BhhPZtwa.js";
|
|
3
3
|
import { a as MergeZodObjects, c as MiddlewareMarker, d as MiddlewareProcedureType, f as MiddlewareResult, g as UnsetMarker, h as Simplify, i as IntersectIfDefined, l as MiddlewareNext, m as ResolveIfSet, n as AnyMiddlewareBuilder, o as MiddlewareBuilder, p as Overwrite, r as GetRawInputFn, s as MiddlewareFunction, t as AnyMiddleware, u as MiddlewareProcedureInfo } from "../types-Bkeicpo6.js";
|
|
4
4
|
import { a as isMutationCtx, c as isSchedulerCtx, d as requireQueryCtx, f as requireRunMutationCtx, i as isActionCtx, l as requireActionCtx, n as RunMutationCtx, o as isQueryCtx, p as requireSchedulerCtx, r as SchedulerCtx, s as isRunMutationCtx, t as GenericCtx, u as requireMutationCtx } from "../context-utils-Cbv4r0AA.js";
|
package/dist/server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as isMutationCtx, c as isSchedulerCtx, d as requireQueryCtx, f as requireRunMutationCtx, i as isActionCtx, l as requireActionCtx, n as createGeneratedFunctionReference, o as isQueryCtx, p as requireSchedulerCtx, r as getGeneratedValue, s as isRunMutationCtx, t as createApiLeaf, u as requireMutationCtx } from "../api-entry-Buvjl9hn.js";
|
|
2
2
|
import { n as createLazyCaller, r as createServerCaller, t as createCallerFactory } from "../caller-factory-C-N540BC.js";
|
|
3
|
-
import { A as zid, C as toCRPCError, D as zCustomAction, E as withSystemFields, M as zodOutputToConvexFields, N as zodToConvex, O as zCustomMutation, P as zodToConvexFields, S as isCRPCError, T as convexToZodFields, _ as CRPCError, a as createMiddlewareFactory, b as getCRPCErrorFromUnknown, c as registerProcedureNameLookup, d as createHttpRouterFactory, f as extractRouteMap, g as matchPathParams, h as handleHttpError, i as QueryProcedureBuilder, j as zodOutputToConvex, k as zCustomQuery, l as HttpRouterWithHono, m as extractPathParams, n as MutationProcedureBuilder, o as initCRPC, p as createHttpProcedureBuilder, r as ProcedureBuilder, s as inferProcedureNameFromCallsite, t as ActionProcedureBuilder, u as createHttpRouter, v as CRPC_ERROR_CODES_BY_KEY, w as convexToZod, x as getHTTPStatusCodeFromError, y as CRPC_ERROR_CODE_TO_HTTP } from "../builder-
|
|
4
|
-
import { a as createProcedureHandlerFactory, c as typedProcedureResolver, i as createProcedureCallerFactory, l as createEnv, n as createGenericCallerFactory, o as defineProcedure, r as createGenericHandlerFactory, s as getGeneratedFunctionReference, t as createGeneratedRegistryRuntime } from "../procedure-caller-
|
|
3
|
+
import { A as zid, C as toCRPCError, D as zCustomAction, E as withSystemFields, M as zodOutputToConvexFields, N as zodToConvex, O as zCustomMutation, P as zodToConvexFields, S as isCRPCError, T as convexToZodFields, _ as CRPCError, a as createMiddlewareFactory, b as getCRPCErrorFromUnknown, c as registerProcedureNameLookup, d as createHttpRouterFactory, f as extractRouteMap, g as matchPathParams, h as handleHttpError, i as QueryProcedureBuilder, j as zodOutputToConvex, k as zCustomQuery, l as HttpRouterWithHono, m as extractPathParams, n as MutationProcedureBuilder, o as initCRPC, p as createHttpProcedureBuilder, r as ProcedureBuilder, s as inferProcedureNameFromCallsite, t as ActionProcedureBuilder, u as createHttpRouter, v as CRPC_ERROR_CODES_BY_KEY, w as convexToZod, x as getHTTPStatusCodeFromError, y as CRPC_ERROR_CODE_TO_HTTP } from "../builder-DDYTlmTB.js";
|
|
4
|
+
import { a as createProcedureHandlerFactory, c as typedProcedureResolver, i as createProcedureCallerFactory, l as createEnv, n as createGenericCallerFactory, o as defineProcedure, r as createGenericHandlerFactory, s as getGeneratedFunctionReference, t as createGeneratedRegistryRuntime } from "../procedure-caller-DgGF_hA8.js";
|
|
5
5
|
|
|
6
6
|
export { ActionProcedureBuilder, CRPCError, CRPC_ERROR_CODES_BY_KEY, CRPC_ERROR_CODE_TO_HTTP, HttpRouterWithHono, MutationProcedureBuilder, ProcedureBuilder, QueryProcedureBuilder, convexToZod, convexToZodFields, createApiLeaf, createCallerFactory, createEnv, createGeneratedFunctionReference, createGeneratedRegistryRuntime, createGenericCallerFactory, createGenericHandlerFactory, createHttpProcedureBuilder, createHttpRouter, createHttpRouterFactory, createLazyCaller, createMiddlewareFactory, createProcedureCallerFactory, createProcedureHandlerFactory, createServerCaller, defineProcedure, extractPathParams, extractRouteMap, getCRPCErrorFromUnknown, getGeneratedFunctionReference, getGeneratedValue, getHTTPStatusCodeFromError, handleHttpError, inferProcedureNameFromCallsite, initCRPC, isActionCtx, isCRPCError, isMutationCtx, isQueryCtx, isRunMutationCtx, isSchedulerCtx, matchPathParams, registerProcedureNameLookup, requireActionCtx, requireMutationCtx, requireQueryCtx, requireRunMutationCtx, requireSchedulerCtx, toCRPCError, typedProcedureResolver, withSystemFields, zCustomAction, zCustomMutation, zCustomQuery, zid, zodOutputToConvex, zodOutputToConvexFields, zodToConvex, zodToConvexFields };
|
package/dist/solid/index.d.ts
CHANGED
|
@@ -60,8 +60,8 @@ type ConvexQueryHookOptions = {
|
|
|
60
60
|
/** Skip query silently when unauthenticated (default: false, calls onQueryUnauthorized) */skipUnauth?: boolean; /** Set to false to fetch once without subscribing (default: true) */
|
|
61
61
|
subscribe?: boolean;
|
|
62
62
|
};
|
|
63
|
-
/** Extract
|
|
64
|
-
type InfiniteQueryInput<TInput> = Omit<TInput, 'cursor' | 'limit'>;
|
|
63
|
+
/** Extract user args without hook-owned pagination transport fields */
|
|
64
|
+
type InfiniteQueryInput<TInput> = Omit<TInput, 'cursor' | 'endCursor' | 'limit'>;
|
|
65
65
|
/** Extract item type from PaginationResult<T> */
|
|
66
66
|
type ExtractPaginatedItem<TOutput> = TOutput extends {
|
|
67
67
|
page: (infer T)[];
|
|
@@ -1429,7 +1429,7 @@ declare const getConvexQueryClientSingleton: ({
|
|
|
1429
1429
|
* Pagination state persisted in queryClient.
|
|
1430
1430
|
* Enables scroll restoration when navigating back to a paginated list.
|
|
1431
1431
|
*
|
|
1432
|
-
* Uses flat { cursor, limit } structure like tRPC.
|
|
1432
|
+
* Uses flat { cursor, endCursor, limit } structure like tRPC.
|
|
1433
1433
|
*/
|
|
1434
1434
|
type PaginationState = {
|
|
1435
1435
|
id: number;
|
|
@@ -1438,13 +1438,12 @@ type PaginationState = {
|
|
|
1438
1438
|
queries: Record<number, {
|
|
1439
1439
|
/** Flat pagination args - tRPC style */args: Record<string, unknown> & {
|
|
1440
1440
|
cursor: string | null;
|
|
1441
|
+
endCursor?: string | null;
|
|
1441
1442
|
limit?: number; /** Internal pagination ID for subscription management */
|
|
1442
1443
|
__paginationId?: number;
|
|
1443
1444
|
};
|
|
1444
|
-
endCursor?: string | null;
|
|
1445
1445
|
}>;
|
|
1446
|
-
version: number;
|
|
1447
|
-
autoRecoveryAttempted?: string;
|
|
1446
|
+
version: number;
|
|
1448
1447
|
};
|
|
1449
1448
|
type PaginationStatus = 'CanLoadMore' | 'Exhausted' | 'LoadingFirstPage' | 'LoadingMore';
|
|
1450
1449
|
/** Return type for infinite query hooks */
|
package/dist/solid/index.js
CHANGED
|
@@ -2935,6 +2935,12 @@ const getConvexQueryClientSingleton = ({ authStore, convex, queryClient, symbolK
|
|
|
2935
2935
|
//#endregion
|
|
2936
2936
|
//#region src/internal/pagination.ts
|
|
2937
2937
|
const shouldSplitPaginationPage = (page, initialNumItems) => Boolean(page.splitCursor) && (page.pageStatus === "SplitRecommended" || page.pageStatus === "SplitRequired" || initialNumItems !== void 0 && page.page.length > initialNumItems * 2);
|
|
2938
|
+
const isInvalidPaginationCursor = (error) => {
|
|
2939
|
+
if (error instanceof Error && error.message.includes("InvalidCursor")) return true;
|
|
2940
|
+
if (!error || typeof error !== "object" || !("data" in error)) return false;
|
|
2941
|
+
const data = error.data;
|
|
2942
|
+
return Boolean(data && typeof data === "object" && "isConvexSystemError" in data && data.isConvexSystemError === true && "paginationError" in data && data.paginationError === "InvalidCursor");
|
|
2943
|
+
};
|
|
2938
2944
|
|
|
2939
2945
|
//#endregion
|
|
2940
2946
|
//#region src/solid/create-queries-results.ts
|
|
@@ -3020,7 +3026,7 @@ const aggregatePages = (results, hasPlaceholderData) => {
|
|
|
3020
3026
|
error,
|
|
3021
3027
|
failureReason: error,
|
|
3022
3028
|
isError: results.some((r) => r.isError),
|
|
3023
|
-
isFetchNextPageError: results.
|
|
3029
|
+
isFetchNextPageError: results.slice(1).some((result) => result.isError),
|
|
3024
3030
|
isFetching,
|
|
3025
3031
|
isLoading: status === "LoadingFirstPage",
|
|
3026
3032
|
isPlaceholderData,
|
|
@@ -3030,72 +3036,18 @@ const aggregatePages = (results, hasPlaceholderData) => {
|
|
|
3030
3036
|
status
|
|
3031
3037
|
};
|
|
3032
3038
|
};
|
|
3033
|
-
/** Build a unique key for recovery attempt detection */
|
|
3034
|
-
const buildRecoveryKey = (pageKeys, page0Cursor, page0UpdatedAt) => JSON.stringify({
|
|
3035
|
-
pageKeys,
|
|
3036
|
-
page0Cursor,
|
|
3037
|
-
page0UpdatedAt
|
|
3038
|
-
});
|
|
3039
3039
|
/**
|
|
3040
3040
|
* Hook for auto-recovering from stale cursors after WebSocket reconnection.
|
|
3041
3041
|
*
|
|
3042
3042
|
* When Convex WebSocket reconnects, page 0 (cursor: null) resubscribes and
|
|
3043
3043
|
* gets fresh data. However, pages 1+ may have stale cursors that fail.
|
|
3044
3044
|
*
|
|
3045
|
-
* This hook
|
|
3046
|
-
* enough items to cover the lost pages, preserving the user's scroll position.
|
|
3045
|
+
* This hook discards the invalid cursor chain and restarts from page one.
|
|
3047
3046
|
*/
|
|
3048
|
-
const useStaleCursorRecovery = ({
|
|
3049
|
-
createEffect(on([
|
|
3050
|
-
() => combined.isFetchNextPageError,
|
|
3051
|
-
pageResults,
|
|
3052
|
-
() => state().pageKeys,
|
|
3053
|
-
() => state().queries,
|
|
3054
|
-
() => state().autoRecoveryAttempted,
|
|
3055
|
-
argsObject
|
|
3056
|
-
], () => {
|
|
3047
|
+
const useStaleCursorRecovery = ({ combined, pageResults, resetPagination }) => {
|
|
3048
|
+
createEffect(on([() => combined.isFetchNextPageError, pageResults], () => {
|
|
3057
3049
|
if (!combined.isFetchNextPageError) return;
|
|
3058
|
-
|
|
3059
|
-
const page0Result = results[0];
|
|
3060
|
-
const page0Data = page0Result?.data;
|
|
3061
|
-
const page0UpdatedAt = page0Result?.dataUpdatedAt ?? 0;
|
|
3062
|
-
const hasPage0Data = page0Data !== void 0 && !page0Result?.isError;
|
|
3063
|
-
const hasSubsequentErrors = results.slice(1).some((q) => q?.isError && !q?.isFetching);
|
|
3064
|
-
if (!hasPage0Data || !hasSubsequentErrors || !page0Data?.continueCursor) return;
|
|
3065
|
-
const currentState = state();
|
|
3066
|
-
const recoveryKey = buildRecoveryKey(currentState.pageKeys, page0Data.continueCursor, page0UpdatedAt);
|
|
3067
|
-
if (currentState.autoRecoveryAttempted === recoveryKey) return;
|
|
3068
|
-
const erroredPageKeys = currentState.pageKeys.filter((_, i) => i > 0 && results[i]?.isError);
|
|
3069
|
-
const itemsToRecover = erroredPageKeys.reduce((sum, key) => {
|
|
3070
|
-
return sum + (currentState.queries[key]?.args?.limit ?? limit ?? 20);
|
|
3071
|
-
}, 0);
|
|
3072
|
-
console.warn("[Pagination] Auto-recovering from stale cursors", {
|
|
3073
|
-
erroredPages: erroredPageKeys.length,
|
|
3074
|
-
itemsToRecover
|
|
3075
|
-
});
|
|
3076
|
-
setState((prev) => ({
|
|
3077
|
-
...prev,
|
|
3078
|
-
id: prev.id,
|
|
3079
|
-
nextPageKey: 2,
|
|
3080
|
-
pageKeys: [prev.pageKeys[0], 1],
|
|
3081
|
-
queries: {
|
|
3082
|
-
[prev.pageKeys[0]]: prev.queries[prev.pageKeys[0]],
|
|
3083
|
-
1: { args: {
|
|
3084
|
-
...argsObject(),
|
|
3085
|
-
cursor: page0Data.continueCursor,
|
|
3086
|
-
limit: Math.min(itemsToRecover + (limit ?? 20), 500),
|
|
3087
|
-
__paginationId: prev.id
|
|
3088
|
-
} }
|
|
3089
|
-
},
|
|
3090
|
-
version: prev.version + 1,
|
|
3091
|
-
autoRecoveryAttempted: recoveryKey
|
|
3092
|
-
}));
|
|
3093
|
-
}));
|
|
3094
|
-
createEffect(on([() => combined.status, () => state().autoRecoveryAttempted], () => {
|
|
3095
|
-
if ((combined.status === "CanLoadMore" || combined.status === "Exhausted") && state().autoRecoveryAttempted) setState((prev) => ({
|
|
3096
|
-
...prev,
|
|
3097
|
-
autoRecoveryAttempted: void 0
|
|
3098
|
-
}));
|
|
3050
|
+
if (pageResults().slice(1).some((result) => result?.isError && !result.isFetching && isInvalidPaginationCursor(result.error))) resetPagination();
|
|
3099
3051
|
}));
|
|
3100
3052
|
};
|
|
3101
3053
|
/**
|
|
@@ -3232,12 +3184,9 @@ const useInfiniteQueryInternal = (query, args, options) => {
|
|
|
3232
3184
|
const [combined, setCombined] = createStore(derive());
|
|
3233
3185
|
createRenderEffect(() => setCombined(derive()));
|
|
3234
3186
|
useStaleCursorRecovery({
|
|
3235
|
-
argsObject,
|
|
3236
3187
|
combined,
|
|
3237
|
-
limit,
|
|
3238
3188
|
pageResults,
|
|
3239
|
-
setState
|
|
3240
|
-
state
|
|
3189
|
+
resetPagination: () => setState(createInitialState())
|
|
3241
3190
|
});
|
|
3242
3191
|
createEffect(on([
|
|
3243
3192
|
pageResults,
|
|
@@ -3252,15 +3201,17 @@ const useInfiniteQueryInternal = (query, args, options) => {
|
|
|
3252
3201
|
const page = pageQuery.data;
|
|
3253
3202
|
const pageKey = state().pageKeys[i];
|
|
3254
3203
|
const pageState = state().queries[pageKey];
|
|
3255
|
-
if (shouldSplitPaginationPage(page, limit) && pageState &&
|
|
3204
|
+
if (shouldSplitPaginationPage(page, limit) && pageState && pageState.args.endCursor !== page.splitCursor) {
|
|
3256
3205
|
setState((prev) => {
|
|
3257
3206
|
const currentPageState = prev.queries[pageKey];
|
|
3258
|
-
if (!currentPageState || currentPageState.endCursor) return prev;
|
|
3207
|
+
if (!currentPageState || currentPageState.args.endCursor === page.splitCursor) return prev;
|
|
3259
3208
|
const newKey = prev.nextPageKey;
|
|
3260
3209
|
const splitCursor = page.splitCursor;
|
|
3210
|
+
const endCursor = currentPageState.args.endCursor ?? page.continueCursor;
|
|
3261
3211
|
const splitPageArgs = {
|
|
3262
3212
|
...argsObject(),
|
|
3263
3213
|
cursor: splitCursor,
|
|
3214
|
+
endCursor,
|
|
3264
3215
|
limit: currentPageState.args.limit,
|
|
3265
3216
|
__paginationId: prev.id
|
|
3266
3217
|
};
|
|
@@ -3275,7 +3226,10 @@ const useInfiniteQueryInternal = (query, args, options) => {
|
|
|
3275
3226
|
...prev.queries,
|
|
3276
3227
|
[pageKey]: {
|
|
3277
3228
|
...currentPageState,
|
|
3278
|
-
|
|
3229
|
+
args: {
|
|
3230
|
+
...currentPageState.args,
|
|
3231
|
+
endCursor: splitCursor
|
|
3232
|
+
}
|
|
3279
3233
|
},
|
|
3280
3234
|
[newKey]: { args: splitPageArgs }
|
|
3281
3235
|
}
|
|
@@ -148,8 +148,8 @@ type PaginationOpts = {
|
|
|
148
148
|
maximumRowsRead?: number;
|
|
149
149
|
maximumBytesRead?: number;
|
|
150
150
|
};
|
|
151
|
-
/** Extract
|
|
152
|
-
type InfiniteQueryInput<TInput> = Omit<TInput, 'cursor' | 'limit'>;
|
|
151
|
+
/** Extract user args without hook-owned pagination transport fields */
|
|
152
|
+
type InfiniteQueryInput<TInput> = Omit<TInput, 'cursor' | 'endCursor' | 'limit'>;
|
|
153
153
|
/** Extract item type from PaginationResult<T> */
|
|
154
154
|
type ExtractPaginatedItem<TOutput> = TOutput extends {
|
|
155
155
|
page: (infer T)[];
|