Skip to content

feat: add ability to map model names in the URLS/JSON response #2187

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

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from

Conversation

lsmith77
Copy link

@lsmith77 lsmith77 commented Jul 15, 2025

implements #2178

this PR also adds support for a prefix similar to the openapi plugin. note openapi plugin itself still needs to be updated, to also use this model name mapping.

also we did not add any new tests. would appreciate any hints on that.

finally we will of course also be happy to provide documentation for this.

/cc @tobiasbrugger

Copy link
Contributor

coderabbitai bot commented Jul 15, 2025

📝 Walkthrough

"""

Walkthrough

The changes introduce configurable model name mappings in the REST API request handler. URL pattern matching and URL generation are updated to use these mappings consistently, including adding an enum for URL patterns and private methods for matching URLs and reversing model name mappings. The OpenAPI generator is also updated to reflect these mappings in generated paths and operation IDs. A new test suite verifies the correct routing behavior with model name mappings.

Changes

File(s) Change Summary
packages/server/src/api/rest/index.ts Added optional modelNameMapping to Options. Introduced UrlPatterns enum and private methods matchUrlPattern and mapModelName in RequestHandler. Refactored URL pattern matching and URL generation to apply model name mappings consistently.
packages/server/tests/api/rest.test.ts Added new test suite verifying REST handler behavior with modelNameMapping, ensuring external model names route correctly and internal names without mapping fail as expected.
packages/plugins/openapi/src/rest-generator.ts Added modelNameMapping property and mapModelName method to RESTfulOpenAPIGenerator. Updated path and operation ID generation to use mapped model names.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant REST API Handler
    participant Internal Logic

    Client->>REST API Handler: Sends request with external model name in URL
    REST API Handler->>REST API Handler: matchUrlPattern applies modelNameMapping to resolve internal model name
    REST API Handler->>Internal Logic: Processes request using internal model name
    Internal Logic-->>REST API Handler: Returns response data
    REST API Handler->>REST API Handler: mapModelName converts internal model name to external for URLs
    REST API Handler->>Client: Sends response with URLs using external model names
Loading

Suggested reviewers

  • ymc9
    """

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92fdd9a and 1c32b85.

📒 Files selected for processing (1)
  • packages/server/src/api/rest/index.ts (18 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/server/src/api/rest/index.ts
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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: 7

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 828a056 and eb9332e.

📒 Files selected for processing (1)
  • packages/server/src/api/rest/index.ts (19 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/server/src/api/rest/index.ts (1)
packages/runtime/src/local-helpers/lower-case-first.ts (1)
  • lowerCaseFirst (1-3)
🔇 Additional comments (3)
packages/server/src/api/rest/index.ts (3)

54-55: LGTM! Clean addition of optional configuration fields.

The new optional properties follow the existing pattern and are well-documented in the PR objectives.


1200-1202: LGTM! Correctly includes prefix in generated URLs.

The implementation properly prepends the prefix to all generated link URLs.


250-256: LGTM! Well-structured initialization of mappings.

The constructor properly initializes the model name mappings with appropriate defaults and efficiently pre-computes the reverse mapping.

primary use case is pluralization ie. model User exposed as /users
it is also  useful in case the internal and external names should be different.

TODO: adapt openapi plugin
@lsmith77 lsmith77 force-pushed the model-name-mapping branch from eb9332e to c05e542 Compare July 15, 2025 14:36
Copy link
Member

@ymc9 ymc9 left a comment

Choose a reason for hiding this comment

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

Hi @lsmith77, thanks for working on this!

I've put a few review comments there, please take a look when you have time. I've also pushed a sample test case that you can use as a base to expand.


const match = pattern.match(path);
if (match) {
match.type = this.modelNameMapping[match.type] ?? match.type;
Copy link
Member

Choose a reason for hiding this comment

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

When a mapping is provided, say "users" => "user", should access via unmapped path name like "POST /api/user" fail? I tend to think so - configuring a mapping requires you to only use the mapped name.

What do you think? Currently I believe both are valid.

Copy link
Author

Choose a reason for hiding this comment

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

Indeed. It should fail. We only had the case in mind where only some of the models are mapped but not all.

So should we rather throw an exception if a model is not mapped if there are any mappings?

Copy link
Member

Choose a reason for hiding this comment

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

I think supporting partial mapping is a good feature to have. What I meant is that, for the models that are configured with a mapping, the original name shouldn't be accessible anymore. E.g., if model "user" is mapped to "users", only "/api/users/..." should be valid, and "/api/user/..." should not.

Copy link
Author

Choose a reason for hiding this comment

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

Ok. I guess we will check if the type is included in the reverseModelNameMapping. In that case I would return null so that it is handled as no match found.

Copy link
Author

Choose a reason for hiding this comment

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

I now did some testing. At least with Nest.js it already returns a 404, since there is no /user route defined. Now if someone would then also define a /user route, indeed without change it would then work but at that point that seems to be intended by the user. So imho there is no need to handle this case inside the RequestHandler.

Copy link
Member

Choose a reason for hiding this comment

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

My understanding is the mapping (in the latest code) is inverted.

I tested the latest code with this mapping:

{
    user: 'myUser',
    post: 'myPost',
}

And this test is failing because of returning 200:

            await expect(
                handler({
                    method: 'post',
                    path: '/user',
                    query: {},
                    requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
                    prisma,
                })
            ).resolves.toMatchObject({
                status: 400,
            });

@ymc9
Copy link
Member

ymc9 commented Jul 16, 2025

Hi @lsmith77, thanks for working on this!

I've put a few review comments there, please take a look when you have time. I've also pushed a sample test case that you can use as a base to expand.

It seems I can't push the test case commit directly. I've put it as a PR here: digital-sustainability#1

@lsmith77 lsmith77 force-pushed the model-name-mapping branch 2 times, most recently from 486a165 to e2573cf Compare July 16, 2025 09:08
@lsmith77
Copy link
Author

Hi @lsmith77, thanks for working on this!
I've put a few review comments there, please take a look when you have time. I've also pushed a sample test case that you can use as a base to expand.

It seems I can't push the test case commit directly. I've put it as a PR here: digital-sustainability#1

I added one comment. Shouldn't using the unmapped model name cause a 404 and not a 400?

@ymc9
Copy link
Member

ymc9 commented Jul 16, 2025

Hi @lsmith77, thanks for working on this!
I've put a few review comments there, please take a look when you have time. I've also pushed a sample test case that you can use as a base to expand.

It seems I can't push the test case commit directly. I've put it as a PR here: digital-sustainability#1

I added one comment. Shouldn't using the unmapped model name cause a 404 and not a 400?

I chose 400 originally based on the understanding that you're passing an "invalid" endpoint (not a valid but not-available one). On the hindsight, maybe 404 is better suited, but it'll be an unnecessary breaking change ...

primary use case is pluralization ie. model User exposed as /users
it is also  useful in case the internal and external names should be different.

TODO: adapt openapi plugin
@lsmith77 lsmith77 force-pushed the model-name-mapping branch from e2573cf to 7d03fdb Compare July 16, 2025 10:03
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

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

3049-3075: Test implementation is correct but could validate response content more thoroughly.

The test logic correctly verifies that original model names fail (400) and mapped names succeed (201). However, it only validates status codes without checking response content.

Consider validating the response body content to ensure the mapping works correctly in all aspects:

-            ).resolves.toMatchObject({
-                status: 201,
-            });
+            ).resolves.toMatchObject({
+                status: 201,
+                body: {
+                    data: {
+                        type: 'user',
+                        attributes: { name: 'User1' },
+                        links: {
+                            self: expect.stringContaining('/myUser/')
+                        }
+                    }
+                }
+            });

This would ensure that:

  1. The response body contains the expected data
  2. URLs in the response use the mapped model names
  3. The type field still uses the original model name (as per the retrieved learnings)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2573cf and 7d03fdb.

📒 Files selected for processing (2)
  • packages/server/src/api/rest/index.ts (18 hunks)
  • packages/server/tests/api/rest.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: ymc9
PR: zenstackhq/zenstack#2187
File: packages/server/src/api/rest/index.ts:287-289
Timestamp: 2025-07-16T03:09:04.681Z
Learning: In REST API URL pattern matching with model name mapping, only the `type` parameter (representing model names) should be mapped using `modelNameMapping`. The `relationship` parameter represents field names on models and should not be mapped, as field names are distinct from model names in the API structure.
packages/server/tests/api/rest.test.ts (1)

<retrieved_learning>
Learnt from: ymc9
PR: #2187
File: packages/server/src/api/rest/index.ts:287-289
Timestamp: 2025-07-16T03:09:04.681Z
Learning: In REST API URL pattern matching with model name mapping, only the type parameter (representing model names) should be mapped using modelNameMapping. The relationship parameter represents field names on models and should not be mapped, as field names are distinct from model names in the API structure.
</retrieved_learning>

packages/server/src/api/rest/index.ts (1)
Learnt from: ymc9
PR: zenstackhq/zenstack#2187
File: packages/server/src/api/rest/index.ts:287-289
Timestamp: 2025-07-16T03:09:04.681Z
Learning: In REST API URL pattern matching with model name mapping, only the `type` parameter (representing model names) should be mapped using `modelNameMapping`. The `relationship` parameter represents field names on models and should not be mapped, as field names are distinct from model names in the API structure.
🧬 Code Graph Analysis (1)
packages/server/src/api/rest/index.ts (1)
packages/runtime/src/local-helpers/lower-case-first.ts (1)
  • lowerCaseFirst (1-3)
🔇 Additional comments (16)
packages/server/src/api/rest/index.ts (16)

54-54: LGTM! Model name mapping option added correctly.

The optional modelNameMapping property is properly typed as a record mapping strings to strings, which is appropriate for mapping external API model names to internal model names.


70-81: Well-structured type definitions for URL pattern matching.

The simplified Match type and UrlPatterns enum provide clean abstractions for URL pattern matching. The enum values clearly correspond to different REST API route patterns.


238-241: Appropriate private fields for URL pattern and model name mapping.

The private fields properly encapsulate the URL pattern map and both forward and reverse model name mappings, which are needed for bidirectional mapping during request processing and URL generation.


247-252: Correct initialization of model name mappings.

The constructor properly initializes both forward and reverse mappings, with the reverse mapping correctly constructed by swapping keys and values from the forward mapping. The URL pattern map is built with the appropriate charset configuration.


254-270: Clean URL pattern building with proper path construction.

The buildUrlPatternMap method correctly constructs URL patterns for different REST API endpoints. The buildPath helper function properly joins path segments with forward slashes.


272-287: Correct implementation of model name mapping logic.

The reverseModelNameMap method properly handles cases where no mapping exists by returning the original type. The matchUrlPattern method correctly applies forward mapping only to the type parameter (line 284), which aligns with the retrieved learning that field names should not be mapped.


320-347: Consistent use of centralized URL pattern matching.

The GET request handling correctly uses the new matchUrlPattern method for all URL pattern types, maintaining consistency across different endpoint patterns.


356-396: Proper URL pattern matching in POST request handling.

The POST request handling consistently uses the centralized matchUrlPattern method for both collection and relationship endpoints.


405-432: Correct URL pattern matching in PUT/PATCH request handling.

The PUT/PATCH request handling properly uses the centralized URL pattern matching for both single resource and relationship endpoints.


436-456: Consistent URL pattern matching in DELETE request handling.

The DELETE request handling correctly uses the centralized URL pattern matching approach.


572-577: Correct reverse mapping for URL generation.

The reverse mapping is properly applied to generate URLs with the external model name for the document linker. This ensures API responses contain URLs using the mapped model names.


624-638: Proper reverse mapping in relationship URL generation.

The code correctly uses reverse mapping to generate URLs for relationship endpoints, ensuring consistency in URL structure throughout the API responses.


723-724: Correct reverse mapping for collection URL generation.

The reverse mapping is properly applied when generating paginated collection URLs, maintaining consistency with the external model name mapping.


1053-1059: Proper reverse mapping in relationship CRUD operations.

The reverse mapping is correctly applied when generating URLs for relationship CRUD operation responses, ensuring consistent URL structure.


1204-1213: Correct reverse mapping in serializer building.

The reverse mapping is properly applied when building serializers to ensure resource links use the external model names consistently throughout the API.


1257-1279: Consistent reverse mapping in relator URL generation.

The reverse mapping is correctly applied when building relator URLs for relationship links, ensuring all relationship URLs use the mapped model names.

Comment on lines +3017 to +3076
describe('REST server tests - model name mapping', () => {
const schema = `
model User {
id String @id @default(cuid())
name String
posts Post[]
}
model Post {
id String @id @default(cuid())
title String
author User? @relation(fields: [authorId], references: [id])
authorId String?
}
`;
beforeAll(async () => {
const params = await loadSchema(schema);
prisma = params.prisma;
zodSchemas = params.zodSchemas;
modelMeta = params.modelMeta;

const _handler = makeHandler({
endpoint: 'http://localhost/api',
modelNameMapping: {
myUser: 'user',
myPost: 'post',
},
});
handler = (args) =>
_handler({ ...args, zodSchemas, modelMeta, url: new URL(`http://localhost/${args.path}`) });
});

it('works with name mapping', async () => {
// using original model name
await expect(
handler({
method: 'post',
path: '/user',
query: {},
requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
prisma,
})
).resolves.toMatchObject({
status: 400,
});

// using mapped model name
await expect(
handler({
method: 'post',
path: '/myUser',
query: {},
requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
prisma,
})
).resolves.toMatchObject({
status: 201,
});
});
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Good foundation for model name mapping tests, but coverage could be expanded.

The test suite correctly validates the basic model name mapping functionality. However, the test coverage is quite limited and could be expanded to ensure the feature works comprehensively.

Consider expanding the test coverage to include:

  1. Test the second mapping: The myPost mapping is configured but not tested
  2. Test other HTTP methods: Currently only POST is tested
  3. Test relationship endpoints: Verify that /myUser/{id}/posts works correctly
  4. Validate response consistency: Ensure URLs in response bodies use mapped names
  5. Test error scenarios: What happens when accessing unmapped model names
+        it('works with both mappings and all HTTP methods', async () => {
+            // Create user with mapped name
+            const userResponse = await handler({
+                method: 'post',
+                path: '/myUser',
+                query: {},
+                requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
+                prisma,
+            });
+            expect(userResponse.status).toBe(201);
+            const userId = userResponse.body.data.id;
+
+            // Create post with mapped name
+            const postResponse = await handler({
+                method: 'post',
+                path: '/myPost',
+                query: {},
+                requestBody: { data: { type: 'post', attributes: { title: 'Post1', authorId: userId } } },
+                prisma,
+            });
+            expect(postResponse.status).toBe(201);
+
+            // Test GET with mapped names
+            const getUserResponse = await handler({
+                method: 'get',
+                path: '/myUser',
+                prisma,
+            });
+            expect(getUserResponse.status).toBe(200);
+
+            // Test relationship endpoints
+            const relationshipResponse = await handler({
+                method: 'get',
+                path: `/myUser/${userId}/posts`,
+                prisma,
+            });
+            expect(relationshipResponse.status).toBe(200);
+        });
+
+        it('validates response URLs use mapped names', async () => {
+            const response = await handler({
+                method: 'post',
+                path: '/myUser',
+                query: {},
+                requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
+                prisma,
+            });
+            
+            expect(response.body.data.links.self).toContain('/myUser/');
+            expect(response.body.data.relationships.posts.links.related).toContain('/myUser/');
+        });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
describe('REST server tests - model name mapping', () => {
const schema = `
model User {
id String @id @default(cuid())
name String
posts Post[]
}
model Post {
id String @id @default(cuid())
title String
author User? @relation(fields: [authorId], references: [id])
authorId String?
}
`;
beforeAll(async () => {
const params = await loadSchema(schema);
prisma = params.prisma;
zodSchemas = params.zodSchemas;
modelMeta = params.modelMeta;
const _handler = makeHandler({
endpoint: 'http://localhost/api',
modelNameMapping: {
myUser: 'user',
myPost: 'post',
},
});
handler = (args) =>
_handler({ ...args, zodSchemas, modelMeta, url: new URL(`http://localhost/${args.path}`) });
});
it('works with name mapping', async () => {
// using original model name
await expect(
handler({
method: 'post',
path: '/user',
query: {},
requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
prisma,
})
).resolves.toMatchObject({
status: 400,
});
// using mapped model name
await expect(
handler({
method: 'post',
path: '/myUser',
query: {},
requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
prisma,
})
).resolves.toMatchObject({
status: 201,
});
});
});
describe('REST server tests - model name mapping', () => {
const schema = `
model User {
id String @id @default(cuid())
name String
posts Post[]
}
model Post {
id String @id @default(cuid())
title String
author User? @relation(fields: [authorId], references: [id])
authorId String?
}
`;
beforeAll(async () => {
const params = await loadSchema(schema);
prisma = params.prisma;
zodSchemas = params.zodSchemas;
modelMeta = params.modelMeta;
const _handler = makeHandler({
endpoint: 'http://localhost/api',
modelNameMapping: {
myUser: 'user',
myPost: 'post',
},
});
handler = (args) =>
_handler({ ...args, zodSchemas, modelMeta, url: new URL(`http://localhost/${args.path}`) });
});
it('works with name mapping', async () => {
// using original model name
await expect(
handler({
method: 'post',
path: '/user',
query: {},
requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
prisma,
})
).resolves.toMatchObject({
status: 400,
});
// using mapped model name
await expect(
handler({
method: 'post',
path: '/myUser',
query: {},
requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
prisma,
})
).resolves.toMatchObject({
status: 201,
});
});
it('works with both mappings and all HTTP methods', async () => {
// Create user with mapped name
const userResponse = await handler({
method: 'post',
path: '/myUser',
query: {},
requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
prisma,
});
expect(userResponse.status).toBe(201);
const userId = userResponse.body.data.id;
// Create post with mapped name
const postResponse = await handler({
method: 'post',
path: '/myPost',
query: {},
requestBody: { data: { type: 'post', attributes: { title: 'Post1', authorId: userId } } },
prisma,
});
expect(postResponse.status).toBe(201);
// Test GET with mapped names
const getUserResponse = await handler({
method: 'get',
path: '/myUser',
prisma,
});
expect(getUserResponse.status).toBe(200);
// Test relationship endpoints
const relationshipResponse = await handler({
method: 'get',
path: `/myUser/${userId}/posts`,
prisma,
});
expect(relationshipResponse.status).toBe(200);
});
it('validates response URLs use mapped names', async () => {
const response = await handler({
method: 'post',
path: '/myUser',
query: {},
requestBody: { data: { type: 'user', attributes: { name: 'User1' } } },
prisma,
});
expect(response.body.data.links.self).toContain('/myUser/');
expect(response.body.data.relationships.posts.links.related).toContain('/myUser/');
});
});
🤖 Prompt for AI Agents
In packages/server/tests/api/rest.test.ts between lines 3017 and 3076, the
existing test only covers POST requests for the 'myUser' mapped model and does
not test the 'myPost' mapping or other HTTP methods. Expand the test suite by
adding tests for the 'myPost' mapping, include GET, PUT, DELETE methods, and
test relationship endpoints like '/myUser/{id}/posts'. Also, add assertions to
verify that response URLs use the mapped model names consistently and include
tests for error scenarios when accessing unmapped model names to ensure
comprehensive coverage of the model name mapping feature.

@lsmith77
Copy link
Author

@ymc9 I have now also updated the openapi plugin. As part of this I realized it would make more sense to have the model mapping look like this:

{
  user: 'users'
}

rather than

{
  users: 'user'
}

@lsmith77 lsmith77 force-pushed the model-name-mapping branch from 15cfdc4 to 92fdd9a Compare July 16, 2025 11:36
@lsmith77
Copy link
Author

@ymc9 is there anything else you need from us before you can merge this?

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.

3 participants