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

Configurable REST API id divider #1785

Merged
merged 8 commits into from
Oct 19, 2024

Conversation

thomassnielsen
Copy link
Contributor

@thomassnielsen thomassnielsen commented Oct 17, 2024

Make id divider in the REST API generator configurable, in case the values contain the default _ divider.

@thomassnielsen thomassnielsen changed the title Configurable id divider Configurable REST API id divider Oct 17, 2024
- Update test to use postgres db
- Changes url pattern option from `segmentNameCharset` to `segmentValueCharset`
- Made sure ID key sent to Prisma is always joined with '_' instead of user-configured divider. I've renamed methods for clarity.
@ymc9
Copy link
Member

ymc9 commented Oct 17, 2024

Hi @thomassnielsen , I've pushed a commit with the following changes:

  • Update test to use postgres db
  • Changes url pattern option from segmentNameCharset to segmentValueCharset
  • Made sure ID key sent to Prisma is always joined with '_' instead of user-configured divider. I've renamed methods for clarity.

Please help check if they make sense. Thanks!

@thomassnielsen
Copy link
Contributor Author

Please help check if they make sense. Thanks!

Looks good to me! Thanks!

@thomassnielsen thomassnielsen marked this pull request as ready for review October 18, 2024 07:04
Copy link
Contributor

coderabbitai bot commented Oct 18, 2024

📝 Walkthrough
<details>
<summary>📝 Walkthrough</summary>

## Walkthrough
The pull request introduces significant modifications to the `RequestHandler` class within the REST API. A new optional property, `idDivider`, is added to the `Options` type, allowing for customizable separation of compound ID fields in URLs. The static `urlPatterns` object is replaced by a dynamic method, `buildUrlPatterns`, which generates URL patterns based on the `idDivider`. Additionally, internal methods related to ID handling are updated for consistency. The test suite is also enhanced to validate the handling of compound IDs with a custom separator, including database setup and teardown for testing.

## Changes

| File Path                                      | Change Summary                                                                                     |
|------------------------------------------------|---------------------------------------------------------------------------------------------------|
| packages/server/src/api/rest/index.ts         | - Added `idDivider?: string;` to `Options` type.<br>- Introduced `buildUrlPatterns(idDivider: string)` method.<br>- Renamed `makeIdFilter` to `makePrismaIdFilter`.<br>- Updated methods to use `idDivider`. |
| packages/server/tests/api/rest.test.ts        | - Added tests for compound IDs with a custom separator.<br>- Included database setup/teardown logic using `createPostgresDb` and `dropPostgresDb`. |

## Possibly related PRs
- **#1754**: Enhances the `RequestHandler` class to support compound IDs, directly relating to the changes made regarding ID handling and the `idDivider` property.
- **#1784**: Modifies the `RequestHandler` to improve serialization for entities with compound IDs, aligning with the focus on managing compound IDs in the main PR.

## Suggested reviewers
- ymc9

</details>

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4e80c29 and 7c5940b.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/*.yaml
📒 Files selected for processing (2)
  • packages/server/src/api/rest/index.ts (24 hunks)
  • packages/server/tests/api/rest.test.ts (2 hunks)
🧰 Additional context used
🔇 Additional comments (1)
packages/server/src/api/rest/index.ts (1)

216-216: Verify URL encoding of special characters in idDivider.

If idDivider contains special characters that may require URL encoding, ensure that segmentValueCharset accommodates them appropriately to prevent parsing issues.

Run the following script to check for special characters in idDivider:

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

🧹 Outside diff range and nitpick comments (3)
packages/server/src/api/rest/index.ts (2)

224-235: LGTM: Well-implemented buildUrlPatterns method.

The buildUrlPatterns method is correctly implemented. It uses the provided urlSegmentNameCharset for creating URL patterns, which should handle custom characters in IDs properly.

Consider adding a comment explaining why the idDivider parameter is not directly used in this method. It might be helpful for future maintainers to understand that it's implicitly used through the urlSegmentNameCharset.


Line range hint 1230-1264: LGTM: Updated ID-related methods to use configurable divider.

The ID-related methods have been updated to use the configurable this.idDivider in most cases, which is correct. The makePrismaIdKey method still uses a hardcoded underscore, which aligns with the PR comment about ensuring the ID key sent to Prisma is always joined with an underscore.

Consider adding a comment in the makePrismaIdKey method explaining why it uses a hardcoded underscore instead of this.idDivider. This will help future maintainers understand the intentional difference.

private makePrismaIdKey(idFields: FieldInfo[]) {
    // TODO: support `@@id` with custom name
+   // Note: We always use underscore for Prisma, regardless of the configured idDivider
    return idFields.map((idf) => idf.name).join('_');
}
packages/server/tests/api/rest.test.ts (1)

2525-2564: LGTM! Well-structured test suite setup.

The setup for the "REST server tests - compound id with custom separator" test suite is comprehensive and well-structured. It correctly configures the test environment with a custom schema, PostgreSQL database, and the necessary options for testing compound IDs with a custom separator.

Consider adding a comment explaining the purpose of the urlSegmentNameCharset option, as it's not immediately clear why it's needed for this test suite.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7c5940b and c002fa2.

📒 Files selected for processing (2)
  • packages/server/src/api/rest/index.ts (24 hunks)
  • packages/server/tests/api/rest.test.ts (2 hunks)
🧰 Additional context used
🔇 Additional comments (10)
packages/server/src/api/rest/index.ts (10)

42-53: LGTM: New options for configurable ID divider and URL segment charset.

The additions of idDivider and urlSegmentNameCharset to the Options type are well-documented and provide clear explanations of their purpose. The default values are sensible, allowing for backward compatibility while enabling customization.


212-216: LGTM: New private properties for ID divider and URL patterns.

The addition of private idDivider and urlPatterns properties to the RequestHandler class is appropriate. These properties will store the configurable ID divider and dynamically generated URL patterns, which are essential for the new functionality.


219-222: LGTM: Proper initialization of ID divider and URL patterns.

The constructor correctly initializes the idDivider and urlPatterns properties. It uses the values from the options object if provided, otherwise falling back to sensible defaults. The buildUrlPatterns method is called with the appropriate parameters to generate the URL patterns.


Line range hint 269-293: LGTM: Correct implementation of dynamic URL patterns in GET handler.

The GET method handler has been updated to use the dynamic this.urlPatterns instead of static patterns. This change correctly implements the use of the custom ID divider in URL matching while maintaining the existing logic for different types of GET requests (single resource, fetch related, read relationship, collection read).


Line range hint 307-322: LGTM: Proper use of dynamic URL patterns in POST handler.

The POST method handler has been correctly updated to use the dynamic this.urlPatterns. This change ensures that the custom ID divider is respected in URL matching for POST requests, while maintaining the existing logic for resource creation and relationship creation.


Line range hint 337-362: LGTM: Correct implementation of dynamic URL patterns in PUT/PATCH handler.

The PUT/PATCH method handler has been properly updated to use the dynamic this.urlPatterns. This change ensures that the custom ID divider is respected in URL matching for update requests, while preserving the existing logic for resource updates and relationship updates.


Line range hint 369-386: LGTM: Proper use of dynamic URL patterns in DELETE handler.

The DELETE method handler has been correctly updated to use the dynamic this.urlPatterns. This change ensures that the custom ID divider is respected in URL matching for delete requests, while maintaining the existing logic for resource deletion and relationship deletion.


777-777: LGTM: Consistent usage of updated ID-related methods.

The changes consistently use the renamed makePrismaIdKey and makePrismaIdFilter methods in various parts of the code, including relationship operations and filter operations. This maintains consistency with the earlier changes and ensures that the configurable ID divider is respected throughout the codebase.

Also applies to: 785-785, 794-794, 1587-1591


Line range hint 1-1740: Summary: Well-implemented configurable REST API ID divider

The changes in this file successfully implement a configurable ID divider for the REST API. Key points:

  1. The Options type now includes idDivider and urlSegmentNameCharset properties.
  2. Dynamic URL patterns are used throughout the request handlers to accommodate the custom ID divider.
  3. ID-related methods have been updated to use the configurable divider, with the exception of makePrismaIdKey which intentionally uses an underscore for Prisma compatibility.
  4. The changes are consistent and maintain the existing functionality while adding the new configurability.

The implementation is solid and achieves the goal of making the REST API ID divider configurable. The code is well-structured and the changes are applied consistently throughout the file.


415-415: LGTM: Updated method name for clarity.

The change from makeIdFilter to makePrismaIdFilter improves clarity about the method's purpose.

Please ensure that the makePrismaIdFilter method correctly uses the new idDivider property. Let's verify its implementation:

@thomassnielsen thomassnielsen requested a review from ymc9 October 18, 2024 10:54
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: 5

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

2541-2565: Robust test setup with room for minor improvement

The test suite setup is well-structured and includes important practices:

  1. Creating a fresh PostgreSQL database for each test run, ensuring a clean testing environment.
  2. Custom handler setup with specific options, allowing for comprehensive testing of the custom ID separator functionality.
  3. Inclusion of potentially problematic characters in urlSegmentNameCharset, which is excellent for thorough testing.

One minor suggestion for improvement:

Consider adding error handling for the database creation and dropping processes. This could help identify any issues with the database setup or teardown more easily.

Example:

beforeAll(async () => {
    try {
        const dbUrl = await createPostgresDb(dbName);
        // ... rest of the setup
    } catch (error) {
        console.error('Failed to set up test database:', error);
        throw error;
    }
});

afterAll(async () => {
    try {
        await dropPostgresDb(dbName);
    } catch (error) {
        console.error('Failed to drop test database:', error);
    }
});
packages/server/src/api/rest/index.ts (2)

1237-1238: Address TODO: Support @@id with custom names in makePrismaIdFilter

The current implementation doesn't support models with @@id composite keys that have custom names. This might lead to incorrect query behavior for such models. Consider implementing support for custom composite ID names.

Would you like assistance in implementing this feature? I can help provide a solution or open a GitHub issue to track this task.


1260-1262: Address TODO: Support @@id with custom names in makePrismaIdKey

The method makePrismaIdKey currently doesn't handle custom names for composite IDs defined using @@id. This could result in incorrect key generation when interfacing with Prisma for models using custom composite IDs.

Would you like assistance in implementing this support? I can help draft the necessary changes or open a GitHub issue to track this enhancement.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between c002fa2 and 5074314.

📒 Files selected for processing (2)
  • packages/server/src/api/rest/index.ts (25 hunks)
  • packages/server/tests/api/rest.test.ts (2 hunks)
🧰 Additional context used
🔇 Additional comments (1)
packages/server/tests/api/rest.test.ts (1)

2524-2540: Well-structured test suite setup

The test suite is well-organized and demonstrates good practices:

  1. Clear definition of the User model with a compound primary key.
  2. Use of enums for the Role field, improving type safety.
  3. Custom idDivider (':') to avoid potential conflicts in compound IDs.
  4. Use of PostgreSQL for testing, which is a robust choice for a database.

These choices contribute to a more reliable and maintainable test suite.

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

🧹 Outside diff range and nitpick comments (2)
packages/server/src/api/rest/index.ts (2)

1258-1267: LGTM: Separated API and Prisma ID key generation.

The changes in makeIdKey, makePrismaIdKey, and makeCompoundId methods correctly implement the separation of concerns between API and Prisma ID handling. This approach maintains Prisma compatibility while allowing API flexibility.

Consider adding a comment explaining why prismaIdDivider is used in makePrismaIdKey to improve code clarity:

 private makePrismaIdKey(idFields: FieldInfo[]) {
     // TODO: support `@@id` with custom name
+    // Use prismaIdDivider to maintain compatibility with Prisma's internal ID handling
     return idFields.map((idf) => idf.name).join(prismaIdDivider);
 }

Line range hint 1233-1247: LGTM: Updated makePrismaIdFilter for compatibility and flexibility.

The makePrismaIdFilter method now correctly uses prismaIdDivider for Prisma compatibility and this.idDivider for API flexibility. This approach ensures proper handling of IDs across both the API and Prisma layers.

Consider adding a comment to explain the dual use of dividers for improved clarity:

 private makePrismaIdFilter(idFields: FieldInfo[], resourceId: string) {
     if (idFields.length === 1) {
         return { [idFields[0].name]: this.coerce(idFields[0].type, resourceId) };
     } else {
         return {
             // TODO: support `@@id` with custom name
+            // Use prismaIdDivider for Prisma compatibility and this.idDivider for API flexibility
             [idFields.map((idf) => idf.name).join(prismaIdDivider)]: idFields.reduce(
                 (acc, curr, idx) => ({
                     ...acc,
                     [curr.name]: this.coerce(curr.type, resourceId.split(this.idDivider)[idx]),
                 }),
                 {}
             ),
         };
     }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 5074314 and 0154a61.

📒 Files selected for processing (2)
  • packages/server/src/api/rest/index.ts (25 hunks)
  • packages/server/tests/api/rest.test.ts (2 hunks)
🧰 Additional context used
🔇 Additional comments (10)
packages/server/src/api/rest/index.ts (10)

42-54: LGTM: New options for ID divider and URL segment charset.

The additions of idDivider and urlSegmentCharset to the Options type are well-documented and provide the necessary flexibility for configuring the REST API handler.


96-96: LGTM: Constant for Prisma ID divider.

The addition of prismaIdDivider constant is a good practice for maintaining consistency with Prisma's internal ID handling.


215-225: LGTM: Constructor updated to handle new options.

The changes in the constructor properly initialize the new idDivider property and dynamically generate urlPatterns. This approach provides the desired configurability while maintaining backward compatibility.


227-238: LGTM: Dynamic URL pattern generation.

The buildUrlPatterns method is a well-implemented solution for generating flexible URL patterns based on the provided options. This enhances the configurability of the API.


Line range hint 272-296: LGTM: Updated handleRequest to use dynamic URL patterns.

The changes in the handleRequest method correctly utilize the new dynamic urlPatterns, ensuring consistency with the configured idDivider.


310-316: LGTM: POST request handling updated for dynamic URL patterns.

The changes in POST request handling correctly use the new dynamic urlPatterns, maintaining consistency with the GET request handling modifications.


Line range hint 340-354: LGTM: PUT/PATCH request handling updated for dynamic URL patterns.

The changes in PUT/PATCH request handling correctly use the new dynamic urlPatterns, maintaining consistency across all HTTP methods.


372-378: LGTM: DELETE request handling updated for dynamic URL patterns.

The changes in DELETE request handling correctly use the new dynamic urlPatterns, ensuring consistency across all CRUD operations.


1137-1137: LGTM: getId method updated to use configurable ID key.

The getId method now correctly uses this.makeIdKey(ids), ensuring consistency with the configured idDivider.


Line range hint 1-1733: Overall assessment: Well-implemented configurable ID divider feature.

The changes in this file consistently implement the new configurable ID divider feature across all relevant methods and operations. The approach taken maintains compatibility with Prisma's internal ID handling while allowing flexibility in the API layer. The separation of concerns between API and Prisma ID handling is well-executed.

Key points:

  1. New options (idDivider and urlSegmentCharset) added to allow configuration.
  2. Dynamic URL pattern generation implemented to support the configurable divider.
  3. All CRUD operations updated to use the new dynamic URL patterns.
  4. ID key generation methods updated to use the configurable divider for API operations while maintaining Prisma compatibility.

The implementation is thorough and consistent, with only minor suggestions for improving code clarity through additional comments.

ymc9
ymc9 previously approved these changes Oct 19, 2024
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