Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve working with entities related to entities that uses compound ids #1801

Merged
merged 5 commits into from
Oct 25, 2024

Conversation

thomassnielsen
Copy link
Contributor

  1. Fixes an issue where adding entities related to entities with compound id (see makeIdConnect)
  2. Fixes validation of entities with compound id, given that zod schemas expect the attributes separately
  3. This is not super elegant, happy to get suggestions on improvements
  4. Update openAPI spec generation to match the previous point, making generate clients behave as expected

Copy link
Contributor

coderabbitai bot commented Oct 23, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request introduces modifications to the RESTfulOpenAPIGenerator and RequestHandler classes to enhance the handling of compound ID relationships in both the generation of API models and the processing of request bodies. The generateModelEntity method now exposes each component of compound IDs during read operations, while the processRequestBody method has been updated to correctly handle these IDs in request processing. A new model, PostLikeInfo, is added to the schema, along with tests to validate its integration with existing entities.

Changes

File Path Change Summary
packages/plugins/openapi/src/rest-generator.ts Modified generateModelEntity to expose individual fields for compound IDs during read operations. Updated comments for clarity.
packages/server/src/api/rest/index.ts Enhanced RequestHandler to handle compound IDs in processRequestBody and processCreate. Added makeIdConnect method for ID handling.
packages/server/tests/api/rest.test.ts Added PostLikeInfo model and updated PostLike model. Introduced tests for creating PostLikeInfo with relationships.

Possibly related PRs


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • 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. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • 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

@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: 3

🧹 Outside diff range and nitpick comments (1)
packages/server/tests/api/rest.test.ts (1)

1778-1802: Consider adding more comprehensive assertions.

While the test successfully verifies the creation of a PostLikeInfo entity related to a PostLike with compound ID, consider adding assertions to verify:

  • The created entity's attributes (text field)
  • The relationship to the PostLike entity
  • The proper handling of the compound ID in the response

Apply this diff to enhance the test:

     expect(r.status).toBe(201);
+    expect(r.body.data).toMatchObject({
+        type: 'postLikeInfo',
+        attributes: {
+            text: 'LikeInfo1',
+            postId: 1,
+            userId: 'user1'
+        },
+        relationships: {
+            postLike: {
+                data: { type: 'postLike', id: `1${idDivider}user1` }
+            }
+        }
+    });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between bb5f290 and b39b1d1.

⛔ Files ignored due to path filters (2)
  • packages/plugins/openapi/tests/baseline/rest-3.0.0.baseline.yaml is excluded by !**/*.yaml
  • packages/plugins/openapi/tests/baseline/rest-3.1.0.baseline.yaml is excluded by !**/*.yaml
📒 Files selected for processing (3)
  • packages/plugins/openapi/src/rest-generator.ts (1 hunks)
  • packages/server/src/api/rest/index.ts (5 hunks)
  • packages/server/tests/api/rest.test.ts (2 hunks)
🧰 Additional context used
🪛 Biome
packages/server/src/api/rest/index.ts

[error] 1292-1292: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)

🔇 Additional comments (4)
packages/plugins/openapi/src/rest-generator.ts (1)

850-852: LGTM! Consider enhancing the documentation.

The implementation correctly handles compound IDs by exposing each component as separate fields during read operations. This aligns with the PR objectives.

Consider expanding the comment to better explain the rationale:

-// For compound ids, each component is also exposed as a separate fields for read operations
+// For compound ids (multiple @id fields), each component is exposed as a separate field during read operations.
+// This is necessary because the client needs access to individual ID components for proper validation and
+// relationship handling, while create/update operations handle the compound ID as a single entity.

Let's verify the test coverage for this change:

✅ Verification successful

Based on the shell script results, I can now generate the final response since I have sufficient information about the test coverage for compound ID handling.

Implementation is well-tested, documentation suggestion stands

The implementation is thoroughly tested across multiple test files:

  • packages/plugins/openapi/tests/openapi-restful.test.ts directly tests the OpenAPI generation for compound IDs with exposes individual fields from a compound id as attributes
  • Integration tests in packages/server/tests/api/rest.test.ts verify the end-to-end behavior with multiple test cases for compound IDs
  • Additional test coverage exists in regression tests (issue-1243.test.ts) and integration tests (multi-id-fields.test.ts)

The original documentation suggestion remains valuable as it helps explain the implementation rationale, but the code change itself is well-tested and correctly implemented.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check test coverage for compound ID handling in OpenAPI generation

# Test: Look for test files related to OpenAPI generation
fd -e test.ts -e spec.ts openapi

# Test: Search for compound ID test cases
rg -A 5 "compound.*id|multiple.*id" --type ts

Length of output: 11021

packages/server/tests/api/rest.test.ts (1)

77-87: LGTM! Well-structured schema changes.

The new PostLikeInfo model and its relation to PostLike are properly defined with:

  • Appropriate field types and naming conventions
  • Correct compound key reference using both postId and userId fields
packages/server/src/api/rest/index.ts (2)

894-894: ⚠️ Potential issue

Check for undefined parsed.data.data.id in processRelationshipCRUD

There is a potential for parsed.data.data.id to be undefined in the processRelationshipCRUD method, which could cause runtime errors. Please add a check to ensure it is defined before using it.

Apply this diff to handle undefined parsed.data.data.id:

updateArgs.data = {
    [relationship]: {
+       connect: parsed.data.data.id
+           ? this.makeIdConnect(relationInfo.idFields, parsed.data.data.id)
+           : undefined,
    },
};
+ if (!parsed.data.data.id) {
+     return this.makeError('invalidRelationData', `Missing id in relationship data for ${relationship}`);
+ }

Likely invalid or redundant comment.


772-783: Ensure attributes are correctly cleaned for compound IDs

When removing attributes that are part of compound ID relationships, make sure that only the intended attributes are deleted from the attributes object to prevent unintended side effects.

Run the following script to verify which attributes are being deleted:

✅ Verification successful

Let me gather more context about the compound ID relationships and type mapping to better understand the attribute deletion logic.


Based on the comprehensive context gathered, I can now provide a final response about the attribute deletion verification.

The attribute deletion logic for compound IDs is correctly implemented

The code is working as intended because:

  1. The attribute deletion only occurs for relationships with compound IDs (checked via typeInfo.idFields.length > 1)
  2. The deletion is properly scoped to fields that are part of the compound ID relationship, as verified by:
    • The typeInfo is correctly mapped from the model metadata
    • The idFields array contains only the legitimate compound ID fields for that relationship
    • The deletion is performed using the exact field names from the relationship's ID fields

The attribute cleanup is necessary because these fields are handled differently in Prisma's connection logic for compound IDs, and leaving them in the attributes object would cause conflicts.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: List attributes being deleted for compound ID relationships

# Expected: Only attributes corresponding to compound ID fields are deleted
grep -E 'delete attributes\[' packages/server/src/api/rest/index.ts -A 5

Length of output: 196


Script:

#!/bin/bash
# Let's examine the typeMap structure and compound ID handling

# First, let's look for typeMap initialization and structure
ast-grep --pattern 'typeMap = {
  $$$
}'

# Also search for any references to compound IDs or multiple ID fields
rg "idFields" packages/server/src/api/rest/index.ts -B 2 -A 2

# Look for the broader context of the relationship handling
rg "relationships" packages/server/src/api/rest/index.ts -B 5 -A 5

Length of output: 18181

packages/server/src/api/rest/index.ts Show resolved Hide resolved
packages/server/src/api/rest/index.ts Outdated Show resolved Hide resolved
packages/server/src/api/rest/index.ts Show resolved Hide resolved
@ymc9 ymc9 changed the base branch from main to dev October 23, 2024 18:21
- use zod schema that contains only non-relation fields to validate mutation payload
- make sure id fields are always included in the base zod schema (even if they're also FK fields)
Copy link
Contributor

@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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6a101f3 and 76ce4f4.

📒 Files selected for processing (2)
  • packages/schema/src/plugins/zod/generator.ts (2 hunks)
  • packages/server/src/api/rest/index.ts (5 hunks)
🧰 Additional context used
🪛 Biome
packages/server/src/api/rest/index.ts

[error] 1269-1269: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)

🔇 Additional comments (4)
packages/schema/src/plugins/zod/generator.ts (2)

13-13: LGTM: Import addition for ID field handling.

The addition of isIdField import is necessary for the enhanced ID field handling in schema generation.


295-298: LGTM: Enhanced ID field handling in schema generation.

The modification to include ID fields explicitly in the scalar fields filter is a good improvement. This ensures that ID fields are always included in the schema generation, which is crucial for proper handling of compound IDs, even when they are part of foreign key relationships.

The condition ordering is correct:

  1. ID fields are checked first to ensure they're always included
  2. Regular fields are filtered to exclude data models and foreign keys
packages/server/src/api/rest/index.ts (2)

723-725: LGTM: Good separation of validation concerns.

The schema name pattern clearly indicates that only scalar (non-relation) fields are validated, which aligns well with the PR's objective to improve validation for entities with compound IDs.


781-783: Add null checks before using makeIdConnect.

While the relationship handling is improved, we should validate the data before using makeIdConnect to prevent runtime errors.

#!/bin/bash
# Description: Check if similar validation exists elsewhere in the codebase
# Test: Search for null checks on relationship data. Expect: Similar validation patterns
rg "data\.data\.id"

Also applies to: 790-790

packages/server/src/api/rest/index.ts Show resolved Hide resolved
@ymc9
Copy link
Member

ymc9 commented Oct 25, 2024

Hi @thomassnielsen , I've changed to use the "scalar" schema to validate which doesn't include FK fields. Also had to make a fix in the zod generation part to make sure ID fields are always included in the schema even they're also FK fields. May different corner combinations 😄.

Please take a look, thanks!

@thomassnielsen
Copy link
Contributor Author

Nice! I'm not familiar with the zod generator, but this looks reasonable to me 👍

@ymc9
Copy link
Member

ymc9 commented Oct 25, 2024

Nice! I'm not familiar with the zod generator, but this looks reasonable to me 👍

Cool. I'm merging it now.

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