Skip to content

Commit

Permalink
Merge pull request #6089 from mostafa/fix-oas-validation-errors
Browse files Browse the repository at this point in the history
fix: generate valid OpenAPI spec
  • Loading branch information
gao-sun authored Jun 23, 2024
2 parents 58f3eea + d51e839 commit a43434c
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 9 deletions.
8 changes: 8 additions & 0 deletions .changeset/heavy-badgers-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@logto/core": patch
---

fix OpenAPI schema returned by the `GET /api/swagger.json` endpoint

1. The `:` character is invalid in parameter names, such as `organizationId:root`. These characters have been replaced with `-`.
2. The `tenantId` parameter of the `/api/.well-known/endpoints/{tenantId}` route was missing from the generated OpenAPI spec document, resulting in validation errors. This has been fixed.
4 changes: 2 additions & 2 deletions packages/core/src/routes/swagger/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ describe('GET /swagger.json', () => {
get: {
parameters: [
{
$ref: '#/components/parameters/mockId:root',
$ref: '#/components/parameters/mockId-root',
},
{
name: 'field',
Expand All @@ -135,7 +135,7 @@ describe('GET /swagger.json', () => {
get: {
parameters: [
{
$ref: '#/components/parameters/mockId:root',
$ref: '#/components/parameters/mockId-root',
},
{
name: 'field',
Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/routes/swagger/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
paginationParameters,
buildPathIdParameters,
mergeParameters,
customParameters,
} from './utils/parameters.js';

type RouteObject = {
Expand Down Expand Up @@ -242,8 +243,11 @@ export default function swaggerRoutes<T extends AnonymousRouter, R extends Route
components: {
schemas: translationSchemas,
parameters: identifiableEntityNames.reduce(
(previous, entityName) => ({ ...previous, ...buildPathIdParameters(entityName) }),
{}
(previous, entityName) => ({
...previous,
...buildPathIdParameters(entityName),
}),
customParameters()
),
},
tags: [...tags, ...additionalTags].map((tag) => ({ name: tag })),
Expand Down
27 changes: 22 additions & 5 deletions packages/core/src/routes/swagger/utils/parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type BuildParameters = {
* For path parameters, this function will try to match reusable ID parameters:
*
* - If the parameter name is `id`, and the path is `/organizations/{id}/users`, the parameter
* `id` will be a reference to `#/components/parameters/organizationId:root`.
* `id` will be a reference to `#/components/parameters/organizationId-root`.
* - If the parameter name ends with `Id`, and the path is `/organizations/{id}/users/{userId}`,
* the parameter `userId` will be a reference to `#/components/parameters/userId`.
*
Expand Down Expand Up @@ -91,7 +91,7 @@ export const buildParameters: BuildParameters = (
if (key === 'id') {
if (rootComponent) {
return {
$ref: `#/components/parameters/${pluralize(rootComponent, 1)}Id:root`,
$ref: `#/components/parameters/${pluralize(rootComponent, 1)}Id-root`,
};
}

Expand Down Expand Up @@ -206,7 +206,7 @@ export const mergeParameters = (destination: unknown[], source: unknown[]) => {
* type: 'string',
* },
* },
* 'organizationId:root': {
* 'organizationId-root': {
* name: 'id',
* // ... same as above
* },
Expand All @@ -216,7 +216,7 @@ export const mergeParameters = (destination: unknown[], source: unknown[]) => {
* @remarks
* The root path component is the first path component in the path. For example, the root path
* component of `/organizations/{id}/users` is `organizations`. Since the name of the parameter is
* same for all root path components, we need to add an additional key with the `:root` suffix to
* same for all root path components, we need to add an additional key with the `-root` suffix to
* distinguish them.
*
* @param rootComponent The root path component in kebab case (`foo-bar`).
Expand All @@ -241,7 +241,7 @@ export const buildPathIdParameters = (
// Need to duplicate the object because OpenAPI does not support partial reference.
// See https://github.com/OAI/OpenAPI-Specification/issues/2026
return {
[`${entityId}:root`]: {
[`${entityId}-root`]: {
...shared,
name: 'id',
},
Expand All @@ -251,3 +251,20 @@ export const buildPathIdParameters = (
},
};
};

/**
* Build a parameter object with additional parameters that are not inferred from the path.
*/
export const customParameters = (): Record<string, OpenAPIV3.ParameterObject> => {
return Object.freeze({
tenantId: {
name: 'tenantId',
in: 'path',
description: 'The unique identifier of the tenant.',
required: true,
schema: {
type: 'string',
},
},
});
};

0 comments on commit a43434c

Please sign in to comment.