kitcn 0.32.2 → 0.33.1
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 +109 -0
- package/dist/aggregate/index.d.ts +2 -2
- package/dist/auth/generated/index.d.ts +1 -1
- package/dist/auth/index.d.ts +16 -16
- package/dist/auth/index.js +1 -1
- package/dist/auth/nextjs/index.d.ts +2 -2
- package/dist/auth/start/server/index.d.ts +2 -2
- package/dist/{builder-Cyd5nCxZ.js → builder-DDYTlmTB.js} +12 -3
- package/dist/caller-factory-C3pcbzo0.d.ts +140 -0
- package/dist/{capabilities-BJm_VSDT.d.ts → capabilities-Bxzoofl4.d.ts} +149 -9
- package/dist/crpc/index.d.ts +3 -2
- package/dist/{generated-contract-disabled-BRm1dNQE.d.ts → generated-contract-disabled-B_EaHGCP.d.ts} +33 -33
- package/dist/{http-types-BhhPZtwa.d.ts → http-types-8FBr10yl.d.ts} +3 -79
- package/dist/{middleware-BBS7oLtT.d.ts → middleware-D2hKJuSZ.d.ts} +1 -1
- package/dist/{middleware-D61Nm-iB.js → middleware-LvZov-hA.js} +1 -1
- package/dist/orm/aggregate-index/index.d.ts +1 -1
- package/dist/orm/aggregate-index/index.js +226 -96
- package/dist/orm/index.d.ts +2 -2
- package/dist/orm/index.js +364 -108
- package/dist/orm/migrations/index.d.ts +2 -2
- package/dist/plugins/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-kn-awLk1.d.ts} +12 -142
- package/dist/{query-context-D4z1CnDH.js → query-context-DQLv58LH.js} +34 -1
- package/dist/ratelimit/index.d.ts +2 -2
- package/dist/ratelimit/index.js +2 -2
- package/dist/react/index.d.ts +5 -6
- package/dist/react/index.js +24 -69
- package/dist/rsc/index.d.ts +4 -3
- package/dist/{schema-Bh7AmJwY.js → schema-BF4P0ZjS.js} +322 -1
- package/dist/server/index.d.ts +5 -4
- package/dist/server/index.js +2 -2
- package/dist/solid/index.d.ts +5 -6
- package/dist/solid/index.js +20 -66
- package/dist/transformer-BEkxlnss.d.ts +78 -0
- package/dist/{types-BXpu7xIU.d.ts → types-Cl0utsTL.d.ts} +4 -3
- package/dist/{where-clause-compiler-Dgf4lrO-.d.ts → where-clause-compiler-CoPVAVDO.d.ts} +136 -136
- package/package.json +1 -1
- package/skills/kitcn/SKILL.md +2 -1
- package/skills/kitcn/references/features/aggregates.md +13 -0
- package/skills/kitcn/references/features/auth-admin.md +1 -0
- package/skills/kitcn/references/features/orm.md +24 -4
- package/skills/kitcn/references/features/react.md +4 -5
- /package/dist/{context-utils-Cbv4r0AA.d.ts → context-utils-ax351iFc.d.ts} +0 -0
- /package/dist/{token-tlbNKQS0.d.ts → token-CZpDQUHd.d.ts} +0 -0
- /package/dist/{types-Bkeicpo6.d.ts → types-CzGsrLrY.d.ts} +0 -0
package/package.json
CHANGED
package/skills/kitcn/SKILL.md
CHANGED
|
@@ -34,7 +34,7 @@ Only remember these non-parity deltas:
|
|
|
34
34
|
2. No `z.void()` outputs; omit `.output(...)` for no-value mutations.
|
|
35
35
|
3. `.output(...)` parses the handler's value as-is and substitutes nothing: a handler must return the schema's *input* type, so `z.string().nullable()` needs an explicit `null` (`?? null`), not `undefined`. Model absent values as `.nullable()`, never a top-level `.optional()` — Convex wires `undefined` as `null` and cannot express top-level optionality, so `.output(z.string().optional())` publishes `v.string()` and the deployment rejects the `null` whenever the handler returns `undefined`. `.optional()` inside an object is fine. The low-level `returns:` option on `zCustomQuery`/`zCustomMutation`/`zCustomAction` differs — it substitutes `null` for `undefined` before parsing.
|
|
36
36
|
4. Stacked `.input(...)` calls merge input shapes.
|
|
37
|
-
5. `.paginated({ limit, item })` must be before `.query()` and
|
|
37
|
+
5. `.paginated({ limit, item })` must be before `.query()` and adds `input.cursor`, `input.endCursor`, and `input.limit`; pass all three to ORM cursor queries so live splits stay bounded.
|
|
38
38
|
6. Metadata is codegen’d onto `@convex/api` leaves (`api.namespace.fn.meta`) so never put secrets in `.meta(...)`; chaining `.meta(...)` is shallow merge and supports `defaultMeta`.
|
|
39
39
|
7. Auth metadata drives client behavior: `auth: "optional"` waits for auth load then runs, `auth: "required"` waits then skips when logged out.
|
|
40
40
|
8. `ctx.orm` enforces constraints + RLS; `ctx.db` bypasses them.
|
|
@@ -245,6 +245,7 @@ export const listProjects = authQuery
|
|
|
245
245
|
where: { ownerId: ctx.userId },
|
|
246
246
|
orderBy: { updatedAt: "desc" },
|
|
247
247
|
cursor: input.cursor,
|
|
248
|
+
endCursor: input.endCursor,
|
|
248
249
|
limit: input.limit,
|
|
249
250
|
})
|
|
250
251
|
);
|
|
@@ -58,6 +58,19 @@ const orders = convexTable(
|
|
|
58
58
|
|
|
59
59
|
After deploying, CLI runs `aggregateBackfill` automatically. Wait for `aggregateBackfillStatus` (an internal query) to report `READY`.
|
|
60
60
|
|
|
61
|
+
### Write costs
|
|
62
|
+
|
|
63
|
+
Bulk ORM statements reuse aggregate bucket/member reads within uninterrupted
|
|
64
|
+
statements: one bucket read per distinct tuple and one membership read per
|
|
65
|
+
document. User hooks, policy callbacks and statement exit end reuse, preserving
|
|
66
|
+
nested-mutation writes. Raw writer calls do not share cached rows.
|
|
67
|
+
|
|
68
|
+
Shared bucket/extrema writes fold within statements. Aggregate reads (including
|
|
69
|
+
returning relation counts) and user hook/policy entry flush pending writes;
|
|
70
|
+
callbacks suspend batching until they settle so nested functions see stored
|
|
71
|
+
writes. Reads/callbacks can increase flush count. Membership rows remain one
|
|
72
|
+
write per changed document.
|
|
73
|
+
|
|
61
74
|
### `count()` — O(1) No-Scan Counts
|
|
62
75
|
|
|
63
76
|
```ts
|
|
@@ -598,7 +598,9 @@ Per source:
|
|
|
598
598
|
|
|
599
599
|
- `index: { name, range }` anchors that source on its own range. It overrides
|
|
600
600
|
the chain-level `.withIndex(...)`; sources that omit it use the chain index.
|
|
601
|
-
- `where`
|
|
601
|
+
- `where` is compiled against the table's indexes like a `findMany` where. It
|
|
602
|
+
bounds the read when it can be lowered onto the index that source walks;
|
|
603
|
+
whatever no index covers is filtered after the read.
|
|
602
604
|
|
|
603
605
|
`interleaveBy` fields must be the trailing fields each source is already ordered
|
|
604
606
|
by, so every field before them has to be pinned with `eq` in that source's
|
|
@@ -607,8 +609,18 @@ fields — e.g. `by_author_likes` (authorId, numLikes) with `eq("authorId", ...)
|
|
|
607
609
|
merges with `numLikesAndType` (type, numLikes) with `eq("type", ...)` under
|
|
608
610
|
`interleaveBy(["numLikes"])`.
|
|
609
611
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
+
Whether a source `where` bounds the read depends on the index that source ends
|
|
613
|
+
up walking. With no index pinned it picks one, so `{ where: { status: "active" } }`
|
|
614
|
+
reads the `by_status` range. With a pinned index it may only narrow that same
|
|
615
|
+
index: `.withIndex("by_status")` plus `{ where: { status: "active" } }` narrows,
|
|
616
|
+
while `.withIndex("by_name")` plus the same `where` walks `by_name` and discards
|
|
617
|
+
the misses.
|
|
618
|
+
|
|
619
|
+
A pinned `range` is the source's scope, never a hint: a `where` alongside one
|
|
620
|
+
always filters after the read rather than widening it. Lowering also has to
|
|
621
|
+
preserve the merge, so a `where` is only lowered when the resulting order can
|
|
622
|
+
still supply `interleaveBy`. Anchor a source with `index: { name, range }`
|
|
623
|
+
whenever you need a specific range read.
|
|
612
624
|
|
|
613
625
|
### Pre-pagination transforms
|
|
614
626
|
|
|
@@ -630,6 +642,14 @@ const page = await ctx.orm.query.users
|
|
|
630
642
|
.paginate({ cursor: null, limit: 20 });
|
|
631
643
|
```
|
|
632
644
|
|
|
645
|
+
Children are read through an index that leads with the relation's foreign key.
|
|
646
|
+
A stage `where` rides that index when one extends it — `where: { numLikes: { gt: 10 } }`
|
|
647
|
+
on `posts` reads the `by_author_likes` (authorId, numLikes) range instead of
|
|
648
|
+
every post by the author. Children then arrive in that index's order, so a
|
|
649
|
+
lowered range field orders them ahead of creation time. Declare an index whose
|
|
650
|
+
fields are `(...foreign key, ...filtered fields)` for the stage filters you
|
|
651
|
+
page on.
|
|
652
|
+
|
|
633
653
|
See [Select Composition Limitations](#select-composition-limitations) in API Reference.
|
|
634
654
|
|
|
635
655
|
## Pagination Modes
|
|
@@ -675,7 +695,7 @@ const page = await ctx.orm.query.users.withIndex("by_status").findMany({
|
|
|
675
695
|
});
|
|
676
696
|
```
|
|
677
697
|
|
|
678
|
-
Falls back to a bounded scan (needs `maxScan`) when the probed index cannot supply the requested `orderBy`, or when
|
|
698
|
+
Falls back to a bounded scan (needs `maxScan`) when the probed index cannot supply the requested `orderBy`, or when a union wider than 64 ranges is asked for an `orderBy` that sorts across values, such as `createdAt`. Up to 64 ranges are read as one merged stream; a wider union is read one range after another, which keeps it index-bounded at any list length but can only produce the index's own order.
|
|
679
699
|
|
|
680
700
|
Without an `orderBy`, an index-union page is in the order of the index it walks — grouped by the probed value — not in creation order.
|
|
681
701
|
|
|
@@ -374,20 +374,19 @@ export const list = publicQuery
|
|
|
374
374
|
.input(z.object({ userId: z.string().optional() }))
|
|
375
375
|
.paginated({ limit: 20, item: SessionSchema })
|
|
376
376
|
.query(async ({ ctx, input }) => {
|
|
377
|
-
// input.cursor and input.limit auto-added
|
|
378
377
|
return ctx.orm.query.session.findMany({
|
|
379
378
|
where: input.userId ? { userId: input.userId } : undefined,
|
|
380
379
|
orderBy: { createdAt: 'desc' },
|
|
381
380
|
cursor: input.cursor,
|
|
381
|
+
endCursor: input.endCursor,
|
|
382
382
|
limit: input.limit,
|
|
383
383
|
});
|
|
384
|
-
// output auto-wrapped as { continueCursor, isDone, page }
|
|
385
384
|
});
|
|
386
385
|
```
|
|
387
386
|
|
|
388
387
|
`.paginated({ limit, item })`:
|
|
389
|
-
- Adds `cursor`
|
|
390
|
-
-
|
|
388
|
+
- Adds `cursor`, optional `endCursor`, and `limit` to input
|
|
389
|
+
- Accepts the full Convex page result, including `pageStatus` and `splitCursor`
|
|
391
390
|
- Must be called before `.query()`
|
|
392
391
|
|
|
393
392
|
### Return Value
|
|
@@ -414,7 +413,7 @@ const { data, isPlaceholderData } = useInfiniteQuery(
|
|
|
414
413
|
|
|
415
414
|
### Real-time & Error Recovery
|
|
416
415
|
|
|
417
|
-
Each page maintains its own WebSocket subscription.
|
|
416
|
+
Each page maintains its own WebSocket subscription. Split pages use `endCursor` to keep adjacent subscriptions bounded. An `InvalidCursor` on a loaded page resets the list cleanly to page 0. Pagination state persists in `queryClient` for scroll restoration.
|
|
418
417
|
|
|
419
418
|
---
|
|
420
419
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|