Skip to content

fix: v0.5.5 — parser brace-counting, implicit relations, FK ordering - #63

Merged
teetangh merged 1 commit into
mainfrom
fix/v0.5.5-parser-and-registry
Apr 4, 2026
Merged

fix: v0.5.5 — parser brace-counting, implicit relations, FK ordering#63
teetangh merged 1 commit into
mainfrom
fix/v0.5.5-parser-and-registry

Conversation

@teetangh

@teetangh teetangh commented Apr 4, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes 3 critical parser/generator bugs found during schema verification.

Bug 1: Inline comments with {/} truncate model parsing

  • preferences Json? // e.g., { preferredDates: [], maxPrice: 500 } — the } in the comment closed the regex match
  • Fix: Replaced [^}]+ regex with brace-counting _extractBlocks() for both model and enum parsing
  • Impact: Waitlist model was missing userId, webinarId, classId fields

Bug 2: Implicit relations not detected

  • Fields like subDomains SubDomain[] (no @relation attribute) were parsed as non-relation fields
  • Fix: Parser now checks if fieldType is a known model name in addition to @relation
  • Impact: Domain model was missing all 3 relations in schema_registry

Bug 3: Wrong FK for multi-relation models

  • ModerationReport has reportedBy→User and targetUser→User. Generator picked first match's FK for both.
  • Fix: Use field's own @relation(fields:[...]) before convention-based lookup
  • Impact: targetUser FK was reportedById instead of targetUserId

Test plan

  • All unit tests pass
  • flutter analyze --fatal-infos — zero issues
  • dart format --set-exit-if-changed . — zero changes
  • Integration tested with familiarise_mobile (local path, dart_frog + curl)
  • Verified: Waitlist now has userId/webinarId/classId
  • Verified: Domain has correct oneToMany relations
  • Verified: ModerationReport.targetUser uses targetUserId FK

🤖 Generated with Claude Code

3 critical bugs fixed:

1. Parser: inline comments with { or } truncated model body extraction.
   Replaced [^}]+ regex with brace-counting _extractBlocks() for both
   model and enum parsing. (Waitlist was missing userId/webinarId/classId)

2. Parser: implicit relations (fields whose type is a model name but
   without @relation attribute) were not detected. Domain's subDomains,
   tags, consultantProfiles were parsed as non-relation fields.

3. Schema registry: wrong FK when a model has multiple relations to the
   same target (ModerationReport→User). Now uses field's own
   @relation(fields:[...]) before falling back to convention lookup.

Integration-tested with familiarise_mobile dart_frog backend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@teetangh
teetangh merged commit b074e02 into main Apr 4, 2026
8 of 12 checks passed

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request updates the Prisma Flutter Connector to version 0.5.5, introducing fixes for model parsing, implicit relation detection, and foreign key resolution in multi-relation models. The parser now uses a brace-counting method to extract blocks, and relation detection has been expanded to include fields referencing known models. Review feedback suggests improving the brace-counting logic to skip comments to avoid issues with unbalanced braces, restructuring the foreign key resolution to avoid unreachable code paths, and removing redundant string operations in the parser.

Comment on lines +652 to +659
while (i < content.length && depth > 0) {
final ch = content[i];
if (ch == '{') depth++;
if (ch == '}') depth--;
i++;
}
// i is now past the closing }, body is between start and i-1
blocks.add(_Block(name: name, body: content.substring(start, i - 1)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The brace-counting logic is still susceptible to the same truncation issue if a comment contains an unbalanced closing brace (e.g., // }). Since the primary goal of this PR is to handle braces in comments, the extraction loop should explicitly skip characters within comments while tracking the block depth. Additionally, it's safer to verify that the block was correctly closed (depth == 0) before adding it to the list.

      while (i < content.length && depth > 0) {
        final ch = content[i];
        // Skip inline comments to avoid false depth triggers from braces in comments
        if (ch == '/' && i + 1 < content.length && content[i + 1] == '/') {
          while (i < content.length && content[i] != '\n') i++;
          continue;
        }
        if (ch == '{') depth++;
        if (ch == '}') depth--;
        i++;
      }
      if (depth == 0) {
        blocks.add(_Block(name: name, body: content.substring(start, i - 1)));
      }

Comment on lines +132 to +133
final fk = _findForeignKeyFromField(field) ??
_findForeignKeyOnModel(model, target);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The call to _findForeignKeyOnModel is currently unreachable because _findForeignKeyFromField always returns a non-null string (it falls back to a default convention if no explicit relation is found). This logic should be restructured to prioritize explicit relations on the field, then check for explicit relations elsewhere in the model, and finally fall back to the naming convention.

        final fk = (field.relationFromFields?.isNotEmpty == true)
            ? field.relationFromFields!.first
            : (_findForeignKeyOnModel(model, target) ??
                '${toLowerCamelCase(field.type)}Id');

Comment on lines +529 to +530
final baseFieldType =
fieldType.replaceAll('?', '').replaceAll('[]', '');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The replaceAll calls here are redundant because fieldType has already been stripped of ? and [] suffixes earlier in the parsing loop (lines 502 and 508).

          final baseFieldType = fieldType;

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.

1 participant