kitcn 0.33.6 → 0.33.8

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/aggregate/index.d.ts +1 -1
  3. package/dist/auth/client/index.d.ts +45 -21
  4. package/dist/auth/client/index.js +203 -111
  5. package/dist/auth/generated/index.d.ts +1 -1
  6. package/dist/auth/index.d.ts +16 -16
  7. package/dist/auth/nextjs/index.d.ts +3 -3
  8. package/dist/auth/nextjs/index.js +3 -2
  9. package/dist/auth/start/index.js +134 -2
  10. package/dist/auth/start/server/index.d.ts +1 -1
  11. package/dist/auth/start/server/index.js +1 -1
  12. package/dist/crpc/index.d.ts +2 -2
  13. package/dist/crpc/index.js +2 -2
  14. package/dist/{generated-contract-disabled-PdNGvNYP.d.ts → generated-contract-disabled-CFLQf8Wg.d.ts} +25 -25
  15. package/dist/orm/index.d.ts +1 -1
  16. package/dist/orm/migrations/index.d.ts +1 -1
  17. package/dist/{query-options-DGG93--5.js → query-options-YkFvau71.js} +6 -2
  18. package/dist/react/index.js +149 -140
  19. package/dist/rsc/index.d.ts +1 -1
  20. package/dist/rsc/index.js +1 -1
  21. package/dist/solid/index.js +4 -1
  22. package/dist/{token-tlbNKQS0.d.ts → token-COZD00dG.d.ts} +2 -1
  23. package/dist/{token-CgIvcEZX.js → token-CZbuEcTL.js} +13 -4
  24. package/dist/{auth-store-x3_wvhTR.js → token-gate-CEzbXArg.js} +178 -1
  25. package/dist/{types-C7JkpfeY.d.ts → types-Bb0kwteA.d.ts} +5 -1
  26. package/dist/{where-clause-compiler-BzAJnWt4.d.ts → where-clause-compiler-CTblNxLo.d.ts} +24 -24
  27. package/package.json +1 -1
  28. package/skills/kitcn/references/features/auth.md +26 -8
  29. package/skills/kitcn/references/features/react.md +5 -1
  30. package/skills/kitcn/references/setup/next.md +48 -1
@@ -64,6 +64,10 @@ declare function replaceUrlParam(url: string, params: Record<string, string>): s
64
64
  * Handles array values as multiple params with same key (like Hono).
65
65
  */
66
66
  declare function buildSearchParams(query: Record<string, string | string[]>): URLSearchParams;
67
+ declare const RECHECK_AUTHORIZATION: unique symbol;
68
+ declare const withAuthorizationRecheck: <T extends {
69
+ [key: string]: string | undefined;
70
+ }>(headers: T, recheck: () => boolean) => T;
67
71
  /**
68
72
  * Hono-style HTTP request executor.
69
73
  * Processes args in the same way as Hono's ClientRequestImpl.fetch().
@@ -210,4 +214,4 @@ type VanillaAction<T extends FunctionReference<'action'>> = {
210
214
  mutate: keyof FunctionArgs<T> extends never ? (args?: EmptyObject) => Promise<FunctionReturnType<T>> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T>) => Promise<FunctionReturnType<T>> : (args: FunctionArgs<T>) => Promise<FunctionReturnType<T>>;
211
215
  };
212
216
  //#endregion
213
- export { HttpInputArgs as A, ReservedMutationOptions as C, VanillaMutation as D, VanillaAction as E, replaceUrlParam as F, RESERVED_KEYS as M, buildSearchParams as N, HttpClientOptions as O, executeHttpRequest as P, ReservedInfiniteQueryOptions as S, StaticQueryOptsParam as T, IsPaginated as _, BaseInfiniteQueryOptsParam as a, PaginatedFnMeta as b, ConvexMutationKey as c, ConvexQueryMeta as d, EmptyObject as f, InfiniteQueryInput as g, FnMeta as h, BaseConvexQueryOptions as i, HttpProxyBaseOptions as j, HttpFormValue as k, ConvexQueryHookOptions as l, FUNC_REF_SYMBOL as m, BaseConvexActionOptions as n, ConvexActionKey as o, ExtractPaginatedItem as p, BaseConvexInfiniteQueryOptions as r, ConvexInfiniteQueryMeta as s, AuthType as t, ConvexQueryKey as u, Meta as v, ReservedQueryOptions as w, PaginationOpts as x, MutationVariables as y };
217
+ export { HttpInputArgs as A, ReservedMutationOptions as C, VanillaMutation as D, VanillaAction as E, executeHttpRequest as F, replaceUrlParam as I, withAuthorizationRecheck as L, RECHECK_AUTHORIZATION as M, RESERVED_KEYS as N, HttpClientOptions as O, buildSearchParams as P, ReservedInfiniteQueryOptions as S, StaticQueryOptsParam as T, IsPaginated as _, BaseInfiniteQueryOptsParam as a, PaginatedFnMeta as b, ConvexMutationKey as c, ConvexQueryMeta as d, EmptyObject as f, InfiniteQueryInput as g, FnMeta as h, BaseConvexQueryOptions as i, HttpProxyBaseOptions as j, HttpFormValue as k, ConvexQueryHookOptions as l, FUNC_REF_SYMBOL as m, BaseConvexActionOptions as n, ConvexActionKey as o, ExtractPaginatedItem as p, BaseConvexInfiniteQueryOptions as r, ConvexInfiniteQueryMeta as s, AuthType as t, ConvexQueryKey as u, Meta as v, ReservedQueryOptions as w, PaginationOpts as x, MutationVariables as y };
@@ -102,22 +102,22 @@ declare const migrationStorageTables: {
102
102
  fieldName: "status";
103
103
  };
104
104
  };
105
- direction: ConvexTextBuilderInitial<""> & {
105
+ cursor: ConvexTextBuilderInitial<""> & {
106
106
  _: {
107
107
  tableName: "migration_state";
108
108
  };
109
109
  } & {
110
110
  _: {
111
- fieldName: "direction";
111
+ fieldName: "cursor";
112
112
  };
113
113
  };
114
- cursor: ConvexTextBuilderInitial<""> & {
114
+ direction: ConvexTextBuilderInitial<""> & {
115
115
  _: {
116
116
  tableName: "migration_state";
117
117
  };
118
118
  } & {
119
119
  _: {
120
- fieldName: "cursor";
120
+ fieldName: "direction";
121
121
  };
122
122
  };
123
123
  migrationId: ConvexTextBuilderInitial<""> & {
@@ -1326,11 +1326,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
1326
1326
  readonly aggregate_extrema: ConvexTableWithColumns<{
1327
1327
  name: "aggregate_extrema";
1328
1328
  columns: {
1329
- value: ConvexCustomBuilderInitial<"", convex_values0.VAny<any, "required", string>> & {
1330
- _: {
1331
- $type: convex_values0.Value;
1332
- };
1333
- } & {
1329
+ count: ConvexNumberBuilderInitial<""> & {
1334
1330
  _: {
1335
1331
  notNull: true;
1336
1332
  };
@@ -1340,10 +1336,14 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
1340
1336
  };
1341
1337
  } & {
1342
1338
  _: {
1343
- fieldName: "value";
1339
+ fieldName: "count";
1344
1340
  };
1345
1341
  };
1346
- count: ConvexNumberBuilderInitial<""> & {
1342
+ value: ConvexCustomBuilderInitial<"", convex_values0.VAny<any, "required", string>> & {
1343
+ _: {
1344
+ $type: convex_values0.Value;
1345
+ };
1346
+ } & {
1347
1347
  _: {
1348
1348
  notNull: true;
1349
1349
  };
@@ -1353,7 +1353,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
1353
1353
  };
1354
1354
  } & {
1355
1355
  _: {
1356
- fieldName: "count";
1356
+ fieldName: "value";
1357
1357
  };
1358
1358
  };
1359
1359
  updatedAt: ConvexNumberBuilderInitial<""> & {
@@ -1596,26 +1596,26 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
1596
1596
  fieldName: "status";
1597
1597
  };
1598
1598
  };
1599
- kind: ConvexTextBuilderInitial<""> & {
1600
- _: {
1601
- notNull: true;
1602
- };
1603
- } & {
1599
+ cursor: ConvexTextBuilderInitial<""> & {
1604
1600
  _: {
1605
1601
  tableName: "aggregate_state";
1606
1602
  };
1607
1603
  } & {
1608
1604
  _: {
1609
- fieldName: "kind";
1605
+ fieldName: "cursor";
1610
1606
  };
1611
1607
  };
1612
- cursor: ConvexTextBuilderInitial<""> & {
1608
+ kind: ConvexTextBuilderInitial<""> & {
1609
+ _: {
1610
+ notNull: true;
1611
+ };
1612
+ } & {
1613
1613
  _: {
1614
1614
  tableName: "aggregate_state";
1615
1615
  };
1616
1616
  } & {
1617
1617
  _: {
1618
- fieldName: "cursor";
1618
+ fieldName: "kind";
1619
1619
  };
1620
1620
  };
1621
1621
  processed: ConvexNumberBuilderInitial<""> & {
@@ -1751,22 +1751,22 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
1751
1751
  fieldName: "status";
1752
1752
  };
1753
1753
  };
1754
- direction: ConvexTextBuilderInitial<""> & {
1754
+ cursor: ConvexTextBuilderInitial<""> & {
1755
1755
  _: {
1756
1756
  tableName: "migration_state";
1757
1757
  };
1758
1758
  } & {
1759
1759
  _: {
1760
- fieldName: "direction";
1760
+ fieldName: "cursor";
1761
1761
  };
1762
1762
  };
1763
- cursor: ConvexTextBuilderInitial<""> & {
1763
+ direction: ConvexTextBuilderInitial<""> & {
1764
1764
  _: {
1765
1765
  tableName: "migration_state";
1766
1766
  };
1767
1767
  } & {
1768
1768
  _: {
1769
- fieldName: "cursor";
1769
+ fieldName: "direction";
1770
1770
  };
1771
1771
  };
1772
1772
  migrationId: ConvexTextBuilderInitial<""> & {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitcn",
3
- "version": "0.33.6",
3
+ "version": "0.33.8",
4
4
  "description": "kitcn - React Query integration and CLI tools for Convex",
5
5
  "keywords": [
6
6
  "convex",
@@ -363,7 +363,7 @@ All from `kitcn/react`:
363
363
  |------|---------|-------------|
364
364
  | `useAuth()` | `{ hasSession, isAuthenticated, isLoading }` | Full auth state |
365
365
  | `useMaybeAuth()` | `boolean` | Has token (optimistic, may not be verified) |
366
- | `useIsAuth()` | `boolean` | Server-verified authentication |
366
+ | `useIsAuth()` | `boolean` | Server-verified authentication (with `optimisticAuth`, also during the optimistic window) |
367
367
  | `useAuthGuard()` | `() => boolean` | Guard mutations, returns true if blocked |
368
368
  | `useConvexAuthRecovery()` | `{ recover, status, error }` | Rebind Convex auth after a transient token failure |
369
369
 
@@ -389,7 +389,7 @@ All from `kitcn/react`:
389
389
  | Component | Renders when |
390
390
  |-----------|-------------|
391
391
  | `MaybeAuthenticated` | Has session token (optimistic) |
392
- | `Authenticated` | Server-verified authenticated |
392
+ | `Authenticated` | Server-verified authenticated (with `optimisticAuth`, also during the optimistic window) |
393
393
  | `MaybeUnauthenticated` | No session token (optimistic) |
394
394
  | `Unauthenticated` | Server-verified not authenticated |
395
395
 
@@ -414,16 +414,34 @@ All from `kitcn/react`:
414
414
  ```
415
415
 
416
416
  `optimisticAuth` only opens auth-bound query gates for a held, unexpired JWT;
417
- expired, opaque, and refused tokens stay closed. Enable
417
+ expired, opaque, and refused tokens stay closed. The window ends at the Convex
418
+ client's first auth result; use one `optimisticAuth` setting per client; no
419
+ optimism over a client the Start loader authenticated. Enable
418
420
  `onTokenIdentityChange` to refuse a JWT whose `sub` or `sessionId` differs from
419
- the document identity before Convex or HTTP sees it. The client closes before
420
- the callback runs, so reload the document there.
421
+ the document identity (whatever its `exp`) before Convex, HTTP or the Start
422
+ loader sees it. On a trip, every mounted provider hands out no token and
423
+ publishes unauthenticated; each guarded one closes its client, then calls the
424
+ callback once, so reload the document there. Browser only, page-wide: later
425
+ providers start tripped, and a guarded one that mounts or shows again on a
426
+ tripped page also closes its client and calls the callback once. Enabling the
427
+ guard on a tripped page delivers that close and callback once too; sign-in
428
+ mutations fail with `TOKEN_IDENTITY_CHANGED`.
421
429
 
422
430
  For multiple provider mounts, pass `tokenIdentityBaseline` as
423
- `sub|sessionId`, or a getter returning the document's current identity. The
424
- getter is checked for every admission, cached tokens included.
431
+ `sub|sessionId`, or a getter returning the document's current identity. Every
432
+ admission (SSR, fresh and cached tokens, sign-in, HTTP, Start loader) binds a
433
+ token to the page identity, the provider's own baseline and every mounted
434
+ provider's current getter answer; an opaque session token is only exchanged,
435
+ never handed to Convex. Held tokens are reconciled when a provider joins the
436
+ page and at every admission. A page that never enables the guard is
437
+ unchanged; once a guarded provider establishes the page identity it persists
438
+ until reload, binding every provider and the Start loader, even after that
439
+ provider unmounts. Two kitcn versions or revisions on one page (dev HMR
440
+ across revisions included) are unsupported: no shared page identity until
441
+ reload.
425
442
  `onTokenIdentityAdmitted(token)` observes admitted JWTs so the app can update
426
- that shared baseline. All three identity options require
443
+ that shared baseline. Admission rechecks the baseline after the callback before
444
+ publishing or handing out the token. All three identity options require
427
445
  `onTokenIdentityChange`.
428
446
 
429
447
  For `@convex-dev/auth` (React Native):
@@ -539,7 +539,11 @@ export const { createContext, createCaller, handler } = convexBetterAuth({
539
539
  | `createCaller` | Server-side caller factory |
540
540
  | `handler` | Next.js API route handler (`export const { GET, POST, OPTIONS } = handler;`) |
541
541
 
542
- Options: `api`, `convexSiteUrl`, `auth.jwtCache` (default true), `auth.isUnauthorized`.
542
+ Options: `api`, `convexSiteUrl`, `auth.jwtCache` (boolean or `{ now }`, default true),
543
+ `auth.expirationToleranceSeconds` (default 60), `auth.isUnauthorized`.
544
+ `now` returns finite Unix seconds or a promise of seconds. For Next partial
545
+ prefetching and request-time versus private-cache clocks, follow
546
+ [Next setup](../setup/next.md#8a4-jwt-cache-and-partial-prefetching).
543
547
 
544
548
  ### Client Provider with Auth
545
549
 
@@ -98,7 +98,54 @@ export function HydrateClient({ children }: { children: React.ReactNode }) {
98
98
  }
99
99
  ```
100
100
 
101
- ### 8.A.4 Pass server token to provider
101
+ ### 8.A.4 JWT cache and partial prefetching
102
+
103
+ With Next 16 `cacheComponents` and `partialPrefetching`, the default JWT expiry
104
+ clock can trigger a Blocking Route error even after `await headers()`. The
105
+ app owns clock timing. For request-time contexts, configure the server factory:
106
+
107
+ ```ts
108
+ import { connection } from 'next/server';
109
+
110
+ export const { createContext, createCaller, handler } = convexBetterAuth({
111
+ api,
112
+ convexSiteUrl: process.env.NEXT_PUBLIC_CONVEX_SITE_URL!,
113
+ auth: {
114
+ jwtCache: {
115
+ now: async () => {
116
+ await connection();
117
+ return Math.floor(Date.now() / 1000);
118
+ },
119
+ },
120
+ },
121
+ });
122
+ ```
123
+
124
+ `auth.jwtCache` accepts a boolean or `{ now?: () => number | Promise<number> }`.
125
+ The clock returns finite **Unix seconds**, not milliseconds. The reader awaits
126
+ it only for a decoded cached JWT with an expiry. Disabled caching, forced
127
+ refresh, missing/malformed cookies, and absent expiry bypass the hook.
128
+ `auth.expirationToleranceSeconds` remains a sibling option (default 60).
129
+ Clock throws/rejections propagate unchanged; `NaN` and infinities are rejected.
130
+
131
+ Keep `await headers()` in the RSC context creator. Put request-time token reads
132
+ under `Suspense`, including a provider or route gate that awaits `caller.getToken()`.
133
+ For `'use cache: private'`, use a separate factory with the default or a sync
134
+ clock; **never call `connection()` inside private cache**. A private token helper
135
+ can use `cacheLife({ stale: 30 })`, read headers, create that context, and return
136
+ `context.token`. A token-blocking layout must defer its token-dependent subtree
137
+ with `Suspense`, including when awaiting a private-cache helper. Private caching
138
+ allows the clock read but does not make runtime auth data static.
139
+
140
+ `auth: { jwtCache: false }` avoids the cookie expiry clock but fetches a token
141
+ on every context creation. Kitcn does not import Next, detect render stages, or
142
+ suppress render aborts. An app that runs a `connection()` clock through TanStack
143
+ queries owns abort handling because recording a query failure can also read
144
+ `Date.now()`. Do not suppress ordinary auth failures.
145
+
146
+ Full examples: [Next.js JWT cache guidance](https://kitcn.dev/docs/nextjs#jwt-cache-and-partial-prefetching).
147
+
148
+ ### 8.A.5 Pass server token to provider
102
149
 
103
150
  ```tsx
104
151
  // app/(app)/layout.tsx