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:
parent
bfda1d2c95
commit
9a4da065dc
10 changed files with 139 additions and 39 deletions
6
.changeset/neat-spiders-change.md
Normal file
6
.changeset/neat-spiders-change.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
"@logto/integration-tests": patch
|
||||
"@logto/core": patch
|
||||
---
|
||||
|
||||
fix incorrect swagger components
|
|
@ -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",
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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`,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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',
|
||||
// },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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",
|
||||
|
|
108
pnpm-lock.yaml
108
pnpm-lock.yaml
|
@ -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==}
|
||||
|
|
Loading…
Reference in a new issue