0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

fix(core): generate correct swagger components (#4884)

* fix(core): generate correct swagger components

* refactor(core): fix tests
This commit is contained in:
Gao Sun 2023-11-16 11:19:54 +08:00 committed by GitHub
parent bfda1d2c95
commit 9a4da065dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 139 additions and 39 deletions

View file

@ -0,0 +1,6 @@
---
"@logto/integration-tests": patch
"@logto/core": patch
---
fix incorrect swagger components

View file

@ -77,6 +77,7 @@
"otplib": "^12.0.1",
"p-retry": "^6.0.0",
"pg-protocol": "^1.6.0",
"pluralize": "^8.0.0",
"qrcode": "^1.5.3",
"redis": "^4.6.5",
"roarr": "^7.11.0",
@ -105,6 +106,7 @@
"@types/koa__cors": "^4.0.0",
"@types/node": "^18.11.18",
"@types/oidc-provider": "^8.0.0",
"@types/pluralize": "^0.0.33",
"@types/qrcode": "^1.5.2",
"@types/semver": "^7.3.12",
"@types/sinon": "^10.0.13",
@ -116,7 +118,7 @@
"nock": "^13.3.1",
"node-mocks-http": "^1.12.1",
"nodemon": "^3.0.0",
"openapi-types": "^12.0.0",
"openapi-types": "^12.1.3",
"prettier": "^3.0.0",
"sinon": "^17.0.0",
"supertest": "^6.2.2",

View file

@ -97,6 +97,17 @@ describe('GET /swagger.json', () => {
}),
() => ({})
);
// Test plural
queryParametersRouter.get(
'/mocks/:id/:field',
koaGuard({
params: object({
id: number(),
field: string(),
}),
}),
() => ({})
);
const swaggerRequest = createSwaggerRequest([queryParametersRouter]);
const response = await swaggerRequest.get('/swagger.json');
@ -105,7 +116,22 @@ describe('GET /swagger.json', () => {
get: {
parameters: [
{
$ref: '#/components/parameters/mocId:root',
$ref: '#/components/parameters/mockId:root',
},
{
name: 'field',
in: 'path',
required: true,
schema: { type: 'string' },
},
],
},
},
'/api/mocks/{id}/{field}': {
get: {
parameters: [
{
$ref: '#/components/parameters/mockId:root',
},
{
name: 'field',

View file

@ -104,8 +104,12 @@ const isManagementApiRouter = ({ stack }: Router) =>
// 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 = [
'key',
'connector-factory',
'factory',
'application',
'connector',
'sso-connector',
'resource',
'user',
'log',
@ -113,6 +117,7 @@ const identifiableEntityNames = [
'scope',
'hook',
'domain',
'verification',
'organization',
'organization-role',
'organization-scope',

View file

@ -1,6 +1,7 @@
import camelcase from 'camelcase';
import deepmerge from 'deepmerge';
import { type OpenAPIV3 } from 'openapi-types';
import pluralize from 'pluralize';
import { z } from 'zod';
import { fallbackDefaultPageSize } from '#src/middleware/koa-pagination.js';
@ -87,7 +88,7 @@ export const buildParameters: BuildParameters = (
if (key === 'id') {
if (rootComponent) {
return {
$ref: `#/components/parameters/${rootComponent.slice(0, -1)}Id:root`,
$ref: `#/components/parameters/${pluralize(rootComponent, 1)}Id:root`,
};
}

View file

@ -49,9 +49,11 @@ export const translationSchemas: Record<string, OpenAPIV3.SchemaObject> = {
{
type: 'string',
},
{
$ref: '#/components/schemas/Translation',
},
// {
// // This self-reference is OK, but it's not supported by Swagger UI
// // See https://github.com/swagger-api/swagger-ui/issues/3325
// $ref: '#/components/schemas/TranslationObject',
// },
],
},
};

View file

@ -21,6 +21,7 @@
"start": "pnpm test"
},
"devDependencies": {
"@apidevtools/swagger-parser": "^10.1.0",
"@jest/test-sequencer": "^29.5.0",
"@jest/types": "^29.1.2",
"@logto/connector-kit": "workspace:^2.0.0",
@ -42,8 +43,8 @@
"jest-puppeteer": "^9.0.0",
"jose": "^5.0.0",
"node-fetch": "^3.3.0",
"openapi-schema-validator": "^12.0.0",
"openapi-types": "^12.0.0",
"openapi-schema-validator": "^12.1.3",
"openapi-types": "^12.1.3",
"prettier": "^3.0.0",
"puppeteer": "^21.0.0",
"text-encoder": "^0.0.4",

View file

@ -1,3 +1,4 @@
import * as SwaggerParser from '@apidevtools/swagger-parser';
import Validator from 'openapi-schema-validator';
import type { OpenAPI } from 'openapi-types';
@ -11,11 +12,17 @@ describe('Swagger check', () => {
expect(response).toHaveProperty('statusCode', 200);
expect(response.headers['content-type']).toContain('application/json');
expect(() => {
// Use multiple validators to be more confident
expect(async () => {
const object: unknown = JSON.parse(response.body);
const validator = new OpenApiSchemaValidator({ version: 3 });
const result = validator.validate(object as OpenAPI.Document);
expect(result.errors).toEqual([]);
await expect(
SwaggerParser.default.validate(object as OpenAPI.Document)
).resolves.not.toThrow();
}).not.toThrow();
});
});

View file

@ -46,7 +46,7 @@
"@types/inquirer": "^9.0.0",
"@types/jest": "^29.4.0",
"@types/node": "^18.11.18",
"@types/pluralize": "^0.0.32",
"@types/pluralize": "^0.0.33",
"camelcase": "^8.0.0",
"chalk": "^5.0.0",
"eslint": "^8.44.0",

View file

@ -3280,6 +3280,9 @@ importers:
pg-protocol:
specifier: ^1.6.0
version: 1.6.0
pluralize:
specifier: ^8.0.0
version: 8.0.0
qrcode:
specifier: ^1.5.3
version: 1.5.3
@ -3359,6 +3362,9 @@ importers:
'@types/oidc-provider':
specifier: ^8.0.0
version: 8.0.0
'@types/pluralize':
specifier: ^0.0.33
version: 0.0.33
'@types/qrcode':
specifier: ^1.5.2
version: 1.5.2
@ -3393,8 +3399,8 @@ importers:
specifier: ^3.0.0
version: 3.0.0
openapi-types:
specifier: ^12.0.0
version: 12.0.0
specifier: ^12.1.3
version: 12.1.3
prettier:
specifier: ^3.0.0
version: 3.0.0
@ -3720,6 +3726,9 @@ importers:
specifier: ^12.0.1
version: 12.0.1
devDependencies:
'@apidevtools/swagger-parser':
specifier: ^10.1.0
version: 10.1.0(openapi-types@12.1.3)
'@jest/test-sequencer':
specifier: ^29.5.0
version: 29.5.0
@ -3784,11 +3793,11 @@ importers:
specifier: ^3.3.0
version: 3.3.0
openapi-schema-validator:
specifier: ^12.0.0
version: 12.0.0
specifier: ^12.1.3
version: 12.1.3
openapi-types:
specifier: ^12.0.0
version: 12.0.0
specifier: ^12.1.3
version: 12.1.3
prettier:
specifier: ^3.0.0
version: 3.0.0
@ -3916,8 +3925,8 @@ importers:
specifier: ^18.11.18
version: 18.11.18
'@types/pluralize':
specifier: ^0.0.32
version: 0.0.32
specifier: ^0.0.33
version: 0.0.33
camelcase:
specifier: ^8.0.0
version: 8.0.0
@ -4177,6 +4186,38 @@ packages:
'@jridgewell/trace-mapping': 0.3.18
dev: true
/@apidevtools/json-schema-ref-parser@9.0.6:
resolution: {integrity: sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg==}
dependencies:
'@jsdevtools/ono': 7.1.3
call-me-maybe: 1.0.2
js-yaml: 3.14.1
dev: true
/@apidevtools/openapi-schemas@2.1.0:
resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==}
engines: {node: '>=10'}
dev: true
/@apidevtools/swagger-methods@3.0.2:
resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==}
dev: true
/@apidevtools/swagger-parser@10.1.0(openapi-types@12.1.3):
resolution: {integrity: sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw==}
peerDependencies:
openapi-types: '>=7'
dependencies:
'@apidevtools/json-schema-ref-parser': 9.0.6
'@apidevtools/openapi-schemas': 2.1.0
'@apidevtools/swagger-methods': 3.0.2
'@jsdevtools/ono': 7.1.3
ajv: 8.12.0
ajv-draft-04: 1.0.0(ajv@8.12.0)
call-me-maybe: 1.0.2
openapi-types: 12.1.3
dev: true
/@authenio/samlify-node-xmllint@2.0.0(samlify@2.8.10):
resolution: {integrity: sha512-V9cQ0CHqu3JwOmbSecGPUnzIES5kHxD00FEZKnWh90ksQUJG5/TscV2r9XLbKp7MlRMOSUfWxecM35xPSLFdSg==}
peerDependencies:
@ -7345,6 +7386,10 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/@jsdevtools/ono@7.1.3:
resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==}
dev: true
/@koa/cors@4.0.0:
resolution: {integrity: sha512-Y4RrbvGTlAaa04DBoPBWJqDR5gPj32OOz827ULXfgB1F7piD1MB/zwn8JR2LAnvdILhxUbXbkXGWuNVsFuVFCQ==}
engines: {node: '>= 14.0.0'}
@ -9965,8 +10010,8 @@ packages:
pg-types: 2.2.0
dev: true
/@types/pluralize@0.0.32:
resolution: {integrity: sha512-exDkoRIkWJlbRDRmtYDbI3ZUE28HwBwHe5VKn4mvpvMW7qIRDHO6URItErBsBSX7J8/PrDLSOHCcbUMFXwA6CA==}
/@types/pluralize@0.0.33:
resolution: {integrity: sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==}
dev: true
/@types/prettier@2.7.1:
@ -10406,7 +10451,18 @@ packages:
transitivePeerDependencies:
- supports-color
/ajv-formats@2.1.1(ajv@8.8.2):
/ajv-draft-04@1.0.0(ajv@8.12.0):
resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
peerDependencies:
ajv: ^8.5.0
peerDependenciesMeta:
ajv:
optional: true
dependencies:
ajv: 8.12.0
dev: true
/ajv-formats@2.1.1(ajv@8.12.0):
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
ajv: ^8.0.0
@ -10414,7 +10470,7 @@ packages:
ajv:
optional: true
dependencies:
ajv: 8.8.2
ajv: 8.12.0
dev: true
/ajv@6.12.6:
@ -10434,15 +10490,6 @@ packages:
uri-js: 4.4.1
dev: true
/ajv@8.8.2:
resolution: {integrity: sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==}
dependencies:
fast-deep-equal: 3.1.3
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
uri-js: 4.4.1
dev: true
/ansi-colors@4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'}
@ -11011,6 +11058,10 @@ packages:
function-bind: 1.1.1
get-intrinsic: 1.1.3
/call-me-maybe@1.0.2:
resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==}
dev: true
/callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
@ -17016,17 +17067,17 @@ packages:
is-wsl: 2.2.0
dev: true
/openapi-schema-validator@12.0.0:
resolution: {integrity: sha512-dtQ5iCiCluL/SXmd5LWqfPXvN/WbVJeCp+3+exF6BHBN3fry5tNAhFllZICYHQ2kTfQxrfwbQcy0fqaw9wOb+w==}
/openapi-schema-validator@12.1.3:
resolution: {integrity: sha512-xTHOmxU/VQGUgo7Cm0jhwbklOKobXby+/237EG967+3TQEYJztMgX9Q5UE2taZKwyKPUq0j11dngpGjUuxz1hQ==}
dependencies:
ajv: 8.8.2
ajv-formats: 2.1.1(ajv@8.8.2)
ajv: 8.12.0
ajv-formats: 2.1.1(ajv@8.12.0)
lodash.merge: 4.6.2
openapi-types: 12.0.0
openapi-types: 12.1.3
dev: true
/openapi-types@12.0.0:
resolution: {integrity: sha512-6Wd9k8nmGQHgCbehZCP6wwWcfXcvinhybUTBatuhjRsCxUIujuYFZc9QnGeae75CyHASewBtxs0HX/qwREReUw==}
/openapi-types@12.1.3:
resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
dev: true
/optionator@0.8.3:
@ -17524,7 +17575,6 @@ packages:
/pluralize@8.0.0:
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
engines: {node: '>=4'}
dev: true
/pngjs@5.0.0:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}