Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Jan 8, 2026

Summary by CodeRabbit

  • New Features

    • Public feeds pages across samples to view published posts
    • Signup pages for user registration
    • New server-side procedures (signUp, listPublicPosts) powering the UI
  • Chores

    • Updated sample app layouts and navigation (consistent header, logo, and main container)
    • Enabled additional API handler logging for improved diagnostics

✏️ Tip: You can customize this high-level summary in your review settings.

ymc9 and others added 25 commits December 12, 2025 15:14
merge dev to main (v3.0.0-beta.28)
merge dev to main (v3.0.0-beta.29)
merge dev to main (v3.0.0-beta.30)
merge dev to main (v3.0.0-beta.31)
merge dev to main (v3.0.0-beta.32)
merge dev to main (v3.0.0-beta.33)
merge dev to main (v3.0.0-beta.34)
merge dev to main (v3.0.0)
chore: update CI sample update script (#531)
Copilot AI review requested due to automatic review settings January 8, 2026 07:46
@claude
Copy link

claude bot commented Jan 8, 2026

Claude encountered an error —— View job


Reviewing PR: feat(cli): implement watch mode for generate

I'll provide a comprehensive review of this pull request focusing on code quality, best practices, potential bugs, performance considerations, security concerns, and test coverage.

Review Tasks:

  • Analyze core tanstack-query changes
  • Review ORM and server modifications
  • Examine sample application restructuring
  • Check for potential bugs and security issues
  • Assess performance implications
  • Evaluate test coverage needs
  • Provide constructive feedback and recommendations

@coderabbitai
Copy link

coderabbitai bot commented Jan 8, 2026

📝 Walkthrough

Walkthrough

Centralizes procedure routing in the TanStack Query clients by adding CUSTOM_PROC_ROUTE_NAME and refactoring React, Svelte, and Vue hook builders to use it; adjusts mutation callback sequencing and optimistic/invalidation flows for procedure calls. Adds procedures, models, pages, and schema updates across sample apps.

Changes

Cohort / File(s) Summary
TanStack Query framework integrations
packages/clients/tanstack-query/src/common/constants.ts, packages/clients/tanstack-query/src/react.ts, packages/clients/tanstack-query/src/svelte/index.svelte.ts, packages/clients/tanstack-query/src/vue.ts
Adds CUSTOM_PROC_ROUTE_NAME = '$procs'; refactors buildProcedureHooks() to be parameterless and routes procedure hooks through the constant; updates mutation/query internals to branch handling for custom procedures and adjust ordering of onMutate/onSuccess/onSettled, invalidation, and optimistic updates.
Server procedure export
packages/server/src/api/common/procedures.ts
Changes exported PROCEDURE_ROUTE_PREFIXES from a readonly tuple ['$procs'] to a readonly string literal '$procs' (type/signature change).
ORM error messaging
packages/orm/src/client/crud/operations/base.ts
Modifies existsNonUnique catch block to include underlying error text in thrown message.
Sample apps — DB client procedures & imports
samples/.../lib/db.ts, samples/nuxt/server/utils/db.ts, samples/sveltekit/src/lib/db.ts
Adds procedures object with signUp and listPublicPosts implementations to ZenStackClient initialization; updates SqliteDialect import paths. (See multiple sample paths under samples/next.js, samples/nuxt, samples/sveltekit.)
Sample schemas, models, and zmodel proxies
samples/shared/schema.zmodel, samples/.../zenstack/schema.ts, samples/.../zenstack/schema-lite.ts, samples/.../zenstack/schema.zmodel
Introduces User and Post models and adds procedures signUp(email: String): User and listPublicPosts(): Post[]; adds small proxy zmodel files referencing shared schema.
Sample UI — new pages and layout/navigation
samples/next.js/app/feeds/page.tsx, samples/next.js/app/signup/page.tsx, samples/next.js/app/layout.tsx, samples/next.js/app/page.tsx, samples/nuxt/app/pages/*.vue, samples/sveltekit/src/routes/*
Adds feeds and signup pages across Next/Nuxt/SvelteKit; updates layouts and home navigation to surface feeds/signup links; reorganizes UI structure and rendering (loading/error/empty states present).
Sample seed & wiring
samples/.../zenstack/seed.ts
Replaces local in-file client setup with imports from centralized db instances in multiple sample apps.
Sample type exports & input types
samples/.../zenstack/input.ts, samples/sveltekit/src/zenstack/input.ts, samples/nuxt/zenstack/input.ts
Exports new type aliases UserExistsArgs and PostExistsArgs; formatting/type declaration adjustments.
Logging option added to API handlers
samples/next.js/app/api/model/[...path]/route.ts, samples/nuxt/server/api/model/[...].ts
Passes log: ['debug', 'error'] to RPCApiHandler instantiation.
Misc formatting/ux tweaks
samples/nuxt/app/plugins/tanstack-query.ts, samples/sveltekit/src/app.d.ts, various small formatting and layout edits
Trailing commas, quoting, indentation, and minor UI/component structure changes across samples.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • custom procedures #551 — Centralizes TanStack Query procedure routing and alters buildProcedureHooks and procedure handling; strongly overlaps with CUSTOM_PROC_ROUTE_NAME changes.
  • feat(tanstack): migrate vue query #365 — Modifies Vue integration and procedure hook behavior in packages/clients/tanstack-query/src/vue.ts, overlapping mutation/query wiring changes.
  • feat(tanstack): migrate svelte query #366 — Updates framework integrations (React/Vue/Svelte) for procedure hooks and internal mutation flows, matching files changed here.

Poem

🐰 I dug a little constant in the ground,
now $procs is found and neatly bound.
Signup hops in, feeds flutter and play,
callbacks ordered, hoppity hooray! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title claims to implement watch mode for generate command, but the changeset focuses on refactoring procedure hooks and adding sample pages/procedures. Update the title to reflect the actual changes, such as 'refactor: centralize custom procedure routing and add sample pages' or similar.
Docstring Coverage ⚠️ Warning Docstring coverage is 46.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6d58c5 and ecebbe5.

📒 Files selected for processing (1)
  • samples/sveltekit/src/routes/+layout.svelte
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to **/*.zmodel : Always run `zenstack generate` after modifying ZModel schemas
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Implement plugin hooks at ORM, Kysely, and entity mutation levels for query interception and customization
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build-test (22.x, postgresql)
  • GitHub Check: build-test (22.x, sqlite)
🔇 Additional comments (3)
samples/sveltekit/src/routes/+layout.svelte (3)

2-6: LGTM: Import formatting updates.

The standardization to double quotes is a consistent code style improvement with no functional impact.


10-14: LGTM: QueryClient configuration.

The browser-gated query enablement is appropriate for SvelteKit's SSR environment.


28-28: The SvelteKit logo image file exists at samples/sveltekit/static/svelte.png and will be properly served as /svelte.png in the layout. No issues detected.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link

claude bot commented Jan 8, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds custom procedure support to the ZenStack ORM framework and updates sample applications to demonstrate this feature. Despite the title mentioning "watch mode for generate", the changes actually focus on implementing and showcasing custom procedures across different framework integrations (Next.js, Nuxt, SvelteKit).

Key Changes:

  • Added procedures definition support to schema files (signUp mutation and listPublicPosts query)
  • Implemented procedure hooks in TanStack Query clients for React, Vue, and Svelte
  • Updated sample applications with new pages demonstrating procedure usage (/signup and /feeds routes)
  • Introduced CUSTOM_PROC_ROUTE_NAME constant for consistent procedure routing
  • Modified dialect imports to use @zenstackhq/orm/dialects/sqlite (partially - not in SvelteKit)

Reviewed changes

Copilot reviewed 40 out of 44 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
samples/shared/schema.zmodel Added shared schema with procedure definitions (signUp, listPublicPosts)
samples/*/zenstack/schema.ts Generated schema files with procedures metadata
samples/*/zenstack/schema-lite.ts Generated lite schema files with procedures metadata
samples/*/zenstack/input.ts Added ExistsArgs type exports with formatting improvements
samples/*/lib/db.ts or server/utils/db.ts Added procedure implementations
samples//app/pages/signup. or routes/signup/* New signup pages using procedure mutations
samples//app/pages/feeds. or routes/feeds/* New feeds pages using procedure queries
samples//app/layout. or routes/+layout.svelte Restructured layout to wrap all pages
packages/server/src/api/common/procedures.ts Changed PROCEDURE_ROUTE_PREFIXES from array to string constant
packages/orm/src/client/crud/operations/base.ts Modified error message formatting and code formatting
packages/clients/tanstack-query/src/*.ts Added CUSTOM_PROC_ROUTE_NAME constant and conditional optimistic update logic

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@claude
Copy link

claude bot commented Jan 8, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/orm/src/client/crud/operations/base.ts (1)

150-174: Error message includes stringified database error which may leak sensitive information to clients.

The error message Failed to execute query: ${err} is exposed via API responses (in both RPC and REST endpoints). The stringified error ${err} could contain database-specific details such as connection strings, schema names, or constraint violations. Instead, use a generic message and reserve detailed error information for server-side logging only.

🤖 Fix all issues with AI agents
In @packages/clients/tanstack-query/src/svelte/index.svelte.ts:
- Around line 579-580: The @ts-ignore comments are hiding a type mismatch
between useQueryClient() and the functions
invalidateQueriesMatchingPredicate/getAllQueries; fix by giving useQueryClient()
(or the local queryClient variable) the correct QueryClient generic type from
TanStack (or import the QueryClient type from
'@tanstack/query-core'/@tanstack/query-core/build/lib/types as used in Vue)
and/or narrow queryClient via an explicit typed cast to QueryClient before
calling invalidateQueriesMatchingPredicate and getAllQueries, and update the
predicate parameter types to match the Vue signature so you can remove the three
@ts-ignore lines around useQueryClient(), invalidateQueriesMatchingPredicate,
and getAllQueries.

In @samples/next.js/lib/db.ts:
- Around line 10-14: The signUp procedure currently spreads all args into
client.user.create (procedures.signUp using client.user.create and args), which
allows clients to set unintended fields; fix this by validating and whitelisting
fields before creating the user—either add a schema check (e.g., Zod/validation
function) or explicitly destructure only allowed properties (email, password,
name, etc.) from args, reject or strip any extra keys, and use the
validated/whitelisted object in client.user.create. Ensure the validation occurs
inside procedures.signUp and returns a clear error for invalid input.
- Line 3: The sample imports SqliteDialect via an indirect re-export from
@zenstackhq/orm/dialects/sqlite; change the import to pull SqliteDialect
directly from the kysely package instead (replace the import that references
@zenstackhq/orm/dialects/sqlite with one that imports SqliteDialect from
'kysely') so the sample relies on the public Kysely API rather than an
undocumented internal path.

In @samples/nuxt/app/pages/index.vue:
- Around line 149-151: The template accesses post.author.name unguarded which
can throw if author is null; update the rendering to only read name when author
exists (e.g., guard with v-if="post.author && !post.$optimistic" or use optional
chaining / a fallback like post.author?.name || 'Unknown') so the <p> block
referencing post.author.name is skipped or shows a safe fallback when author is
null.
- Around line 36-54: In onCreatePost, remove the console.log call and replace
the non-null assertion when picking a random user with a safety check: first
ensure users.value is an array with length > 0, then pick a random index with
Math.floor(Math.random() * users.value.length) and guard against undefined
before using forUser.id; if no users exist, return early or surface an error
instead of proceeding to createPost.mutate.

In @samples/nuxt/server/utils/db.ts:
- Around line 10-14: The signUp procedure currently spreads args directly into
client.user.create (signUp) which lets callers set arbitrary User fields;
replace this by validating/whitelisting allowed signup fields before calling
client.user.create (e.g., explicitly pick only safe fields like email, password,
name) or run args through a schema validator (e.g., Zod/validator) and pass the
validated object to client.user.create; update the signUp procedure to use the
validated/allowlisted payload instead of spreading args to prevent setting
admin/role/internal fields.

In @samples/sveltekit/src/lib/db.ts:
- Around line 10-14: The signUp procedure currently spreads all args into
client.user.create which can let callers set unintended fields; change
procedures.signUp to whitelist and validate allowed fields (e.g., only accept
email, name, password) rather than spreading args, reject or strip any extra
properties, and perform server-side checks (type/format/required) before calling
client.user.create; reference the signUp procedure and client.user.create to
locate where to implement explicit field selection and validation or integrate a
validation schema (e.g., Zod) to enforce the allowed input shape.

In @samples/sveltekit/src/routes/+layout.svelte:
- Around line 24-33: The img tag for the Svelte logo declares width="100"
height="20" which distorts the portrait 429x513 source; update the <img
src="/svelte.png" ...> attributes to preserve aspect ratio (e.g., width="100"
height="120" or set width="100" and height="auto" / remove the fixed height) so
the rendered dimensions match the source aspect ratio and avoid distortion.
🧹 Nitpick comments (10)
packages/server/src/api/common/procedures.ts (1)

4-4: Naming inconsistency: PROCEDURE_ROUTE_PREFIXES (plural) holds a single string value.

The variable name uses the plural form "PREFIXES" but contains a single string '$procs'. Consider renaming to PROCEDURE_ROUTE_PREFIX (singular) for clarity and consistency with the client-side equivalent CUSTOM_PROC_ROUTE_NAME.

samples/next.js/app/api/model/[...path]/route.ts (1)

7-7: Debug logging added for development.

The addition of log: ['debug', 'error'] is helpful for debugging during development. For production deployments, you may want to adjust the log level to reduce verbosity (e.g., only 'error' or 'warn').

samples/sveltekit/src/lib/db.ts (1)

15-23: Consider adding pagination to prevent performance issues.

The listPublicPosts query has no limit or pagination, which could return large datasets and cause performance/memory issues as the post count grows.

⚡ Proposed fix to add pagination support
-    listPublicPosts: ({ client }) =>
+    listPublicPosts: ({ client, args }) => {
+      const { take = 50, skip = 0 } = args as { take?: number; skip?: number };
       return client.post.findMany({
         where: {
           published: true,
         },
         orderBy: {
           updatedAt: "desc",
         },
+        take,
+        skip,
-      }),
+      });
+    },
samples/next.js/lib/db.ts (2)

15-23: Consider adding pagination to prevent performance issues.

The listPublicPosts query has no limit or pagination, which could return large datasets and cause performance/memory issues as the post count grows. This is the same issue present in samples/sveltekit/src/lib/db.ts.

⚡ Proposed fix to add pagination support
-        listPublicPosts: ({ client }) =>
+        listPublicPosts: ({ client, args }) => {
+            const { take = 50, skip = 0 } = args as { take?: number; skip?: number };
+            return client.post.findMany({
                 where: {
                     published: true,
                 },
                 orderBy: {
                     updatedAt: 'desc',
                 },
-            }),
+                take,
+                skip,
+            });
+        },

10-24: Consider extracting duplicated procedure implementations to a shared utility.

The procedures block is duplicated identically across three samples (next.js, sveltekit, nuxt). Consider extracting these common procedure implementations to a shared utility in samples/shared/ to reduce duplication and maintain consistency.

Example structure:

// samples/shared/procedures.ts
export const commonProcedures = {
  signUp: ({ client, args }: { client: any; args: any }) => {
    const { email, name } = args as { email: string; name?: string };
    return client.user.create({ data: { email, name } });
  },
  listPublicPosts: ({ client, args }: { client: any; args: any }) => {
    const { take = 50, skip = 0 } = args as { take?: number; skip?: number };
    return client.post.findMany({
      where: { published: true },
      orderBy: { updatedAt: 'desc' },
      take,
      skip,
    });
  },
};
samples/next.js/app/signup/page.tsx (1)

35-84: Well-implemented UI with good accessibility practices.

The form rendering is solid with proper semantic HTML, loading states, and dark mode support. Consider adding aria-live="polite" to the success/error message divs for better screen reader support.

♿ Optional: Enhance accessibility with aria-live regions
             {successMessage && (
-                <div className="w-full p-4 rounded-md bg-green-50 border border-green-200 text-green-800 dark:bg-green-900/20 dark:border-green-800 dark:text-green-400">
+                <div role="status" aria-live="polite" className="w-full p-4 rounded-md bg-green-50 border border-green-200 text-green-800 dark:bg-green-900/20 dark:border-green-800 dark:text-green-400">
                     {successMessage}
                 </div>
             )}

             {errorMessage && (
-                <div className="w-full p-4 rounded-md bg-red-50 border border-red-200 text-red-800 dark:bg-red-900/20 dark:border-red-800 dark:text-red-400">
+                <div role="alert" aria-live="assertive" className="w-full p-4 rounded-md bg-red-50 border border-red-200 text-red-800 dark:bg-red-900/20 dark:border-red-800 dark:text-red-400">
                     {errorMessage}
                 </div>
             )}
samples/next.js/app/feeds/page.tsx (1)

7-9: Query setup is correct for the demo use case.

The useQuery() call properly destructures the TanStack Query result. For production use with potentially large datasets, consider implementing pagination or infinite scroll patterns.

samples/sveltekit/src/routes/+layout.svelte (1)

19-21: Improve formatting and follow Svelte conventions.

The svelte:head tag formatting is unconventional and may cause readability issues. Additionally, the href attribute unnecessarily quotes the interpolation expression.

♻️ Proposed formatting improvement
-<svelte:head
-  ><link rel="icon" href="{favicon}"
-/></svelte:head>
+<svelte:head>
+  <link rel="icon" href={favicon} />
+</svelte:head>
samples/sveltekit/src/routes/feeds/+page.svelte (1)

21-35: Consider using {:else if} for mutually exclusive states.

The current implementation uses separate {#if} blocks for loading, error, and empty states. While functionally correct, using {:else if} would make the mutual exclusivity clearer and prevent potential edge cases where multiple states could render simultaneously.

♻️ Suggested refactor for clearer state handling
-{#if isLoading}
-	<div class="text-gray-600 dark:text-gray-400">Loading public posts...</div>
-{/if}
-
-{#if error}
+{#if isLoading}
+	<div class="text-gray-600 dark:text-gray-400">Loading public posts...</div>
+{:else if error}
 	<div
 		class="w-full p-4 rounded-md bg-red-50 border border-red-200 text-red-800 dark:bg-red-900/20 dark:border-red-800 dark:text-red-400"
 	>
 		Error loading posts: {error instanceof Error ? error.message : 'Unknown error'}
 	</div>
-{/if}
-
-{#if !isLoading && !error && posts && posts.length === 0}
+{:else if posts && posts.length === 0}
 	<div class="text-gray-600 dark:text-gray-400">No public posts available yet.</div>
+{:else if posts && posts.length > 0}
+	<!-- posts list here -->
 {/if}
samples/sveltekit/src/routes/+page.svelte (1)

147-159: Consider adding accessible labels to action buttons.

The Delete and Publish buttons use generic text without context for screen readers. Consider adding aria-label attributes to improve accessibility.

♻️ Add aria-labels for better accessibility
 <button
 	class="rounded-md px-2 py-1 text-white cursor-pointer underline text-xs"
 	onclick={() => onDeletePost(post.id)}
+	aria-label={`Delete post: ${post.title}`}
 >
 	Delete
 </button>
 <button
 	class="rounded-md px-2 py-1 text-white cursor-pointer underline text-xs"
 	onclick={() => onTogglePublishPost(post)}
+	aria-label={`${post.published ? 'Unpublish' : 'Publish'} post: ${post.title}`}
 >
 	{post.published ? 'Unpublish' : 'Publish'}
 </button>
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2172614 and b6d58c5.

📒 Files selected for processing (44)
  • packages/clients/tanstack-query/src/common/constants.ts
  • packages/clients/tanstack-query/src/react.ts
  • packages/clients/tanstack-query/src/svelte/index.svelte.ts
  • packages/clients/tanstack-query/src/vue.ts
  • packages/orm/src/client/crud/operations/base.ts
  • packages/server/src/api/common/procedures.ts
  • samples/next.js/app/api/model/[...path]/route.ts
  • samples/next.js/app/feeds/page.tsx
  • samples/next.js/app/layout.tsx
  • samples/next.js/app/page.tsx
  • samples/next.js/app/signup/page.tsx
  • samples/next.js/lib/db.ts
  • samples/next.js/zenstack/input.ts
  • samples/next.js/zenstack/schema-lite.ts
  • samples/next.js/zenstack/schema.ts
  • samples/next.js/zenstack/schema.zmodel
  • samples/next.js/zenstack/schema.zmodel
  • samples/next.js/zenstack/seed.ts
  • samples/nuxt/app/app.vue
  • samples/nuxt/app/layouts/default.vue
  • samples/nuxt/app/pages/feeds.vue
  • samples/nuxt/app/pages/index.vue
  • samples/nuxt/app/pages/signup.vue
  • samples/nuxt/app/plugins/tanstack-query.ts
  • samples/nuxt/server/api/model/[...].ts
  • samples/nuxt/server/utils/db.ts
  • samples/nuxt/zenstack/input.ts
  • samples/nuxt/zenstack/schema-lite.ts
  • samples/nuxt/zenstack/schema.ts
  • samples/nuxt/zenstack/schema.zmodel
  • samples/nuxt/zenstack/schema.zmodel
  • samples/nuxt/zenstack/seed.ts
  • samples/shared/schema.zmodel
  • samples/sveltekit/src/app.d.ts
  • samples/sveltekit/src/lib/db.ts
  • samples/sveltekit/src/routes/+layout.svelte
  • samples/sveltekit/src/routes/+page.svelte
  • samples/sveltekit/src/routes/feeds/+page.svelte
  • samples/sveltekit/src/routes/signup/+page.svelte
  • samples/sveltekit/src/zenstack/input.ts
  • samples/sveltekit/src/zenstack/schema-lite.ts
  • samples/sveltekit/src/zenstack/schema.ts
  • samples/sveltekit/src/zenstack/schema.zmodel
  • samples/sveltekit/src/zenstack/schema.zmodel
🧰 Additional context used
📓 Path-based instructions (1)
**/*.zmodel

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.zmodel: Always run zenstack generate after modifying ZModel schemas
ZModel schema files should define database structure and policies that compile to TypeScript via zenstack generate

Files:

  • samples/nuxt/zenstack/schema.zmodel
  • samples/sveltekit/src/zenstack/schema.zmodel
  • samples/next.js/zenstack/schema.zmodel
  • samples/shared/schema.zmodel
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to **/*.zmodel : Always run `zenstack generate` after modifying ZModel schemas
📚 Learning: 2025-12-30T15:07:06.254Z
Learnt from: mwillbanks
Repo: zenstackhq/zenstack-v3 PR: 550
File: packages/orm/src/client/crud/operations/base.ts:158-159
Timestamp: 2025-12-30T15:07:06.254Z
Learning: Do not use ts-expect-error in production code within the zenstackhq/zenstack-v3 repo (e.g., packages/*). Use explicit type annotations, targeted type assertions, or refactor to resolve the type error. ts-expect-error may be acceptable only in test files for stubbing or temporary silencing. Ensure production code is type-safe and maintainable.

Applied to files:

  • packages/clients/tanstack-query/src/common/constants.ts
  • packages/orm/src/client/crud/operations/base.ts
  • packages/server/src/api/common/procedures.ts
  • packages/clients/tanstack-query/src/react.ts
  • packages/clients/tanstack-query/src/svelte/index.svelte.ts
  • packages/clients/tanstack-query/src/vue.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to **/*.zmodel : ZModel schema files should define database structure and policies that compile to TypeScript via `zenstack generate`

Applied to files:

  • samples/nuxt/zenstack/schema.ts
  • samples/next.js/zenstack/schema.ts
  • samples/nuxt/zenstack/schema-lite.ts
  • samples/next.js/lib/db.ts
  • samples/next.js/zenstack/seed.ts
  • samples/next.js/zenstack/schema-lite.ts
  • samples/nuxt/server/utils/db.ts
  • samples/sveltekit/src/zenstack/input.ts
  • samples/nuxt/zenstack/seed.ts
  • samples/nuxt/zenstack/input.ts
  • samples/shared/schema.zmodel
  • samples/next.js/zenstack/input.ts
  • samples/sveltekit/src/zenstack/schema-lite.ts
  • samples/sveltekit/src/zenstack/schema.ts
📚 Learning: 2025-10-21T16:09:31.218Z
Learnt from: ymc9
Repo: zenstackhq/zenstack-v3 PR: 319
File: packages/runtime/src/client/executor/zenstack-query-executor.ts:63-72
Timestamp: 2025-10-21T16:09:31.218Z
Learning: In ZenStack, TypeDefs can be inherited by models. When a TypeDef contains fields with `map` attributes, those mapped field names need to be processed by the QueryNameMapper since they become part of the inheriting model's schema. Therefore, when checking if a schema has mapped names (e.g., in `schemaHasMappedNames`), both `schema.models` and `schema.typeDefs` must be inspected for `@map` and `map` attributes.

Applied to files:

  • samples/next.js/zenstack/schema.ts
  • samples/next.js/zenstack/schema-lite.ts
  • packages/clients/tanstack-query/src/svelte/index.svelte.ts
  • samples/sveltekit/src/zenstack/schema-lite.ts
  • samples/sveltekit/src/zenstack/schema.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Implement plugin hooks at ORM, Kysely, and entity mutation levels for query interception and customization

Applied to files:

  • packages/server/src/api/common/procedures.ts
  • samples/next.js/lib/db.ts
  • samples/next.js/zenstack/seed.ts
  • samples/nuxt/server/utils/db.ts
  • samples/sveltekit/src/zenstack/input.ts
  • packages/clients/tanstack-query/src/react.ts
  • samples/nuxt/zenstack/seed.ts
  • samples/nuxt/zenstack/input.ts
  • packages/clients/tanstack-query/src/svelte/index.svelte.ts
  • packages/clients/tanstack-query/src/vue.ts
  • samples/next.js/zenstack/input.ts
  • samples/sveltekit/src/zenstack/schema-lite.ts
  • samples/nuxt/app/plugins/tanstack-query.ts
  • samples/sveltekit/src/zenstack/schema.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Use Kysely as the query builder interface for low-level database queries, avoiding raw SQL when possible

Applied to files:

  • samples/next.js/lib/db.ts
  • samples/next.js/zenstack/seed.ts
  • samples/nuxt/server/utils/db.ts
  • samples/sveltekit/src/zenstack/input.ts
  • packages/clients/tanstack-query/src/react.ts
  • samples/nuxt/zenstack/seed.ts
  • samples/nuxt/zenstack/input.ts
  • packages/clients/tanstack-query/src/vue.ts
  • samples/next.js/zenstack/input.ts
  • samples/sveltekit/src/zenstack/schema.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Database migrations should use Prisma CLI under the hood via ZenStack commands

Applied to files:

  • samples/next.js/lib/db.ts
  • samples/next.js/zenstack/seed.ts
  • samples/nuxt/server/utils/db.ts
  • samples/nuxt/zenstack/seed.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Support only SQLite (better-sqlite3) and PostgreSQL (pg) as database adapters

Applied to files:

  • samples/next.js/lib/db.ts
📚 Learning: 2025-12-30T15:07:10.092Z
Learnt from: mwillbanks
Repo: zenstackhq/zenstack-v3 PR: 550
File: packages/orm/src/client/crud/operations/base.ts:158-159
Timestamp: 2025-12-30T15:07:10.092Z
Learning: In the zenstackhq/zenstack-v3 codebase, ts-expect-error should be heavily avoided in production code (packages/*). It is acceptable in test files but production code should use proper type annotations, type assertions, or refactoring to resolve type errors instead.

Applied to files:

  • samples/next.js/zenstack/seed.ts
  • samples/nuxt/zenstack/seed.ts
  • samples/nuxt/zenstack/input.ts
  • samples/next.js/zenstack/input.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.test.{ts,tsx} : ORM package tests should include comprehensive client API tests and policy tests

Applied to files:

  • samples/next.js/zenstack/seed.ts
  • samples/nuxt/server/utils/db.ts
  • samples/sveltekit/src/zenstack/input.ts
  • samples/nuxt/zenstack/seed.ts
  • samples/nuxt/zenstack/input.ts
  • samples/next.js/zenstack/input.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to tests/e2e/**/*.{ts,tsx} : E2E tests should validate real-world schema compatibility with established projects

Applied to files:

  • samples/next.js/zenstack/input.ts
🧬 Code graph analysis (10)
samples/next.js/app/signup/page.tsx (2)
packages/clients/tanstack-query/src/react.ts (1)
  • useClientQueries (336-397)
samples/next.js/zenstack/schema-lite.ts (1)
  • schema (120-120)
samples/next.js/lib/db.ts (2)
samples/nuxt/server/utils/db.ts (1)
  • db (6-25)
samples/sveltekit/src/lib/db.ts (1)
  • db (6-25)
samples/nuxt/server/utils/db.ts (4)
samples/next.js/lib/db.ts (1)
  • db (6-25)
samples/sveltekit/src/lib/db.ts (1)
  • db (6-25)
samples/nuxt/zenstack/schema-lite.ts (1)
  • schema (120-120)
samples/nuxt/zenstack/schema.ts (1)
  • schema (129-129)
samples/sveltekit/src/zenstack/input.ts (2)
samples/next.js/zenstack/input.ts (21)
  • UserFindManyArgs (11-11)
  • UserFindUniqueArgs (12-12)
  • UserFindFirstArgs (13-13)
  • UserExistsArgs (14-14)
  • UserCreateArgs (15-15)
  • UserCreateManyArgs (16-16)
  • UserCreateManyAndReturnArgs (17-17)
  • UserUpdateArgs (18-18)
  • UserUpdateManyArgs (19-19)
  • UserGetPayload (31-31)
  • PostFindManyArgs (32-32)
  • PostFindUniqueArgs (33-33)
  • PostFindFirstArgs (34-34)
  • PostExistsArgs (35-35)
  • PostCreateArgs (36-36)
  • PostCreateManyArgs (37-37)
  • PostCreateManyAndReturnArgs (38-38)
  • PostUpdateArgs (39-39)
  • PostUpdateManyArgs (40-40)
  • PostUpdateManyAndReturnArgs (41-41)
  • PostGetPayload (52-52)
samples/nuxt/zenstack/input.ts (21)
  • UserFindManyArgs (11-11)
  • UserFindUniqueArgs (12-12)
  • UserFindFirstArgs (13-13)
  • UserExistsArgs (14-14)
  • UserCreateArgs (15-15)
  • UserCreateManyArgs (16-16)
  • UserCreateManyAndReturnArgs (17-17)
  • UserUpdateArgs (18-18)
  • UserUpdateManyArgs (19-19)
  • UserGetPayload (31-31)
  • PostFindManyArgs (32-32)
  • PostFindUniqueArgs (33-33)
  • PostFindFirstArgs (34-34)
  • PostExistsArgs (35-35)
  • PostCreateArgs (36-36)
  • PostCreateManyArgs (37-37)
  • PostCreateManyAndReturnArgs (38-38)
  • PostUpdateArgs (39-39)
  • PostUpdateManyArgs (40-40)
  • PostUpdateManyAndReturnArgs (41-41)
  • PostGetPayload (52-52)
packages/clients/tanstack-query/src/react.ts (3)
packages/clients/tanstack-query/src/common/constants.ts (1)
  • CUSTOM_PROC_ROUTE_NAME (1-1)
packages/clients/tanstack-query/src/common/client.ts (2)
  • invalidateQueriesMatchingPredicate (5-15)
  • getAllQueries (17-41)
packages/clients/client-helpers/src/optimistic.ts (1)
  • createOptimisticUpdater (68-139)
samples/nuxt/zenstack/input.ts (2)
samples/next.js/zenstack/input.ts (5)
  • UserFindManyArgs (11-11)
  • UserFindUniqueArgs (12-12)
  • UserFindFirstArgs (13-13)
  • UserExistsArgs (14-14)
  • PostExistsArgs (35-35)
samples/sveltekit/src/zenstack/input.ts (5)
  • UserFindManyArgs (36-36)
  • UserFindUniqueArgs (37-37)
  • UserFindFirstArgs (38-38)
  • UserExistsArgs (39-39)
  • PostExistsArgs (69-69)
samples/next.js/app/feeds/page.tsx (2)
packages/clients/tanstack-query/src/react.ts (1)
  • useClientQueries (336-397)
samples/next.js/zenstack/schema-lite.ts (1)
  • schema (120-120)
packages/clients/tanstack-query/src/vue.ts (3)
packages/clients/tanstack-query/src/common/constants.ts (1)
  • CUSTOM_PROC_ROUTE_NAME (1-1)
packages/clients/client-helpers/src/invalidation.ts (2)
  • createInvalidator (26-44)
  • InvalidationPredicate (9-9)
packages/clients/tanstack-query/src/common/client.ts (2)
  • invalidateQueriesMatchingPredicate (5-15)
  • getAllQueries (17-41)
samples/sveltekit/src/zenstack/schema-lite.ts (1)
packages/schema/src/expression-utils.ts (1)
  • ExpressionUtils (19-123)
samples/sveltekit/src/zenstack/schema.ts (1)
packages/schema/src/expression-utils.ts (1)
  • ExpressionUtils (19-123)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build-test (22.x, sqlite)
  • GitHub Check: build-test (22.x, postgresql)
🔇 Additional comments (57)
samples/nuxt/server/api/model/[...].ts (1)

7-7: Remove the log option from RPCApiHandler—it's not supported by this component.

The log: ['debug', 'error'] option is not accepted by RPCApiHandler. Logging configuration belongs on the ORM client (ZenStackClient / Kysely or Prisma), not the handler. Pass the log settings when creating the database client instead. For a sample application, this is important to demonstrate the correct usage pattern to users.

⛔ Skipped due to learnings
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.test.{ts,tsx} : ORM package tests should include comprehensive client API tests and policy tests
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Use Kysely as the query builder interface for low-level database queries, avoiding raw SQL when possible
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Implement plugin hooks at ORM, Kysely, and entity mutation levels for query interception and customization
Learnt from: mwillbanks
Repo: zenstackhq/zenstack-v3 PR: 550
File: packages/orm/src/client/crud/operations/base.ts:158-159
Timestamp: 2025-12-30T15:07:10.092Z
Learning: In the zenstackhq/zenstack-v3 codebase, ts-expect-error should be heavily avoided in production code (packages/*). It is acceptable in test files but production code should use proper type annotations, type assertions, or refactoring to resolve type errors instead.
samples/nuxt/app/plugins/tanstack-query.ts (1)

14-16: LGTM! Formatting change only.

The trailing comma addition and spacing adjustment are purely cosmetic with no functional impact.

samples/next.js/zenstack/schema.ts (1)

113-126: LGTM! Generated schema procedures.

The new procedures block correctly defines signUp and listPublicPosts operations as generated by ZenStack CLI. This is expected output from the schema compilation process.

samples/sveltekit/src/app.d.ts (1)

4-10: LGTM! Formatting adjustment.

Indentation changes to the namespace declaration with no functional impact.

samples/nuxt/zenstack/input.ts (1)

9-9: LGTM! Generated type exports.

The addition of ExistsArgs import and the UserExistsArgs/PostExistsArgs type exports are consistent with the pattern in other framework samples and are generated by ZenStack CLI as expected.

Also applies to: 14-14, 35-35

samples/nuxt/app/app.vue (1)

1-5: LGTM! Clean refactoring to layout composition pattern.

The component has been simplified to use Nuxt's layout composition approach, delegating page-specific logic to child routes. This is a cleaner architecture for the sample application.

samples/next.js/app/layout.tsx (1)

2-2: LGTM! Proper Next.js 15 Image usage and layout structure.

The Image component is correctly configured with required props (width, height, alt) and the priority flag for above-the-fold content. The responsive layout uses standard Tailwind utilities compatible with the framework version in use.

Also applies to: 24-38

samples/nuxt/zenstack/schema.ts (1)

113-126: Generated code reflects new procedures definition.

This file is auto-generated by ZenStack CLI (as indicated in the header). The new procedures block correctly defines the signUp and listPublicPosts operations based on the source schema.

Reminder: Based on learnings, ensure you run zenstack generate after modifying the source .zmodel schema files to keep this generated code in sync.

samples/next.js/zenstack/input.ts (1)

9-9: LGTM! Generated type exports for exists operations.

This auto-generated file correctly adds ExistsArgs type exports for User and Post models, following the established pattern for other operation types (FindMany, Create, Update, etc.).

Also applies to: 14-14, 35-35

samples/next.js/zenstack/schema-lite.ts (1)

104-117: Generated code structure looks correct.

The procedures definition correctly reflects the schema operations:

  • signUp: properly configured as a mutation with email parameter
  • listPublicPosts: properly configured as a query returning an array

Since this is an auto-generated file, ensure that any future modifications are made to the source .zmodel file followed by running zenstack generate.

samples/shared/schema.zmodel (5)

1-4: LGTM!

The SQLite datasource configuration is appropriate for a sample application.


7-14: LGTM!

The User model is well-structured with appropriate constraints and relationships:

  • CUID for distributed-friendly IDs
  • Unique email constraint
  • Proper timestamp tracking
  • Correct one-to-many relationship with Post

17-25: LGTM!

The Post model is correctly structured with:

  • Proper relationship to User with cascade rules ensuring referential integrity
  • Sensible default for published (false for draft state)
  • Consistent ID generation strategy

27-28: LGTM!

The procedure definitions are correct:

  • signUp: appropriately marked as mutation for user creation
  • listPublicPosts: read-only query returning Post array

Both align with the generated TypeScript in schema-lite.ts.


1-28: Ensure zenstack generate is executed after schema modifications.

As per coding guidelines, after modifying ZModel schemas, you must run the generation command to compile the schema to TypeScript and keep generated files in sync.

Based on coding guidelines: "Always run zenstack generate after modifying ZModel schemas"

Run the following command to regenerate the TypeScript schema files:

#!/bin/bash
# Generate TypeScript from ZModel schema
zenstack generate
samples/nuxt/server/utils/db.ts (2)

2-2: Import paths updated correctly.

The import paths for SqliteDialect and schema are consistent with the project structure and match the patterns used in other sample applications.

Also applies to: 4-4


15-23: listPublicPosts procedure implementation looks good.

The procedure correctly filters by published: true and orders results by updatedAt descending, providing a safe public API for fetching posts.

samples/next.js/app/page.tsx (2)

77-95: UI restructure improves navigation.

The replacement of the image logo with a text heading and navigation buttons (View Public Feeds, Sign Up) provides clear entry points to the new features introduced in this PR. The Link-based navigation is appropriate for client-side routing in Next.js.


97-177: Core functionality preserved correctly.

All existing data fetching, mutations, and UI interactions (create post, delete post, toggle publish, filters, optimistic updates) remain intact. The structural reorganization maintains the same user experience while improving the layout.

samples/nuxt/app/layouts/default.vue (1)

1-10: LGTM!

The layout component is well-structured with appropriate responsive and dark mode styling. The centered container with constrained width provides a clean chrome for the Nuxt pages.

samples/nuxt/zenstack/seed.ts (2)

3-13: LGTM!

The seeding logic correctly uses the centralized db instance to clear and populate test users.


1-1: The centralized db import is correctly set up and properly exported from server/utils/db.ts as a ZenStackClient instance.

packages/clients/tanstack-query/src/common/constants.ts (1)

1-1: LGTM!

Centralizing the custom procedure route name as a constant is excellent practice. This ensures consistency across all framework integrations (React, Svelte, Vue) and makes future updates easier.

samples/sveltekit/src/routes/signup/+page.svelte (2)

1-30: LGTM!

The script logic is well-implemented:

  • Proper use of Svelte 5 runes for reactive state
  • Correct integration with TanStack Query via useClientQueries
  • Clean mutation handling with appropriate callbacks
  • Error handling includes fallback message for non-Error objects
  • Form state is properly cleared on success

32-86: LGTM!

The template is well-structured with:

  • Semantic HTML form elements
  • Proper accessibility (labels, required attributes)
  • Disabled states during mutation to prevent double submission
  • Clear visual feedback for success and error states
  • Responsive design with dark mode support
  • Good UX with dynamic button text and form disabling
samples/next.js/zenstack/seed.ts (1)

1-13: LGTM! Clean refactoring to use centralized db instance.

The change correctly refactors the seed script to use the centralized database instance from @/lib/db, eliminating duplicate initialization code. The seeding logic remains unchanged and functional.

samples/nuxt/zenstack/schema-lite.ts (1)

1-4: No action needed. The source ZModel schema (samples/shared/schema.zmodel) correctly defines both the signUp and listPublicPosts procedures, which are properly reflected in the generated file at lines 104-117. The file is correctly auto-generated and contains the expected procedures definition.

Likely an incorrect or invalid review comment.

samples/next.js/app/signup/page.tsx (3)

1-6: LGTM!

The imports and 'use client' directive are correctly configured for a Next.js client component with form handling and TanStack Query integration.


8-14: LGTM!

The component setup correctly uses the new $procs API for accessing custom procedures. State management is clean and appropriate for form handling.


16-33: LGTM!

The form submission handler is well-structured with proper error handling and user feedback. The mutation callbacks correctly handle success and error states, and the UX is thoughtful (clearing form on success, resetting messages on new submission).

samples/next.js/app/feeds/page.tsx (2)

1-5: LGTM!

The imports are correctly configured for a client-side data fetching component using the ZenStack TanStack Query integration.


11-58: Excellent state management and UI implementation.

The component properly handles all query states (loading, error, empty, success) with clear user feedback. The date formatting using toLocaleDateString() is locale-aware, and the pluralization logic is correct. Dark mode support is comprehensive throughout.

samples/sveltekit/src/routes/+layout.svelte (1)

2-16: The endpoint configuration is correct.

The formatting updates (quote consistency, indentation) look good. The endpoint /api/model is appropriate—it's the standard endpoint used consistently across all sample projects (Next.js, Nuxt, SvelteKit) and is the default query endpoint. The CUSTOM_PROC_ROUTE_NAME constant ('$procs') is an internal client-side routing mechanism, not an HTTP endpoint path, and the RPC API handler at /api/model correctly handles both model and custom procedure requests.

samples/nuxt/app/pages/signup.vue (2)

1-29: LGTM - Well-structured signup page implementation.

The reactive state management, mutation handling with success/error callbacks, and form submission logic are correctly implemented. The use of isPending to disable the form during submission prevents double-submissions.

Consider adding type annotations for the user and error parameters in the callbacks for improved type safety, though this is acceptable for sample code:

onSuccess: (user: { email: string }) => { ... }

32-79: Clean template with proper accessibility and state handling.

Good use of:

  • @submit.prevent to handle form submission
  • :disabled binding for both input and button during pending state
  • Conditional message rendering with appropriate styling for success/error states
samples/sveltekit/src/routes/feeds/+page.svelte (1)

1-7: LGTM - Clean query setup for public feeds.

The destructuring of query results and usage of the $procs namespace for custom procedures follows the established pattern.

samples/sveltekit/src/routes/+page.svelte (2)

22-29: LGTM - Improved readability with multi-line formatting.

The reformatted useFindMany call clearly separates the query arguments from the options, making the code easier to read and maintain.


79-92: Good addition of navigation links to new features.

The links to /feeds and /signup integrate well with the new pages added in this PR.

samples/sveltekit/src/zenstack/input.ts (1)

1-95: Auto-generated file - no review needed.

This file is automatically generated by ZenStack CLI as indicated by the header. The changes (added ExistsArgs types and formatting adjustments) are consistent with the generated output in other sample projects (samples/next.js/zenstack/input.ts, samples/nuxt/zenstack/input.ts).

samples/nuxt/app/pages/feeds.vue (3)

1-7: LGTM - Clean query setup matching the established pattern.

The use of useClientQueries and the $procs namespace for custom procedures is consistent with the Vue integration.


20-31: Same state handling pattern as SvelteKit - consider consistency.

The conditional rendering uses separate v-if blocks similar to the SvelteKit version. Vue's v-else-if could make state transitions clearer, though the current implementation is functionally correct.


33-46: LGTM - Proper list rendering with key binding.

Good use of :key="post.id" for efficient Vue list rendering.

samples/sveltekit/src/zenstack/schema-lite.ts (1)

1-124: Auto-generated file - no review needed.

This file is automatically generated by ZenStack CLI from ZModel schema files. The structure follows ZenStack conventions with proper model definitions, relations, and procedure declarations. Based on learnings, always run zenstack generate after modifying ZModel schemas to regenerate this file.

packages/clients/tanstack-query/src/svelte/index.svelte.ts (6)

59-59: Good use of centralized constant for procedure routing.

Importing CUSTOM_PROC_ROUTE_NAME from a shared constants file ensures consistency across React, Vue, and Svelte integrations.


301-333: LGTM - Clean refactor to parameterless procedure hook builder.

The removal of the endpointModel parameter in favor of directly using CUSTOM_PROC_ROUTE_NAME simplifies the API and ensures consistency across framework integrations.


549-551: Good separation of custom procedure logic.

The guard model !== CUSTOM_PROC_ROUTE_NAME correctly excludes custom procedures from the model-specific optimistic update and invalidation logic, as custom procedures don't follow the standard CRUD model pattern.


584-591: LGTM - Correct onMutate sequencing for optimistic updates.

The optimistic updater runs before the user's onMutate, ensuring the cache is updated optimistically before any user logic executes. The return value from origOnMutate is correctly propagated for potential rollback context.


605-616: LGTM - Correct onSettled sequencing for invalidation.

Running the invalidator before the user's onSettled ensures the cache is refreshed with server data before user cleanup logic runs, which is the expected behavior for optimistic updates.


565-571: Callback sequencing matches React implementation.

The Svelte implementation correctly runs the invalidator before the user's onSuccess callback, consistent with React's implementation. Both explicitly wrap the callback to ensure cache invalidation happens first.

packages/clients/tanstack-query/src/vue.ts (3)

57-57: LGTM!

Clean import of the centralized constant for procedure routing.


313-345: LGTM!

The refactored buildProcedureHooks correctly routes all procedure queries and mutations through CUSTOM_PROC_ROUTE_NAME, aligning with the centralized routing approach.


568-630: LGTM - Well-structured mutation handling for custom procedures.

The branching logic correctly:

  1. Skips invalidation/optimistic updates for custom procedures (CUSTOM_PROC_ROUTE_NAME)
  2. Runs invalidation in onSuccess for non-optimistic mutations
  3. Runs optimistic updates in onMutate and invalidation in onSettled for optimistic mutations
  4. Ensures internal handlers execute before user-provided callbacks
packages/clients/tanstack-query/src/react.ts (3)

58-58: LGTM!

Consistent import of the centralized routing constant.


354-393: LGTM!

The React implementation correctly mirrors the Vue pattern while including React-specific hooks (useSuspenseQuery, useInfiniteQuery, useSuspenseInfiniteQuery). All procedure hooks properly route through CUSTOM_PROC_ROUTE_NAME.


655-718: LGTM - Consistent with Vue implementation.

The React mutation handling correctly implements the same callback sequencing pattern:

  • Custom procedures bypass invalidation/optimistic logic
  • Non-optimistic: invalidation runs before user onSuccess
  • Optimistic: updates run before user onMutate, invalidation runs before user onSettled

The implementations are functionally consistent across both frameworks, with appropriate framework-specific differences (React doesn't need Vue's unref()).

samples/sveltekit/src/zenstack/schema.ts (2)

1-4: Auto-generated file - no manual modifications needed.

This file is automatically generated by ZenStack CLI. The changes here reflect the new procedures (signUp and listPublicPosts) that were added to the source schema.


162-175: Procedures definition looks correct.

The auto-generated procedures block properly defines:

  • signUp as a mutation with email parameter returning User
  • listPublicPosts as a query (no mutation flag) returning Post[]

This aligns with the tanstack-query client implementations that route procedures through CUSTOM_PROC_ROUTE_NAME.

@claude
Copy link

claude bot commented Jan 8, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

@ymc9 ymc9 merged commit 2c9db43 into dev Jan 8, 2026
4 of 5 checks passed
@ymc9 ymc9 deleted the fix/procs-hooks-invalidation branch January 8, 2026 08:12
This was referenced Jan 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants