Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Sep 12, 2025

Summary by CodeRabbit

  • Refactor

    • Code generator now omits a runtime utility import when unused, reducing generated code size.
  • Tests

    • Added a regression test suite with generation script, schema/models/tests for issue-204, and automated test run.
  • Chores

    • Added a dedicated regression test package with scripts, TypeScript and Vitest configs.
    • Minor housekeeping: removed an obsolete inline comment in a test helper script.

Copilot AI review requested due to automatic review settings September 12, 2025 06:32
@coderabbitai
Copy link

coderabbitai bot commented Sep 12, 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 conditional import emission for ExpressionUtils in the TS schema generator, introduces a regression test workspace with generator and configs, and adds an issue-204 regression case (schema, generated artifacts, and test). Also removes a single inline comment in a runtime test script.

Changes

Cohort / File(s) Summary
Codegen: conditional ExpressionUtils import
packages/sdk/src/ts-schema-generator.ts
Adds a usedExpressionUtils flag, precomputes schemaObject, emits ExpressionUtils import only when used, introduces createExpressionUtilsCall helper, and routes expression-generation calls through it; reuses precomputed schema for emission.
Regression test workspace
tests/regression/package.json, tests/regression/tsconfig.json, tests/regression/vitest.config.ts, tests/regression/generate.ts
Adds a new regression package with scripts, TypeScript config, Vitest config, and a generator script that discovers .zmodel files, loads them with plugin definitions, and emits TypeScript schemas.
Regression case: issue-204
tests/regression/test/issue-204/regression.zmodel, .../schema.ts, .../models.ts, .../input.ts, .../regression.test.ts
Introduces a new zmodel (datasource, enum ShirtColor, type Configuration, model Foo), generated TS schema and model/enum exports, many model arg type aliases, and a Vitest regression exercising optional enum array typing.
Test script cleanup
packages/runtime/test/scripts/generate.ts
Removes a single inline comment; no behavioral changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • feat: generate input types #94 — Modifies ts-schema-generator.ts and changes code-generation/import emission behavior; likely overlaps with the conditional import work in this PR.

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title accurately and concisely captures the two primary changes in the changeset: adding a regression project and optimizing the TypeScript schema generation logic. It is specific, focused, and free of noisy details or emojis, so a reviewer scanning history will understand the main intent.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Poem

I nibble schemas, quiet and spry,
Import only when ExpressionUtils is nigh.
Tests planted deep in a regression bed,
Shirt colors flutter where carrots are fed.
Hop—codegen skips what it needn't try. 🥕🐇

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test/regression

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 Sep 12, 2025

Claude finished @ymc9's task —— View job


Pull Request Review

I've completed a comprehensive review of this pull request. Here's my feedback on code quality, potential issues, performance, security, and test coverage.

Todo List:

  • Read and understand the changed files
  • Review ts-schema-generator.ts optimizations
  • Review regression test structure and setup
  • Analyze code quality and best practices
  • Check for potential bugs or issues
  • Evaluate performance considerations
  • Assess security concerns
  • Review test coverage
  • Provide comprehensive feedback via GitHub comment

Code Quality & Best Practices ✅

TypeScript Schema Generator Optimizations (packages/sdk/src/ts-schema-generator.ts)

Excellent improvements:

  • Smart import generation: The new pattern of determining imports based on actual usage (usedExpressionUtils flag) is a significant improvement over static imports
  • Clean architecture: The createExpressionUtilsCall() method centralizes ExpressionUtils usage tracking
  • Proper separation of concerns: Schema content generation happens first, then imports are determined based on what was actually used

Code organization:

  • Methods are well-structured and follow single responsibility principle
  • Good use of TypeScript factory patterns for AST generation
  • Proper error handling with informative error messages

Regression Test Structure (tests/regression/)

Well-designed test infrastructure:

  • Clean separation of test cases by issue number
  • Proper use of workspace dependencies
  • Follows established project conventions for testing

Performance Considerations ✅

Significant optimizations:

  1. Reduced bundle size: Only imports ExpressionUtils when actually needed, reducing generated code size
  2. Conditional imports: The dynamic import determination prevents unnecessary runtime dependencies
  3. Efficient AST generation: Uses TypeScript compiler API efficiently without redundant operations

Key performance improvements:

// Before: Always imported ExpressionUtils
// After: Only imports when this.usedExpressionUtils is true
...(this.usedExpressionUtils
    ? [ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier('ExpressionUtils'))]
    : []),

Security Concerns ✅

No security issues identified:

  • File system operations use proper path handling with path.join()
  • No dynamic code execution or eval usage
  • Input validation through TypeScript compiler API
  • Generated code follows safe patterns

Potential Issues & Bugs ✅

No critical bugs found. The changes are well-implemented with proper:

  • Error handling in loadDocument() calls
  • Type safety throughout the generator
  • Proper AST node creation patterns

Minor considerations:

  • The usedExpressionUtils flag is properly reset between generations (line 61)
  • All dynamic import decisions are based on deterministic analysis

Test Coverage ✅

Comprehensive test setup for issue-204:

  1. ZModel schema: Tests optional enum arrays (teamColors ShirtColor[]?)
  2. Generated TypeScript: Verifies correct type inference and compilation
  3. Runtime test: Validates actual usage patterns with both populated and empty configurations
  4. Type checking: Ensures TypeScript compilation passes

Test structure:

// tests/regression/test/issue-204/regression.test.ts
const config: Configuration = { teamColors: [ShirtColor.Black, ShirtColor.Blue] };
const config1: Configuration = {}; // Tests optional nature

Overall Assessment ⭐

This is a high-quality pull request that delivers meaningful optimizations:

Strengths:

  • Performance optimization: Smart import generation reduces bundle size
  • Maintainable code: Clean separation of concerns and good architecture
  • Comprehensive testing: Well-structured regression test for the specific issue
  • Type safety: Maintains strong TypeScript inference throughout

Technical Excellence:

  • Proper use of TypeScript compiler API
  • Efficient AST generation patterns
  • Clean error handling and validation
  • Good separation between schema generation and import determination

No Action Required:

  • No bugs or security issues found
  • Code quality meets project standards
  • Test coverage is appropriate for the changes

Recommendation: ✅ Approve and merge

This PR successfully addresses the regression issue while delivering meaningful performance improvements through smarter import generation.


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 adds a regression testing project and optimizes TypeScript schema generation by conditionally importing the ExpressionUtils utility. The optimization reduces bundle size by only importing ExpressionUtils when it's actually used in the generated schema.

  • Adds a regression testing framework with test case for issue 204
  • Optimizes TS schema generation to conditionally import ExpressionUtils
  • Updates comment in existing test generation script

Reviewed Changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 1 comment.

File Description
tests/regression/* New regression testing project with configuration, test case for issue 204, and generation script
packages/sdk/src/ts-schema-generator.ts Optimizes schema generation by tracking ExpressionUtils usage and conditionally importing it
packages/runtime/test/scripts/generate.ts Minor comment update in existing test generation script
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

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

🧹 Nitpick comments (5)
tests/regression/tsconfig.json (1)

6-6: Include the root-level script for type-checking (or explicitly exclude it).

tests/regression/generate.ts won’t be type-checked with the current include globs. If you intend to type-check it, add the root pattern.

-    "include": ["src/**/*.ts", "test/**/*.ts"]
+    "include": ["*.ts", "src/**/*.ts", "test/**/*.ts"]
tests/regression/test/issue-204/regression.test.ts (1)

5-11: Make the regression meaningful: replace logs with type assertions.

The test currently has no assertions. Use expectTypeOf to assert optional-array typing and remove console.log.

-import { describe, it } from 'vitest';
+import { describe, it, expectTypeOf } from 'vitest';
@@
-    it('tests issue 204', () => {
-        const config: Configuration = { teamColors: [ShirtColor.Black, ShirtColor.Blue] };
-        console.log(config.teamColors?.[0]);
-        const config1: Configuration = {};
-        console.log(config1);
-    });
+    it('tests issue 204', () => {
+        const config: Configuration = { teamColors: [ShirtColor.Black, ShirtColor.Blue] };
+        const config1: Configuration = {};
+        // teamColors is optional and, when present, is an array; element access is safe-optional
+        expectTypeOf(config).toMatchTypeOf<Configuration>();
+        expectTypeOf(config1).toMatchTypeOf<Configuration>();
+        // Adjust the expected union as needed based on your TypeDef mapping
+        // Example expectation:
+        // expectTypeOf<Configuration['teamColors']>().toEqualTypeOf<ShirtColor[] | null | undefined>();
+    });
tests/regression/generate.ts (3)

21-21: Remove unused variable.

tsPath is never used.

-    const tsPath = path.join(outputDir, 'schema.ts');

24-27: Surface non-fatal warnings to aid debugging.

Log result.warnings so flaky schema issues are visible in CI.

     if (!result.success) {
         throw new Error(`Failed to load schema from ${schemaPath}: ${result.errors}`);
     }
+    if (result.warnings?.length) {
+        console.warn(`Loaded with warnings for ${schemaPath}:\n- ${result.warnings.join('\n- ')}`);
+    }

30-30: Handle top-level rejections for clean CI failures.

Catch and exit on errors to avoid noisy unhandled-rejection traces.

-main();
+main().catch((err) => {
+    console.error(err);
+    process.exit(1);
+});
📜 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 71935e0 and 097c037.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • packages/runtime/test/scripts/generate.ts (0 hunks)
  • packages/sdk/src/ts-schema-generator.ts (10 hunks)
  • tests/regression/generate.ts (1 hunks)
  • tests/regression/package.json (1 hunks)
  • tests/regression/test/issue-204/input.ts (1 hunks)
  • tests/regression/test/issue-204/models.ts (1 hunks)
  • tests/regression/test/issue-204/regression.test.ts (1 hunks)
  • tests/regression/test/issue-204/regression.zmodel (1 hunks)
  • tests/regression/test/issue-204/schema.ts (1 hunks)
  • tests/regression/tsconfig.json (1 hunks)
  • tests/regression/vitest.config.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/runtime/test/scripts/generate.ts
🧰 Additional context used
📓 Path-based instructions (2)
{packages,samples,tests}/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place packages only under packages/, samples/, or tests/

Files:

  • tests/regression/test/issue-204/regression.test.ts
  • tests/regression/test/issue-204/schema.ts
  • tests/regression/vitest.config.ts
  • tests/regression/test/issue-204/models.ts
  • tests/regression/generate.ts
  • tests/regression/test/issue-204/regression.zmodel
  • tests/regression/test/issue-204/input.ts
  • tests/regression/package.json
  • packages/sdk/src/ts-schema-generator.ts
  • tests/regression/tsconfig.json
**/schema.ts

📄 CodeRabbit inference engine (CLAUDE.md)

The generated TypeScript schema should be named schema.ts

Files:

  • tests/regression/test/issue-204/schema.ts
🧠 Learnings (1)
📚 Learning: 2025-09-04T12:38:14.150Z
Learnt from: CR
PR: zenstackhq/zenstack-v3#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-04T12:38:14.150Z
Learning: Applies to **/schema.ts : The generated TypeScript schema should be named `schema.ts`

Applied to files:

  • tests/regression/test/issue-204/schema.ts
  • tests/regression/test/issue-204/models.ts
  • tests/regression/generate.ts
  • packages/sdk/src/ts-schema-generator.ts
🧬 Code graph analysis (4)
tests/regression/test/issue-204/regression.test.ts (1)
tests/regression/test/issue-204/models.ts (3)
  • Configuration (11-11)
  • ShirtColor (12-12)
  • ShirtColor (13-13)
tests/regression/test/issue-204/schema.ts (1)
packages/sdk/src/schema/schema.ts (1)
  • SchemaDef (10-18)
tests/regression/generate.ts (2)
packages/sdk/src/ts-schema-generator.ts (1)
  • generate (57-71)
packages/language/src/index.ts (1)
  • loadDocument (21-132)
packages/sdk/src/ts-schema-generator.ts (2)
packages/language/src/generated/ast.ts (11)
  • Expression (115-115)
  • Expression (117-117)
  • BinaryExpr (256-262)
  • BinaryExpr (264-264)
  • UnaryExpr (741-746)
  • UnaryExpr (748-748)
  • ArrayExpr (185-189)
  • ArrayExpr (191-191)
  • ReferenceExpr (688-693)
  • ReferenceExpr (695-695)
  • isDataField (344-346)
packages/sdk/src/schema/expression.ts (2)
  • Expression (1-10)
  • CallExpression (46-50)
⏰ 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: claude-review
  • GitHub Check: build-test (20.x)
🔇 Additional comments (20)
tests/regression/vitest.config.ts (1)

1-4: LGTM.

Merges the shared base config with no overrides; straightforward and correct.

tests/regression/test/issue-204/regression.zmodel (1)

14-21: LGTM.

The optional array ShirtColor[]? models the issue well; Foo.config as @json is appropriate for the regression.

packages/sdk/src/ts-schema-generator.ts (14)

55-56: LGTM: usage tracking flag.

The usedExpressionUtils flag is a clean way to conditionally import runtime helpers.


60-62: LGTM: reset usage flag per generation.

Prevents leakage across multiple runs.


90-92: LGTM: precompute schema to decide imports.

Evaluating schemaObject first makes conditional import generation reliable.


134-136: LGTM: as const + satisfies for schema.

This preserves literal types and validates against SchemaDef.


503-513: LGTM: default expressions now mark ExpressionUtils usage consistently.

Routing through the helper ensures the conditional import toggles correctly.

Also applies to: 519-525


1029-1029: LGTM: _this via helper.

Keeps usage tracking unified.


1048-1049: LGTM: member access via helper.

Flattens the chain and records usage correctly.


1052-1053: LGTM: _null via helper.


1056-1061: LGTM: binary expression via helper.


1064-1068: LGTM: unary expression via helper.


1071-1073: LGTM: array expression via helper.


1078-1078: LGTM: field reference via helper.


1087-1093: LGTM: invocation via helper.


110-118: Verify TypeScript >= 4.7 — mixed type/value per‑specifier imports in ts-schema-generator.ts

packages/sdk/src/ts-schema-generator.ts (lines 110–118) emits mixed per‑specifier type and value imports. package.json shows "typescript": "catalog:" (inconclusive). Confirm the actual TypeScript compiler/version used by your build/CI (lockfile or installed tsc). If the project uses < 4.7, update the generator to emit type-only imports or split the import into separate type and value declarations.

tests/regression/package.json (1)

10-12: Double-check runtime vs dev-time placement of @zenstackhq/runtime.

Generated files import @zenstackhq/runtime/schema at runtime. Keeping @zenstackhq/runtime in devDependencies works in a monorepo test harness, but if this package ever runs outside test scripts, move it to dependencies.

tests/regression/test/issue-204/schema.ts (1)

8-59: LGTM: generated schema matches guidelines and structure.

  • File is named schema.ts as required.
  • Types and enums align with the zmodel; export pattern as const satisfies SchemaDef is correct.
tests/regression/test/issue-204/models.ts (1)

8-13: LGTM: clean public surface for model/type exports.

Imports and type/value exports are correct and consistent with the generated schema.

tests/regression/test/issue-204/input.ts (1)

8-30: LGTM: argument and payload type aliases look consistent.

Aliases map correctly to runtime generics; FooGetPayload constraint is appropriate.

@claude
Copy link

claude bot commented Sep 12, 2025

Claude finished @ymc9's task —— View job


Pull Request Review

I've completed a comprehensive review of this pull request. Here's my feedback on code quality, potential issues, performance, security, and test coverage.

Todo List:

  • Read and understand the changed files
  • Review ts-schema-generator.ts optimizations
  • Review regression test structure and setup
  • Analyze code quality and best practices
  • Check for potential bugs or issues
  • Evaluate performance considerations
  • Assess security concerns
  • Review test coverage
  • Provide comprehensive feedback

Code Quality & Best Practices ✅

TypeScript Schema Generator Optimizations (packages/sdk/src/ts-schema-generator.ts)

Excellent improvements:

  • Smart import generation: The new pattern of determining imports based on actual usage (usedExpressionUtils flag) is a significant improvement over static imports
  • Clean architecture: The createExpressionUtilsCall() method centralizes ExpressionUtils usage tracking
  • Proper separation of concerns: Schema content generation happens first, then imports are determined based on what was actually used

Code organization:

  • Methods are well-structured and follow single responsibility principle
  • Good use of TypeScript factory patterns for AST generation
  • Proper error handling with informative error messages

Regression Test Structure (tests/regression/)

Well-designed test infrastructure:

  • Clean separation of test cases by issue number
  • Proper use of workspace dependencies
  • Follows established project conventions for testing

Critical Issues Found ❌

1. Bug in createExpressionUtilsCall method (ts-schema-generator.ts:157)

ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('ExpressionUtils'), method)

Issue: The second parameter should be ts.factory.createIdentifier(method), not the raw string method.

Fix needed:

ts.factory.createPropertyAccessExpression(
    ts.factory.createIdentifier('ExpressionUtils'),
    ts.factory.createIdentifier(method)  // Fix: wrap method in createIdentifier
)

2. Bug in NumberLiteral handling (ts-schema-generator.ts:1099)

.with('NumberLiteral', () =>
    this.createExpressionUtilsCall('literal', [ts.factory.createIdentifier(value as string)]),
)

Issue: ts.factory.createIdentifier("123") creates an invalid identifier. Number literals should use createNumericLiteral.

Fix needed:

.with('NumberLiteral', () =>
    this.createExpressionUtilsCall('literal', [ts.factory.createNumericLiteral(value as string)]),
)

Performance Considerations ✅

Significant optimizations:

  1. Reduced bundle size: Only imports ExpressionUtils when actually needed, reducing generated code size
  2. Conditional imports: The dynamic import determination prevents unnecessary runtime dependencies
  3. Efficient AST generation: Uses TypeScript compiler API efficiently without redundant operations

Key performance improvements:

// Before: Always imported ExpressionUtils
// After: Only imports when this.usedExpressionUtils is true
...(this.usedExpressionUtils
    ? [ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier('ExpressionUtils'))]
    : []),

Security Concerns ✅

No security issues identified:

  • File system operations use proper path handling with path.join()
  • No dynamic code execution or eval usage
  • Input validation through TypeScript compiler API
  • Generated code follows safe patterns

Test Coverage ✅

Comprehensive test setup for issue-204:

  1. ZModel schema: Tests optional enum arrays (teamColors ShirtColor[]?)
  2. Generated TypeScript: Verifies correct type inference and compilation
  3. Runtime test: Validates actual usage patterns with both populated and empty configurations
  4. Type checking: Ensures TypeScript compilation passes

Test structure:

// tests/regression/test/issue-204/regression.test.ts
const config: Configuration = { teamColors: [ShirtColor.Black, ShirtColor.Blue] };
const config1: Configuration = {}; // Tests optional nature

Minor Issues

1. Missing dependencies in regression package (tests/regression/package.json)

Scripts reference tsx, tsc, and vitest but they're not in devDependencies. Consider:

  • Adding them as devDependencies, or
  • Using workspace binaries: pnpm -w exec tsx generate.ts

2. Unused variable in generate.ts

const tsPath = path.join(outputDir, 'schema.ts'); // Line 21 - never used

3. Test could be more meaningful

The regression test only logs values. Consider adding actual assertions:

expectTypeOf(config).toMatchTypeOf<Configuration>();
expect(config.teamColors).toEqual([ShirtColor.Black, ShirtColor.Blue]);

Overall Assessment ⭐

This is a high-quality pull request that delivers meaningful optimizations, but contains 2 critical bugs that need to be fixed before merging.

Strengths:

  • Performance optimization: Smart import generation reduces bundle size
  • Maintainable code: Clean separation of concerns and good architecture
  • Comprehensive testing: Well-structured regression test for the specific issue
  • Type safety: Maintains strong TypeScript inference throughout

Critical Issues:

  • 2 bugs in TypeScript AST generation that will cause runtime failures
  • These should be fixed immediately as they affect core functionality

Recommendation: 🔄 Request changes to fix the critical bugs, then approve for merge.


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

♻️ Duplicate comments (3)
packages/sdk/src/ts-schema-generator.ts (3)

90-92: Precomputing schemaObject before emitting imports: consider documenting or two-pass scan

This inversion works to gate imports, but it inverts the usual “imports-first” flow. Either add a brief comment here explaining the necessity, or introduce a cheap first pass to detect ExpressionUtils usage without building the full object.


1070-1074: Tighten return types; avoid undefined from createLiteralNode

These helpers are expressions; returning any (and potentially undefined) weakens types and risks bad nodes during refactors.

Apply:

-    private createArrayExpression(expr: ArrayExpr): any {
+    private createArrayExpression(expr: ArrayExpr): ts.Expression {
         return this.createExpressionUtilsCall('array', [
             ts.factory.createArrayLiteralExpression(expr.items.map((item) => this.createExpression(item))),
         ]);
     }

-    private createRefExpression(expr: ReferenceExpr): any {
+    private createRefExpression(expr: ReferenceExpr): ts.Expression {
         if (isDataField(expr.target.ref)) {
             return this.createExpressionUtilsCall('field', [this.createLiteralNode(expr.target.$refText)]);
         } else if (isEnumField(expr.target.ref)) {
             return this.createLiteralExpression('StringLiteral', expr.target.$refText);
         } else {
             throw new Error(`Unsupported reference type: ${expr.target.$refText}`);
         }
     }

-    private createLiteralNode(arg: string | number | boolean | null): any {
-        return arg === null
-            ? ts.factory.createNull()
-            : typeof arg === 'string'
-              ? ts.factory.createStringLiteral(arg)
-              : typeof arg === 'number'
-                ? ts.factory.createNumericLiteral(arg)
-                : arg === true
-                  ? ts.factory.createTrue()
-                  : arg === false
-                    ? ts.factory.createFalse()
-                    : undefined;
-    }
+    private createLiteralNode(arg: string | number | boolean | null): ts.Expression {
+        return arg === null
+            ? ts.factory.createNull()
+            : typeof arg === 'string'
+            ? ts.factory.createStringLiteral(arg)
+            : typeof arg === 'number'
+            ? ts.factory.createNumericLiteral(arg)
+            : arg
+            ? ts.factory.createTrue()
+            : ts.factory.createFalse();
+    }

Also applies to: 1076-1084, 887-899


1097-1102: Bug: NumberLiteral uses Identifier instead of NumericLiteral

Constructing number nodes as identifiers produces invalid TS. Use createNumericLiteral (or parse then reuse createLiteralNode).

Apply:

-            .with('NumberLiteral', () =>
-                this.createExpressionUtilsCall('literal', [ts.factory.createIdentifier(value as string)]),
-            )
+            .with('NumberLiteral', () =>
+                this.createExpressionUtilsCall('literal', [
+                    ts.factory.createNumericLiteral(value as string),
+                ]),
+            )
🧹 Nitpick comments (1)
packages/sdk/src/ts-schema-generator.ts (1)

159-160: Use nullish coalescing for args

Minor: prefer args ?? [] to avoid future surprises if an empty array is ever intentionally passed.

-            args || [],
+            args ?? [],
📜 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 097c037 and 295ce40.

📒 Files selected for processing (1)
  • packages/sdk/src/ts-schema-generator.ts (10 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{packages,samples,tests}/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place packages only under packages/, samples/, or tests/

Files:

  • packages/sdk/src/ts-schema-generator.ts
🧠 Learnings (1)
📚 Learning: 2025-09-04T12:38:14.150Z
Learnt from: CR
PR: zenstackhq/zenstack-v3#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-04T12:38:14.150Z
Learning: Applies to **/schema.ts : The generated TypeScript schema should be named `schema.ts`

Applied to files:

  • packages/sdk/src/ts-schema-generator.ts
🧬 Code graph analysis (1)
packages/sdk/src/ts-schema-generator.ts (2)
packages/language/src/generated/ast.ts (13)
  • Model (559-563)
  • Model (565-565)
  • Expression (115-115)
  • Expression (117-117)
  • BinaryExpr (256-262)
  • BinaryExpr (264-264)
  • UnaryExpr (741-746)
  • UnaryExpr (748-748)
  • ArrayExpr (185-189)
  • ArrayExpr (191-191)
  • ReferenceExpr (688-693)
  • ReferenceExpr (695-695)
  • isDataField (344-346)
packages/sdk/src/schema/expression.ts (2)
  • Expression (1-10)
  • CallExpression (46-50)
⏰ 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 (20.x)
  • GitHub Check: claude-review
🔇 Additional comments (6)
packages/sdk/src/ts-schema-generator.ts (6)

55-62: Usage flag for ExpressionUtils + reset per generation: LGTM

The boolean gate is simple and effective; resetting it at the start of generate avoids cross-run leakage.


110-118: Conditional import emission for ExpressionUtils: LGTM

Importing ExpressionUtils only when used keeps the generated schema.ts trim.


154-158: Fixed callee construction: property access over string identifier is correct

Switching to ExpressionUtils.method via createPropertyAccessExpression resolves the invalid identifier bug.


503-513: Default value mapping via ExpressionUtils (call/member): LGTM

Shaping defaults through the same helper ensures the usage flag is set consistently.

Also applies to: 519-525


1029-1030: _this/_null routed through ExpressionUtils: LGTM

Keeps expression construction uniform.

Also applies to: 1052-1053


1048-1049: Unified ExpressionUtils path for member/binary/unary/array/field/call: LGTM

This centralization reduces drift and makes gating reliable.

Also applies to: 1056-1061, 1064-1068, 1071-1073, 1078-1079, 1087-1093

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