mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
refactor(core): fix tests
This commit is contained in:
parent
35e44a54d3
commit
49aabe0290
4 changed files with 55 additions and 26 deletions
|
@ -8,7 +8,8 @@ import koaGuard from '#src/middleware/koa-guard.js';
|
|||
import koaPagination from '#src/middleware/koa-pagination.js';
|
||||
import type { AnonymousRouter } from '#src/routes/types.js';
|
||||
|
||||
const { default: swaggerRoutes, paginationParameters } = await import('./index.js');
|
||||
const { default: swaggerRoutes } = await import('./index.js');
|
||||
const { paginationParameters } = await import('./utils/parameters.js');
|
||||
|
||||
const createSwaggerRequest = (
|
||||
allRouters: Router[],
|
||||
|
@ -79,7 +80,7 @@ describe('GET /swagger.json', () => {
|
|||
get: { tags: ['Mock'] },
|
||||
},
|
||||
'/api/.well-known': {
|
||||
put: { tags: ['.well-known'] },
|
||||
put: { tags: ['Well known'] },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -101,22 +102,18 @@ describe('GET /swagger.json', () => {
|
|||
const response = await swaggerRequest.get('/swagger.json');
|
||||
expect(response.body.paths).toMatchObject({
|
||||
'/api/mock/:id/:field': {
|
||||
get: {
|
||||
parameters: [
|
||||
{
|
||||
name: 'id',
|
||||
in: 'path',
|
||||
required: true,
|
||||
schema: { type: 'number' },
|
||||
},
|
||||
{
|
||||
name: 'field',
|
||||
in: 'path',
|
||||
required: true,
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
],
|
||||
},
|
||||
parameters: [
|
||||
{
|
||||
$ref: '#/components/parameters/mocId:root',
|
||||
},
|
||||
{
|
||||
name: 'field',
|
||||
in: 'path',
|
||||
required: true,
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
],
|
||||
get: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ import { translationSchemas, zodTypeToSwagger } from '#src/utils/zod.js';
|
|||
|
||||
import type { AnonymousRouter } from '../types.js';
|
||||
|
||||
import { buildTag, findSupplementFiles } from './utils/general.js';
|
||||
import { buildTag, findSupplementFiles, normalizePath } from './utils/general.js';
|
||||
import {
|
||||
type ParameterArray,
|
||||
buildParameters,
|
||||
|
@ -103,6 +103,20 @@ const isManagementApiRouter = ({ stack }: Router) =>
|
|||
.filter(({ path }) => !path.includes('.*'))
|
||||
.some(({ stack }) => stack.some((function_) => isKoaAuthMiddleware(function_)));
|
||||
|
||||
// Add more components here to cover more ID parameters in paths. For example, if there is a
|
||||
// path `/foo/:barBazId`, then add `bar-baz` to the array.
|
||||
const identifiableEntityNames = [
|
||||
'application',
|
||||
'connector',
|
||||
'resource',
|
||||
'user',
|
||||
'log',
|
||||
'role',
|
||||
'scope',
|
||||
'hook',
|
||||
'domain',
|
||||
];
|
||||
|
||||
/**
|
||||
* Attach the `/swagger.json` route which returns the generated OpenAPI document for the
|
||||
* management APIs.
|
||||
|
@ -123,14 +137,14 @@ export default function swaggerRoutes<T extends AnonymousRouter, R extends Route
|
|||
return (
|
||||
router.stack
|
||||
// Filter out universal routes (mostly like a proxy route to withtyped)
|
||||
.filter(({ path }) => !path.includes('.*') && path.startsWith('/organization'))
|
||||
.filter(({ path }) => !path.includes('.*'))
|
||||
.flatMap<RouteObject>(({ path: routerPath, stack, methods }) =>
|
||||
methods
|
||||
.map((method) => method.toLowerCase())
|
||||
// There is no need to show the HEAD method.
|
||||
.filter((method): method is OpenAPIV3.HttpMethods => method !== 'head')
|
||||
.map((httpMethod) => {
|
||||
const path = `/api${routerPath}`;
|
||||
const path = normalizePath(routerPath);
|
||||
const { pathParameters, ...operation } = buildOperation(
|
||||
stack,
|
||||
routerPath,
|
||||
|
@ -180,7 +194,7 @@ export default function swaggerRoutes<T extends AnonymousRouter, R extends Route
|
|||
paths: Object.fromEntries(pathMap),
|
||||
components: {
|
||||
schemas: translationSchemas,
|
||||
parameters: ['organization', 'organization-role', 'organization-scope', 'user'].reduce(
|
||||
parameters: identifiableEntityNames.reduce(
|
||||
(previous, entityName) => ({ ...previous, ...buildPathIdParameters(entityName) }),
|
||||
{}
|
||||
),
|
||||
|
|
|
@ -14,8 +14,12 @@ export const getRootComponent = (path?: string) => path?.split('/')[1];
|
|||
* component name.
|
||||
* @example '/organization-roles' -> 'Organization roles'
|
||||
*/
|
||||
export const buildTag = (path: string) =>
|
||||
capitalize((getRootComponent(path) ?? 'General').replaceAll('-', ' '));
|
||||
export const buildTag = (path: string) => {
|
||||
const rootComponent = (getRootComponent(path) ?? 'General').replaceAll('-', ' ');
|
||||
return rootComponent.startsWith('.')
|
||||
? capitalize(rootComponent.slice(1))
|
||||
: capitalize(rootComponent);
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively find all supplement files (files end with `.openapi.json`) for the given
|
||||
|
@ -37,3 +41,16 @@ export const findSupplementFiles = async (directory: string) => {
|
|||
return result;
|
||||
};
|
||||
/* eslint-enable @silverhand/fp/no-mutating-methods, no-await-in-loop */
|
||||
|
||||
/**
|
||||
* Normalize the path to the OpenAPI path by adding `/api` prefix and replacing the path parameters
|
||||
* with OpenAPI path parameters.
|
||||
*
|
||||
* @example
|
||||
* normalizePath('/organization/:id') -> '/api/organization/{id}'
|
||||
*/
|
||||
export const normalizePath = (path: string) =>
|
||||
`/api${path}`
|
||||
.split('/')
|
||||
.map((part) => (part.startsWith(':') ? `{${part.slice(1)}}` : part))
|
||||
.join('/');
|
||||
|
|
|
@ -336,8 +336,7 @@ export default class SchemaRouter<
|
|||
`/:id/${pathname}/:${camelCaseSchemaId(relationSchema)}`,
|
||||
koaGuard({
|
||||
params: z.object({ id: z.string().min(1), [relationSchemaId]: z.string().min(1) }),
|
||||
// Should be 422 if the relation doesn't exist, update until we change the error handling
|
||||
status: [204, 404],
|
||||
status: [204, 422],
|
||||
}),
|
||||
async (ctx, next) => {
|
||||
const {
|
||||
|
@ -345,7 +344,9 @@ export default class SchemaRouter<
|
|||
} = ctx.guard;
|
||||
|
||||
await relationQueries.delete({
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- `koaGuard()` ensures the value is not `undefined`
|
||||
[columns.schemaId]: id!,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- `koaGuard()` ensures the value is not `undefined`
|
||||
[columns.relationSchemaId]: relationId!,
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue