Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Nov 18, 2025

Summary by CodeRabbit

  • New Features

    • Added a ZenStack adapter for Better-Auth and a schema generator to integrate and emit models.
    • Exported ORM CRUD type aliases to improve type safety.
  • Changes

    • Default schema discovery now prioritizes ./schema.zmodel over ./zenstack/schema.zmodel.
  • Chores

    • Added package, build, test, lint, and TypeScript configs for the Better-Auth adapter package.

Copilot AI review requested due to automatic review settings November 18, 2025 00:27
@coderabbitai
Copy link

coderabbitai bot commented Nov 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a new Better-Auth adapter package for ZenStack (implementation, schema generator, build/config), introduces ESLint/tsconfig/tsup/vitest and package.json exports, exports several ORM client types, and adjusts CLI schema search order and codegen reference lookups.

Changes

Cohort / File(s) Summary
Better-Auth package metadata & tooling
packages/auth-adapters/better-auth/package.json, packages/auth-adapters/better-auth/tsconfig.json, packages/auth-adapters/better-auth/tsup.config.ts, packages/auth-adapters/better-auth/vitest.config.ts, packages/auth-adapters/better-auth/eslint.config.js
Adds a new package manifest and configuration files (ESLint, tsconfig, tsup, Vitest) defining exports (ESM/CJS), dependencies/peerDependencies/devDependencies, build and test settings, and a custom ESLint config.
Better-Auth adapter implementation
packages/auth-adapters/better-auth/src/adapter.ts, packages/auth-adapters/better-auth/src/index.ts
Implements AdapterConfig and zenstackAdapter to map Better-Auth operations to ZenStack ORM calls; exposes adapter and config via src/index.ts.
Schema generator for adapter
packages/auth-adapters/better-auth/src/schema-generator.ts
Adds generateSchema to produce/update ZModel schema from BetterAuth table definitions, handling scalar types, relations, defaults, to-many inverses, and emit logic only on changes.
ORM client type exports
packages/orm/src/client/crud-types.ts
Changes visibility of several type aliases — exports CreateManyInput, CreateInput, and UpdateInput.
CLI & codegen tweaks
packages/cli/src/actions/action-utils.ts, packages/language/src/zmodel-code-generator.ts
Reorders default schema file lookup to prefer ./schema.zmodel over ./zenstack/schema.zmodel; replaces ref?.name lookups with $refText for code generation name resolution.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Focus review on:
    • packages/auth-adapters/better-auth/src/adapter.ts — where-clause translation, operator mapping, transaction wrapping, and error handling.
    • packages/auth-adapters/better-auth/src/schema-generator.ts — type mapping, relation/@relation generation, and id/default handling.
    • packages/language/src/zmodel-code-generator.ts — ensure $refText substitution preserves intended name resolution.
    • packages/cli/src/actions/action-utils.ts — confirm schema search order change is intentional and compatible.

Poem

🐰 I dug a tunnel, found new code to share,
A Better-Auth bridge with ZenStack flair.
Models stitched, relations neatly spun,
Build tools humming — oh what fun!
Hoppity-hop, the adapter's begun! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: better-auth adapter' is directly related to the main change—adding a complete Better-Auth adapter implementation with configuration, schema generation, and public API exports across multiple new files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/better-auth-adapter

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 Nov 18, 2025

Claude finished @ymc9's task —— View job


Code Review: Better Auth Adapter

Reviewing the new better-auth adapter implementation. Here's my analysis checklist:

Review Tasks:

  • Analyze adapter.ts implementation
  • Review schema-generator.ts logic
  • Check package configuration and dependencies
  • Examine integration with existing ZenStack code
  • Assess security considerations
  • Evaluate performance implications
  • Check for test coverage
  • Provide comprehensive feedback

📋 Code Review Summary

Strengths

  1. Well-structured adapter implementation - The zenstackAdapter follows Better Auth's adapter factory pattern correctly
  2. Comprehensive CRUD operations - Full support for create, read, update, delete with proper where clause conversion
  3. Robust schema generation - Intelligent ZModel schema generation from Better Auth table definitions
  4. Transaction support - Proper implementation of database transactions
  5. Type safety - Good use of TypeScript generics and type constraints

⚠️ Issues & Concerns

Critical Issues

  1. Missing Test Coverage (packages/auth-adapters/better-auth/src/):

    • No test files found for this critical authentication adapter
    • Complex logic in schema generation and CRUD operations needs comprehensive testing
    • Risk: Production bugs, security vulnerabilities, integration failures
  2. Silent Error Handling (adapter.ts:192-197):

    try {
        await modelDb.delete({ where: whereClause });
    } catch {
        // If the record doesn't exist, we don't want to throw an error
    }
    • Silently catches ALL exceptions, not just "record not found"
    • Risk: Database connection errors, constraint violations masked

Security Concerns

  1. SQL Injection Prevention (adapter.ts:70-113):

    • Where clause conversion logic looks sound but needs security testing
    • Operator mapping is comprehensive: starts_with, ends_with, ne, not_in
    • Recommendation: Add explicit tests for injection attempts
  2. Input Validation (adapter.ts:115-123):

    • Model existence check is good, but error message reveals internal structure
    • Consider sanitizing error messages for production

Code Quality Issues

  1. Hard-coded Magic Values (adapter.ts:148, schema-generator.ts:237):

    • Default limit of 100 in findMany should be configurable
    • Hard-coded SQLite database path file:./test.db
  2. TODO Comment (schema-generator.ts:40):

    • TODO for respecting package.json zenstack configuration
    • Should be addressed before production release
  3. Console Warnings (schema-generator.ts:337-340, 347-351):

    • Multiple console.warn calls for unsupported features
    • Consider using structured logging instead

🏗️ Architecture & Integration

Positive:

  • Clean integration with ZenStack's ORM client contract
  • Proper use of workspace dependencies
  • Follows monorepo conventions with appropriate peer dependencies

Integration Points Reviewed:

  • CLI integration (packages/cli/src/actions/action-utils.ts): Minor changes to schema file resolution ✅
  • Language integration (packages/language/src/zmodel-code-generator.ts): AST generation improvements ✅
  • ORM integration (packages/orm/src/client/crud-types.ts): Type definition enhancements ✅

🚀 Performance Considerations

  • Lazy initialization of Better Auth options is efficient
  • Schema generation happens at build time, not runtime ✅
  • Transaction implementation delegates properly to ZenStack's transaction system ✅

📦 Package Configuration

Good practices:

  • Proper peer dependencies for Better Auth
  • ESM/CJS dual export support
  • TypeScript configuration follows project standards

🛠️ Recommendations

High Priority (Must Fix)

  1. Add comprehensive test suite covering:

    • CRUD operations with various data types
    • Where clause conversion edge cases
    • Schema generation scenarios
    • Error handling paths
    • Security injection attempts
  2. Improve error handling in delete operations:

    // Instead of catching all errors:
    try {
        const result = await modelDb.delete({ where: whereClause });
        return result;
    } catch (error) {
        if (isRecordNotFoundError(error)) {
            return null; // or appropriate response
        }
        throw error; // Re-throw unexpected errors
    }

Medium Priority

  1. Address TODO comment - Implement package.json zenstack configuration support
  2. Make configurations configurable - Remove hard-coded values
  3. Implement structured logging instead of console.warn

Low Priority

  1. Add JSDoc documentation for public APIs
  2. Consider adding integration examples in package README

🔒 Security Assessment

Overall: Acceptable with testing

  • Input sanitization appears adequate
  • No obvious SQL injection vectors
  • Error messages could be more production-friendly
  • Requires: Security-focused testing before production use

📊 Final Rating

Code Quality: B+ - Well-structured with room for improvement
Security: B - Looks secure but needs validation through testing
Performance: A- - Efficient design patterns
Test Coverage: F - Critical gap that must be addressed

Overall Recommendation: Approve with required changes - The foundation is solid, but testing is essential before merging.


Job run: https://github.com/zenstackhq/zenstack-v3/actions/runs/19449396482

Copilot finished reviewing on behalf of ymc9 November 18, 2025 00:31
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: 7

Caution

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

⚠️ Outside diff range comments (1)
packages/cli/src/actions/action-utils.ts (1)

33-41: Verify and apply the error message and consider release notes for breaking behavior change.

The review comment is accurate. Verification confirms:

  1. Error message mismatch confirmed: The code checks ./schema.zmodel first (lines 33-34), then ./zenstack/schema.zmodel (lines 35-36), but the error message at line 39 still lists them in reverse order.

  2. Breaking change confirmed: The help text in packages/cli/src/index.ts line 52 documents the default as "zenstack/schema.zmodel", but the new search order will now prefer ./schema.zmodel for projects with both files—a behavioral reversal.

Apply the suggested diff to correct the error message ordering, and ensure this breaking change is documented in release notes.

🧹 Nitpick comments (4)
packages/auth-adapters/better-auth/src/schema-generator.ts (2)

465-465: Simple pluralization strategy may not handle irregular plurals.

The to-many relation names are generated using ${lowerCaseFirst(relatedModel)}s, which won't correctly handle irregular plurals (e.g., "person" → "persons" instead of "people", "child" → "childs" instead of "children").

Consider using a pluralization library like pluralize for more robust plural handling, or document this limitation for users to manually adjust relation names when needed.


122-133: Multiple as any type assertions reduce type safety.

Throughout the file (e.g., lines 124, 159, 165, 198, 224, and many others), there are numerous as any casts when constructing AST nodes. While this may be necessary due to circular dependencies in AST node construction, it significantly reduces type safety.

Consider whether typed factory functions or builder patterns could reduce the need for these assertions while maintaining correct AST structure.

packages/auth-adapters/better-auth/src/adapter.ts (2)

70-113: Where clause conversion logic could be simplified.

The convertWhereClause function handles single and multiple where clauses separately with some duplication. Lines 88-96 and 98-106 contain nearly identical mapping logic.

Consider extracting the common mapping logic into a helper function:

const mapWhereCondition = (w: Where) => ({
    [getFieldName({ model, field: w.field })]:
        w.operator === 'eq' || !w.operator
            ? w.value
            : {
                  [operatorToORMOperator(w.operator)]: w.value,
              },
});

const convertWhereClause = (model: string, where?: Where[]): any => {
    if (!where || !where.length) return {};
    if (where.length === 1) {
        const w = where[0]!;
        if (!w) {
            throw new BetterAuthError('Invalid where clause');
        }
        return mapWhereCondition(w);
    }
    const and = where.filter((w) => w.connector === 'AND' || !w.connector);
    const or = where.filter((w) => w.connector === 'OR');
    const andClause = and.map(mapWhereCondition);
    const orClause = or.map(mapWhereCondition);

    return {
        ...(andClause.length ? { AND: andClause } : {}),
        ...(orClause.length ? { OR: orClause } : {}),
    };
};

148-148: Consider making default limit configurable.

The default limit of 100 for findMany operations is hardcoded. Depending on the use case, this might be too high or too low.

Consider making this configurable through AdapterConfig to allow users to adjust based on their performance requirements.

📜 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 160437a and 6390570.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • packages/auth-adapters/better-auth/eslint.config.js (1 hunks)
  • packages/auth-adapters/better-auth/package.json (1 hunks)
  • packages/auth-adapters/better-auth/src/adapter.ts (1 hunks)
  • packages/auth-adapters/better-auth/src/index.ts (1 hunks)
  • packages/auth-adapters/better-auth/src/schema-generator.ts (1 hunks)
  • packages/auth-adapters/better-auth/tsconfig.json (1 hunks)
  • packages/auth-adapters/better-auth/tsup.config.ts (1 hunks)
  • packages/auth-adapters/better-auth/vitest.config.ts (1 hunks)
  • packages/cli/src/actions/action-utils.ts (1 hunks)
  • packages/language/src/zmodel-code-generator.ts (4 hunks)
  • packages/orm/src/client/crud-types.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 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:

  • packages/auth-adapters/better-auth/src/schema-generator.ts
🧬 Code graph analysis (3)
packages/orm/src/client/crud-types.ts (2)
packages/schema/src/schema.ts (2)
  • SchemaDef (11-19)
  • GetModels (120-120)
packages/orm/src/utils/type-utils.ts (2)
  • OrArray (52-52)
  • XOR (70-70)
packages/auth-adapters/better-auth/src/schema-generator.ts (5)
packages/auth-adapters/better-auth/src/adapter.ts (1)
  • AdapterConfig (16-35)
packages/common-helpers/src/upper-case-first.ts (1)
  • upperCaseFirst (1-3)
packages/language/src/zmodel-code-generator.ts (2)
  • ZModelCodeGenerator (71-388)
  • fieldType (180-187)
packages/language/src/generated/ast.ts (1)
  • isDataModel (391-393)
packages/common-helpers/src/lower-case-first.ts (1)
  • lowerCaseFirst (1-3)
packages/auth-adapters/better-auth/src/adapter.ts (4)
packages/schema/src/schema.ts (2)
  • SchemaDef (11-19)
  • GetModels (120-120)
packages/orm/src/client/contract.ts (2)
  • ClientContract (52-172)
  • ModelOperations (803-807)
packages/orm/src/client/crud-types.ts (1)
  • UpdateInput (890-894)
packages/auth-adapters/better-auth/src/schema-generator.ts (1)
  • generateSchema (31-57)
⏰ 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). (5)
  • GitHub Check: Agent
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: claude-review
  • GitHub Check: build-test (20.x, postgresql)
  • GitHub Check: build-test (20.x, sqlite)
🔇 Additional comments (12)
packages/orm/src/client/crud-types.ts (2)

781-794: Exposing CreateManyInput and CreateInput looks correct and non-breaking

Making these input helpers exported aligns them with the rest of the CRUD typings and is an additive, type-only change (no runtime impact). The generic parameters and Without handling remain unchanged, so existing internal usage should continue to work as before.


890-894: Exporting UpdateInput completes the CRUD input surface

Promoting UpdateInput to an exported type gives external consumers parity with create inputs and matches the surrounding API design. The alias still composes UpdateScalarInput and UpdateRelationInput identically, so there’s no behavioral change—just expanded type visibility.

packages/auth-adapters/better-auth/tsconfig.json (1)

1-8: LGTM!

The TypeScript configuration is standard and appropriate for the new adapter package. Extending the base config and including src/**/* is correct.

packages/language/src/zmodel-code-generator.ts (3)

201-201: Systematic refactor to $refText looks good.

The change from resolved(ast.decl).name to ast.decl.$refText is consistent with the overall refactoring pattern in this file.


267-267: LGTM on reference expression refactor.

The systematic change to use $refText for reference expressions, member access, and invocations is consistent and cleaner than the previous approach.

Also applies to: 277-277, 282-282


163-163: Refactor to $refText for mixins is correct and verified.

The change properly uses Langium's built-in $refText property for cross-reference text, which is the standard approach in this codebase (see line 201 for identical pattern with attributes). Generated schemas correctly produce mixin declarations like model M mixes A, B { ... }, and existing E2E tests validate that mixin fields and attributes are properly inherited and generated.

packages/auth-adapters/better-auth/vitest.config.ts (1)

1-4: LGTM!

Standard Vitest configuration extending the base config.

packages/auth-adapters/better-auth/src/index.ts (1)

1-1: LGTM!

Standard re-export pattern for the public API surface.

packages/auth-adapters/better-auth/tsup.config.ts (1)

1-13: LGTM!

The tsup configuration is properly set up for dual ESM/CJS output with type declarations and source maps.

packages/auth-adapters/better-auth/package.json (1)

21-36: LGTM on exports configuration!

The exports map is properly configured for dual ESM/CJS support with correct type definitions for each format. The explicit ./package.json export is a good practice.

packages/auth-adapters/better-auth/eslint.config.js (1)

5-9: Remove the @typescript-eslint/no-unused-expressions disable—no violations exist in the adapter code.

After analyzing all source files (adapter.ts, index.ts, schema-generator.ts), no patterns that violate this rule were found. All expressions are properly assigned, awaited, or produce side effects. Disabling this rule package-wide unnecessarily relaxes linting standards without justification. The current code adheres to best practices and would pass this rule without modification.

packages/auth-adapters/better-auth/src/adapter.ts (1)

42-241: LGTM with minor concerns - Well-structured adapter implementation.

The adapter implementation correctly translates BetterAuth operations to ZenStack ORM calls. The transaction support is properly implemented using the lazy options pattern, and the helper functions appropriately handle field name mapping and operator conversion.

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 introduces a Better-Auth adapter for ZenStack, allowing users to integrate Better-Auth authentication with ZenStack ORM. The implementation includes schema generation capabilities, type exports for better API support, and improvements to the ZModel code generator.

Key Changes

  • New @zenstackhq/better-auth package providing adapter functionality for Better-Auth integration
  • Exported additional types (CreateInput, CreateManyInput, UpdateInput) from crud-types.ts to support external adapter implementations
  • Refactored ZModel code generator to use $refText instead of resolved references for more reliable code generation
  • Updated schema file search priority in CLI to check ./schema.zmodel before ./zenstack/schema.zmodel

Reviewed Changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
pnpm-lock.yaml Added Better-Auth dependencies and related packages for authentication support
packages/orm/src/client/crud-types.ts Exported CreateInput, CreateManyInput, and UpdateInput types for external use
packages/language/src/zmodel-code-generator.ts Changed reference resolution to use $refText instead of ref?.name
packages/cli/src/actions/action-utils.ts Reversed schema file search priority order
packages/auth-adapters/better-auth/* New adapter package with configuration, implementation, and schema generation
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

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

@claude
Copy link

claude bot commented Nov 18, 2025

Claude finished @ymc9's task —— View job


Claude finished @ymc9's task —— View job


Code Review: Better Auth Adapter

Reviewing the new better-auth adapter implementation. Here's my analysis checklist:

Review Tasks:

  • Analyze adapter.ts implementation
  • Review schema-generator.ts logic
  • Check package configuration and dependencies
  • Examine integration with existing ZenStack code
  • Assess security considerations
  • Evaluate performance implications
  • Check for test coverage
  • Provide comprehensive feedback

📋 Code Review Summary

Strengths

  1. Well-structured adapter implementation - The zenstackAdapter follows Better Auth's adapter factory pattern correctly
  2. Comprehensive CRUD operations - Full support for create, read, update, delete with proper where clause conversion
  3. Robust schema generation - Intelligent ZModel schema generation from Better Auth table definitions
  4. Transaction support - Proper implementation of database transactions
  5. Type safety - Good use of TypeScript generics and type constraints

⚠️ Issues & Concerns

Critical Issues

  1. Missing Test Coverage (packages/auth-adapters/better-auth/src/):

    • No test files found for this critical authentication adapter
    • Complex logic in schema generation and CRUD operations needs comprehensive testing
    • Risk: Production bugs, security vulnerabilities, integration failures
  2. Silent Error Handling (adapter.ts:192-197):

    try {
        await modelDb.delete({ where: whereClause });
    } catch {
        // If the record doesn't exist, we don't want to throw an error
    }
    • Silently catches ALL exceptions, not just "record not found"
    • Risk: Database connection errors, constraint violations masked

Security Concerns

  1. SQL Injection Prevention (adapter.ts:70-113):

    • Where clause conversion logic looks sound but needs security testing
    • Operator mapping is comprehensive: starts_with, ends_with, ne, not_in
    • Recommendation: Add explicit tests for injection attempts
  2. Input Validation (adapter.ts:115-123):

    • Model existence check is good, but error message reveals internal structure
    • Consider sanitizing error messages for production

Code Quality Issues

  1. Hard-coded Magic Values (adapter.ts:148, schema-generator.ts:237):

    • Default limit of 100 in findMany should be configurable
    • Hard-coded SQLite database path file:./test.db
  2. TODO Comment (schema-generator.ts:40):

    • TODO for respecting package.json zenstack configuration
    • Should be addressed before production release
  3. Console Warnings (schema-generator.ts:337-340, 347-351):

    • Multiple console.warn calls for unsupported features
    • Consider using structured logging instead

🏗️ Architecture & Integration

Positive:

  • Clean integration with ZenStack's ORM client contract
  • Proper use of workspace dependencies
  • Follows monorepo conventions with appropriate peer dependencies

Integration Points Reviewed:

  • CLI integration (packages/cli/src/actions/action-utils.ts): Minor changes to schema file resolution ✅
  • Language integration (packages/language/src/zmodel-code-generator.ts): AST generation improvements ✅
  • ORM integration (packages/orm/src/client/crud-types.ts): Type definition enhancements ✅

🚀 Performance Considerations

  • Lazy initialization of Better Auth options is efficient
  • Schema generation happens at build time, not runtime ✅
  • Transaction implementation delegates properly to ZenStack's transaction system ✅

📦 Package Configuration

Good practices:

  • Proper peer dependencies for Better Auth
  • ESM/CJS dual export support
  • TypeScript configuration follows project standards

🛠️ Recommendations

High Priority (Must Fix)

  1. Add comprehensive test suite covering:

    • CRUD operations with various data types
    • Where clause conversion edge cases
    • Schema generation scenarios
    • Error handling paths
    • Security injection attempts
  2. Improve error handling in delete operations:

    // Instead of catching all errors:
    try {
        const result = await modelDb.delete({ where: whereClause });
        return result;
    } catch (error) {
        if (isRecordNotFoundError(error)) {
            return null; // or appropriate response
        }
        throw error; // Re-throw unexpected errors
    }

Medium Priority

  1. Address TODO comment - Implement package.json zenstack configuration support
  2. Make configurations configurable - Remove hard-coded values
  3. Implement structured logging instead of console.warn

Low Priority

  1. Add JSDoc documentation for public APIs
  2. Consider adding integration examples in package README

🔒 Security Assessment

Overall: Acceptable with testing

  • Input sanitization appears adequate
  • No obvious SQL injection vectors
  • Error messages could be more production-friendly
  • Requires: Security-focused testing before production use

📊 Final Rating

Code Quality: B+ - Well-structured with room for improvement
Security: B - Looks secure but needs validation through testing
Performance: A- - Efficient design patterns
Test Coverage: F - Critical gap that must be addressed

Overall Recommendation: Approve with required changes - The foundation is solid, but testing is essential before merging.


Job run: https://github.com/zenstackhq/zenstack-v3/actions/runs/19449839966

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: 1

♻️ Duplicate comments (6)
packages/auth-adapters/better-auth/src/adapter.ts (1)

178-186: Type assertion bypasses validation on update payload.

Similar to the update operation, the updateMany operation passes the update parameter directly as data without type validation. While TypeScript infers compatibility, runtime validation would prevent issues if BetterAuth's update structure differs from ZenStack's expectations.

packages/auth-adapters/better-auth/src/schema-generator.ts (5)

75-93: Consider adding explicit type annotation for clarity.

The toManyRelations map (line 76) lacks an explicit type annotation, which would improve code maintainability and catch potential type errors earlier.

Based on learnings: When working with mapped data structures that track relationships, explicit typing helps prevent errors when the structure is complex.


232-240: Hardcoded SQLite database path limits flexibility.

The SQLite URL defaults to 'file:./dev.db' (line 236), which is a development-specific path. This should be configurable to support different environments and deployment scenarios.


284-288: Field existence check only verifies name, not definition.

The check on line 286 only verifies if a field name exists but doesn't validate whether the field's type, attributes, or other properties have changed. If BetterAuth updates field definitions, the generated schema could become out of sync.


354-356: Foreign key field addition doesn't check for duplicates.

When adding a foreign key field (line 355), there's no check to see if the field already exists, unlike the scalar field handling at line 286. This could lead to duplicate fields or errors.


119-132: Type assertion bypasses safety when constructing AST nodes.

The AttributeArg is created with as any (line 123), which bypasses TypeScript's type checking. This pattern is repeated throughout the file (lines 164, 197, 208, 302, 368, 400, 422, 444, 472, 524, 537).

🧹 Nitpick comments (3)
packages/auth-adapters/better-auth/src/adapter.ts (2)

143-159: Consider making the default limit configurable.

The findMany operation uses a hardcoded default limit of 100 records (line 148). For production use cases, this default might be too restrictive or too permissive depending on the data model and query patterns.

Consider adding a defaultLimit option to AdapterConfig to allow users to configure this behavior:

 export interface AdapterConfig {
     provider: 'sqlite' | 'postgresql';
     debugLogs?: DBAdapterDebugLogOption | undefined;
     usePlural?: boolean | undefined;
+    defaultLimit?: number | undefined;
 }

Then use it in the adapter:

         return await modelDb.findMany({
             where: whereClause,
-            take: limit || 100,
+            take: limit || config.defaultLimit || 100,
             skip: offset || 0,

223-230: Non-null assertion assumes lazyOptions is set.

The transaction callback uses lazyOptions! (line 228) and adapterOptions!.config (line 226). While the code structure ensures these are set before transactions run, the non-null assertions reduce type safety.

Consider restructuring to avoid non-null assertions:

 transaction: (cb) =>
     db.$transaction((tx) => {
+        if (!lazyOptions) {
+            throw new Error('Adapter not initialized - call returned function first');
+        }
         const adapter = createAdapterFactory({
-            config: adapterOptions!.config,
+            config: adapterOptions.config,
             adapter: createCustomAdapter(tx as ClientContract<Schema>),
-        })(lazyOptions!);
+        })(lazyOptions);
         return cb(adapter);
     }),
packages/auth-adapters/better-auth/src/schema-generator.ts (1)

460-486: Simple pluralization won't handle irregular plural forms.

The to-many relation naming on line 464 uses ${lowerCaseFirst(relatedModel)}s, which simply appends 's'. This won't work correctly for irregular plurals (e.g., "Person" → "Persons" instead of "People", "Child" → "Childs" instead of "Children").

Consider using a pluralization library or allowing custom relation names:

// Option 1: Use a library like 'pluralize'
import pluralize from 'pluralize';
const relationName = lowerCaseFirst(pluralize(relatedModel));

// Option 2: Add config option for custom relation naming
// This would require extending BetterAuthDBSchema or AdapterConfig

Alternatively, document this limitation so users know to manually adjust relation names for irregular plurals after generation.

📜 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 6390570 and 167e185.

📒 Files selected for processing (3)
  • packages/auth-adapters/better-auth/package.json (1 hunks)
  • packages/auth-adapters/better-auth/src/adapter.ts (1 hunks)
  • packages/auth-adapters/better-auth/src/schema-generator.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 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:

  • packages/auth-adapters/better-auth/src/schema-generator.ts
🧬 Code graph analysis (2)
packages/auth-adapters/better-auth/src/schema-generator.ts (5)
packages/auth-adapters/better-auth/src/adapter.ts (1)
  • AdapterConfig (16-35)
packages/common-helpers/src/upper-case-first.ts (1)
  • upperCaseFirst (1-3)
packages/language/src/zmodel-code-generator.ts (2)
  • ZModelCodeGenerator (71-388)
  • fieldType (180-187)
packages/language/src/generated/ast.ts (1)
  • isDataModel (391-393)
packages/common-helpers/src/lower-case-first.ts (1)
  • lowerCaseFirst (1-3)
packages/auth-adapters/better-auth/src/adapter.ts (4)
packages/schema/src/schema.ts (2)
  • SchemaDef (11-19)
  • GetModels (120-120)
packages/orm/src/client/contract.ts (2)
  • ClientContract (52-172)
  • ModelOperations (803-807)
packages/orm/src/client/crud-types.ts (1)
  • UpdateInput (890-894)
packages/auth-adapters/better-auth/src/schema-generator.ts (1)
  • generateSchema (30-56)
⏰ 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). (3)
  • GitHub Check: claude-review
  • GitHub Check: build-test (20.x, sqlite)
  • GitHub Check: build-test (20.x, postgresql)
🔇 Additional comments (2)
packages/auth-adapters/better-auth/package.json (1)

37-53: Better‑Auth dependency alignment looks good now

peerDependencies and devDependencies for @better-auth/core / better-auth are now consistently ^1.3.0, which matches the tested range and avoids version skew for consumers.

packages/auth-adapters/better-auth/src/schema-generator.ts (1)

30-56: LGTM! Clear default schema path resolution.

The function correctly handles schema path resolution with sensible defaults (./schema.zmodel or ./zenstack/schema.zmodel) and properly determines overwrite behavior based on file existence.

@ymc9 ymc9 merged commit c27e25d into dev Nov 18, 2025
7 checks passed
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