Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Aug 13, 2025

Summary by CodeRabbit

  • New Features
    • Pre/post-mutation hooks now support loading multiple entities. The related flags are pluralized: loadBeforeMutationEntities and loadAfterMutationEntities.
  • Documentation
    • README updated to reflect the pluralized flags for multi-entity loading in mutation interception examples.
  • Chores
    • Version bumped to 3.0.0-alpha.23 across packages.

ymc9 and others added 2 commits August 13, 2025 21:00
* fix: improve plugin config typing

* update
Copilot AI review requested due to automatic review settings August 13, 2025 14:27
@claude
Copy link

claude bot commented Aug 13, 2025

Claude finished @ymc9's task —— View job


PR Review: merge dev to main (v3.0.0-alpha.23) ✅

Review Checklist:

  • Analyze changed files and understand scope
  • Review version consistency across packages
  • Review runtime code changes for quality issues
  • Check for potential bugs or security concerns
  • Assess performance implications
  • Evaluate test coverage
  • Provide comprehensive feedback

Analysis Summary

This PR merges dev to main for v3.0.0-alpha.23 release. The changes include:

Detailed Review

✅ Version Consistency
All 21 packages have been correctly updated to version 3.0.0-alpha.23 - no inconsistencies found.

✅ Code Quality & Bug Fixes
The main code change is an important bug fix in the plugin system:

Fixed Property Naming Inconsistency (packages/runtime/src/client/plugin.ts:42-47, zenstack-query-executor.ts:75,286-287,293,357)

  • Before: Mixed usage of loadBeforeMutationEntity (singular) and loadAfterMutationEntity
  • After: Consistent loadBeforeMutationEntities (plural) throughout
  • Impact: This fixes a critical type safety issue where the API expected plural form but implementation used singular
  • Proper Fix: All 6 test cases in mutation-hooks.test.ts updated to match the corrected API

✅ Security & Performance

  • No security concerns identified
  • No performance regressions - the changes are purely cosmetic/typing fixes
  • Maintains backward compatibility within the alpha release cycle

✅ Test Coverage
Excellent test coverage for the plugin changes:

  • All 6 test scenarios in mutation-hooks.test.ts updated
  • Tests cover loadBeforeMutationEntities and loadAfterMutationEntities functionality
  • Tests verify both single and multi-entity mutation scenarios
  • Transaction rollback scenarios properly tested

✅ Best Practices

  • Consistent naming conventions now enforced
  • Proper TypeScript typing maintained
  • Documentation comments updated to match API changes

Recommendation: APPROVED

This is a solid release merge with important bug fixes:

  1. Critical Plugin API Fix: Resolves type inconsistency that could cause runtime errors
  2. Clean Version Bump: Consistent across all packages
  3. Comprehensive Testing: All affected code paths have test coverage
  4. No Breaking Changes: Safe for alpha users to upgrade

The changes improve API consistency and fix potential bugs without introducing any regressions. Ready to merge to main.

@ymc9 ymc9 changed the title merge dev to main merge dev to main (v3.0.0-alpha.23) Aug 13, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 13, 2025

Walkthrough

Renames mutation interception flags to pluralized forms across runtime code, plugin types, tests, and README. Updates executor logic to use plural fields for pre/post-mutation entity loading. Bumps versions to 3.0.0-alpha.23 across root, packages, samples, and tests. No other functional changes.

Changes

Cohort / File(s) Summary
Runtime mutation interception API rename
packages/runtime/src/client/executor/zenstack-query-executor.ts, packages/runtime/src/client/plugin.ts, packages/runtime/test/plugin/mutation-hooks.test.ts
Replace loadBeforeMutationEntity/loadAfterMutationEntity with loadBeforeMutationEntities/loadAfterMutationEntities; update executor flow, public type MutationInterceptionFilterResult, and tests to handle multi-entity before/after loading.
Docs update
README.md
README sample updated to use loadBeforeMutationEntities and loadAfterMutationEntities.
Version bump metadata
package.json, packages/*/package.json (cli, common-helpers, create-zenstack, dialects/sql.js, eslint-config, ide/vscode, language, runtime, sdk, tanstack-query, testtools, typescript-config, vitest-config, zod), samples/blog/package.json, tests/e2e/package.json
Bump versions from 3.0.0-alpha.22 to 3.0.0-alpha.23; no other fields changed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Poem

I twitch my whiskers, tap my paws—
Plurals hop in, obeying laws.
Before and after, entities dance,
Executor keeps a steady stance.
Alpha bumps across the glade,
Carrots raised for code well-made! 🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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 PR merges the dev branch to main, primarily bumping the version number from 3.0.0-alpha.22 to 3.0.0-alpha.23 across all packages and fixing API naming inconsistencies in mutation lifecycle hooks.

  • Version bump from 3.0.0-alpha.22 to 3.0.0-alpha.23 across all packages
  • API naming fix: renamed loadBeforeMutationEntity and loadAfterMutationEntity to their plural forms
  • Updated corresponding test files and documentation to reflect the API changes

Reviewed Changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated no comments.

Show a summary per file
File Description
package.json Root package version bump
packages/*/package.json Version updates for all package modules
packages/runtime/src/client/plugin.ts API interface updates for mutation lifecycle hooks
packages/runtime/src/client/executor/zenstack-query-executor.ts Implementation updates to use new plural property names
packages/runtime/test/plugin/mutation-hooks.test.ts Test updates to use new API naming
README.md Documentation updates showing new API usage

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

@ymc9 ymc9 added this pull request to the merge queue Aug 13, 2025
Merged via the queue into main with commit 726b826 Aug 13, 2025
6 of 7 checks passed
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: 0

🔭 Outside diff range comments (2)
packages/runtime/src/client/executor/zenstack-query-executor.ts (2)

71-83: Don't clobber existing RETURNING and avoid changing the user-visible result shape

Overwriting any existing returning clause with SELECT * can change the rows shape returned to callers. If the original query specified a returning projection (or none), this will silently alter behavior. Only add returning when it's absent.

Apply this diff to preserve an existing returning:

-            if (
-                (InsertQueryNode.is(queryNode) || UpdateQueryNode.is(queryNode)) &&
-                mutationInterceptionInfo?.loadAfterMutationEntities
-            ) {
-                // need to make sure the query node has "returnAll"
-                // for insert and update queries
-                queryNode = {
-                    ...queryNode,
-                    returning: ReturningNode.create([SelectionNode.createSelectAll()]),
-                };
-            }
+            if (
+                (InsertQueryNode.is(queryNode) || UpdateQueryNode.is(queryNode)) &&
+                mutationInterceptionInfo?.loadAfterMutationEntities
+            ) {
+                // ensure the query node returns rows for insert/update, but don't clobber an existing returning
+                if (!queryNode.returning) {
+                    queryNode = {
+                        ...queryNode,
+                        returning: ReturningNode.create([SelectionNode.createSelectAll()]),
+                    };
+                }
+            }

Also, Line 100 still has a TODO about trimming the result to the original query node. Consider addressing it here to prevent returning a different shape than the original query intended. I can help sketch a minimal normalizer if needed.


316-326: beforeEntityMutation payload likely uses the wrong property name

You’re passing entities to beforeEntityMutation, while the rest of the file (and the pluralization change) suggests the new field should be beforeMutationEntities. If the type has been updated (as per the PR), this will break consumers at compile-time or silently omit data at runtime.

Apply this diff to align naming:

-                    await plugin.beforeEntityMutation({
-                        model: mutationModel,
-                        action: mutationInterceptionInfo.action,
-                        queryNode,
-                        entities: mutationInterceptionInfo.beforeMutationEntities,
-                    });
+                    await plugin.beforeEntityMutation({
+                        model: mutationModel,
+                        action: mutationInterceptionInfo.action,
+                        queryNode,
+                        beforeMutationEntities: mutationInterceptionInfo.beforeMutationEntities,
+                    });

If the public plugin API intentionally still uses entities for the “before” hook, please confirm and keep it consistent across docs/tests.

🧹 Nitpick comments (1)
packages/runtime/src/client/executor/zenstack-query-executor.ts (1)

286-288: Normalize plugin flags to booleans and avoid undefined propagation

Using the ||= operator works, but the fields can remain undefined when no plugin sets them. Normalize to booleans for clarity and type safety.

Apply this diff:

-                    result.loadBeforeMutationEntities ||= filterResult.loadBeforeMutationEntities;
-                    result.loadAfterMutationEntities ||= filterResult.loadAfterMutationEntities;
+                    result.loadBeforeMutationEntities =
+                        !!result.loadBeforeMutationEntities || !!filterResult.loadBeforeMutationEntities;
+                    result.loadAfterMutationEntities =
+                        !!result.loadAfterMutationEntities || !!filterResult.loadAfterMutationEntities;

Optionally, initialize the fields where result is declared so they’re always boolean:

-            const result: MutationInterceptionFilterResult = {
-                intercept: false,
-            };
+            const result: MutationInterceptionFilterResult = {
+                intercept: false,
+                loadBeforeMutationEntities: false,
+                loadAfterMutationEntities: false,
+            };
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aec0096 and ac43d58.

📒 Files selected for processing (21)
  • README.md (1 hunks)
  • package.json (1 hunks)
  • packages/cli/package.json (1 hunks)
  • packages/common-helpers/package.json (1 hunks)
  • packages/create-zenstack/package.json (1 hunks)
  • packages/dialects/sql.js/package.json (1 hunks)
  • packages/eslint-config/package.json (1 hunks)
  • packages/ide/vscode/package.json (1 hunks)
  • packages/language/package.json (1 hunks)
  • packages/runtime/package.json (1 hunks)
  • packages/runtime/src/client/executor/zenstack-query-executor.ts (3 hunks)
  • packages/runtime/src/client/plugin.ts (2 hunks)
  • packages/runtime/test/plugin/mutation-hooks.test.ts (5 hunks)
  • packages/sdk/package.json (1 hunks)
  • packages/tanstack-query/package.json (1 hunks)
  • packages/testtools/package.json (1 hunks)
  • packages/typescript-config/package.json (1 hunks)
  • packages/vitest-config/package.json (1 hunks)
  • packages/zod/package.json (1 hunks)
  • samples/blog/package.json (1 hunks)
  • tests/e2e/package.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
{packages,samples,tests}/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

Packages are located in packages/, samples/, and tests/

Files:

  • packages/sdk/package.json
  • samples/blog/package.json
  • packages/create-zenstack/package.json
  • packages/testtools/package.json
  • packages/runtime/package.json
  • packages/tanstack-query/package.json
  • packages/dialects/sql.js/package.json
  • packages/vitest-config/package.json
  • tests/e2e/package.json
  • packages/ide/vscode/package.json
  • packages/runtime/test/plugin/mutation-hooks.test.ts
  • packages/eslint-config/package.json
  • packages/cli/package.json
  • packages/typescript-config/package.json
  • packages/zod/package.json
  • packages/language/package.json
  • packages/runtime/src/client/plugin.ts
  • packages/common-helpers/package.json
  • packages/runtime/src/client/executor/zenstack-query-executor.ts
tests/e2e/**

📄 CodeRabbit Inference Engine (CLAUDE.md)

E2E tests are in tests/e2e/ directory

Files:

  • tests/e2e/package.json
🧠 Learnings (2)
📚 Learning: 2025-08-04T08:43:33.161Z
Learnt from: CR
PR: zenstackhq/zenstack-v3#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-04T08:43:33.161Z
Learning: `zenstack generate` compiles ZModel to TypeScript schema (`schema.ts`)

Applied to files:

  • packages/language/package.json
📚 Learning: 2025-08-04T08:43:33.161Z
Learnt from: CR
PR: zenstackhq/zenstack-v3#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-04T08:43:33.161Z
Learning: Plugin Architecture: Runtime plugins for query interception and entity mutation hooks

Applied to files:

  • packages/runtime/src/client/plugin.ts
  • packages/runtime/src/client/executor/zenstack-query-executor.ts
⏰ 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). (1)
  • GitHub Check: build-test (20.x)
🔇 Additional comments (30)
packages/language/package.json (2)

4-4: Version bump looks correct and aligned with the PR scope.
This aligns with the repo-wide bump to 3.0.0-alpha.23.


4-4: ✅ Monorepo versions all at 3.0.0-alpha.23 with no stale references

All package.json files declare version 3.0.0-alpha.23, and the search for “3.0.0-alpha.22” returned no hits. No further action needed.

packages/common-helpers/package.json (1)

3-3: LGTM: simple version bump.
No other fields changed; consistent with monorepo-wide bump.

packages/dialects/sql.js/package.json (1)

3-3: LGTM: version updated as expected.
Peer deps remain unchanged and compatible; nothing else modified.

tests/e2e/package.json (1)

3-3: LGTM: e2e package version bump only.
No script or dependency changes; aligns with the overall version update.

samples/blog/package.json (1)

3-3: LGTM: sample app version bump.
No functional changes; dependencies still use workspace references.

packages/cli/package.json (1)

6-6: Monorepo Pre-release Version Consistency Verified

All automated checks passed for version 3.0.0-alpha.23 across the repository:

  • 13 @zenstackhq/* packages (and create-zenstack) are correctly bumped.
  • All internal @zenstackhq/* dependencies use workspace:*.
  • No deprecated loadBeforeMutationEntity or loadAfterMutationEntity flags remain.

LGTM—no further action required.

packages/tanstack-query/package.json (1)

3-3: LGTM: version bump only.

No API or config changes; aligns with the monorepo release.

packages/create-zenstack/package.json (1)

3-3: LGTM: version bump aligns with the release.

CLI scaffolder metadata-only update; no other changes.

packages/zod/package.json (1)

3-3: LGTM: version bump only.

Private package; dependencies unchanged; consistent with repo-wide bump.

packages/sdk/package.json (1)

3-3: LGTM: version bump only.

Exports, deps, and build scripts unchanged; consistent with the release train.

packages/vitest-config/package.json (1)

4-4: Version bump looks good

Metadata-only change. No concerns.

package.json (1)

3-3: Root version bump approved; monorepo consistency verified

Verified across all package.json files:

  • All versions updated to 3.0.0-alpha.23
  • No lingering 3.0.0-alpha.22 references
  • All internal @zenstackhq/* dependencies use the workspace: protocol

Ready to merge.

packages/runtime/package.json (1)

3-3: Runtime package version bump aligns with related API changes

Given the pluralization of mutation interception fields elsewhere in the PR, bumping to alpha.23 is appropriate. No further action in this file.

packages/typescript-config/package.json (1)

3-3: LGTM: metadata-only bump

Private package version updated; no impact on consumers.

packages/testtools/package.json (1)

3-3: Test tools version bump approved

No script/export changes. Ensure peer dependency ranges remain satisfied in the monorepo CI matrix.

If helpful, extend the earlier script to assert that all packages depending on better-sqlite3 or pg declare compatible versions, by grepping for "better-sqlite3" and "pg" in package.json and reviewing the ranges.

packages/ide/vscode/package.json (1)

4-4: Version bump aligned with monorepo pattern.

The version upgrade to 3.0.0-alpha.23 is consistent with the overall version uplift across the monorepo.

packages/eslint-config/package.json (1)

3-3: Version bump aligned with monorepo pattern.

The version upgrade to 3.0.0-alpha.23 is consistent with the overall version uplift across the monorepo.

packages/runtime/src/client/plugin.ts (4)

42-42: Field name pluralization improves API consistency.

The rename from loadBeforeMutationEntity to loadBeforeMutationEntities better reflects that multiple entities can be affected by a single mutation operation.


47-47: Field name pluralization improves API consistency.

The rename from loadAfterMutationEntity to loadAfterMutationEntities better reflects that multiple entities can be affected by a single mutation operation.


152-152: Documentation correctly updated to reference plural field.

The parameter documentation now properly references loadBeforeMutationEntities which aligns with the field name change.


159-162: Documentation correctly updated to reference plural fields.

The parameter documentation now properly references both loadBeforeMutationEntities and loadAfterMutationEntities which aligns with the field name changes.

README.md (1)

354-356: Documentation example updated to reflect API changes.

The code sample correctly demonstrates the new plural field names loadBeforeMutationEntities and loadAfterMutationEntities in the mutation interception filter configuration.

packages/runtime/test/plugin/mutation-hooks.test.ts (5)

115-115: Test updated for pluralized API.

The test correctly uses the new loadBeforeMutationEntities field name, maintaining the same boolean functionality while aligning with the updated API.


162-162: Test updated for pluralized API.

The test correctly uses the new loadAfterMutationEntities field name, maintaining the same boolean functionality while aligning with the updated API.


208-208: Test updated for pluralized API.

The test correctly uses the new loadAfterMutationEntities field name for multi-entity mutation testing.


266-266: Test updated for pluralized API.

The test correctly uses the new loadAfterMutationEntities field name for nested mutation testing.


353-354: Test updated for pluralized API.

The test correctly uses both new field names loadBeforeMutationEntities and loadAfterMutationEntities for comprehensive mutation lifecycle testing.

packages/runtime/src/client/executor/zenstack-query-executor.ts (2)

292-294: LGTM: pre-mutation entity loading now correctly gated by plural flag

The condition now aligns with the new pluralized flag and applies only to update/delete, which is appropriate for pre-mutation reads.


352-361: After-mutation entities derivation: consider dialects without RETURNING

This relies on rows being present for insert/update. For dialects that don’t support RETURNING, the adapter may ignore it and rows could be empty. If that’s a supported configuration, add a fallback (e.g., reloading by PKs when available) or guard by dialect capability.

Would you confirm whether all supported dialects in this runtime guarantee RETURNING semantics for insert/update when requested? If not, I can propose a guarded fallback path.

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.

2 participants