From d85581e3ab90b0c3dbe30db9ad13f2855457fc03 Mon Sep 17 00:00:00 2001 From: sinasab Date: Mon, 18 Sep 2023 14:54:55 -0700 Subject: [PATCH 1/4] Adding simple working validating test --- bun.lockb | Bin 45324 -> 50912 bytes package.json | 1 + test/index.test.ts | 9 +++++++++ 3 files changed, 10 insertions(+) diff --git a/bun.lockb b/bun.lockb index 84a314c0e1d7b8622976f7643431ffb7723a599f..3867f43464e08f0d72371e825b0aa9cd37a7e26a 100755 GIT binary patch delta 11448 zcmeHNc~lhF((fKXX=GK53?m}$L}yqA92I5IXmANC?#3mKFv74ig9{LyK>-zU%f$sH zn#33aYNGMEKI5907&U4(<4dB6QKKec^wXG4eZT4j(MLQv?>q7RlY6MHuDW%r>ej7$ zyQitr^Qx~GIxW!!w_KSwVb|r2>d^<$PqfaN zzz^=G)Ngm3k_Ep2Rzo1sY|heJY+N-4lEH@^=m#rgXbt+^fpdY|1E<)uxu*0q&SXu> zGFffrRPf1Bi%px9mN}WbjakyTN#N6jElC-fR`WQH8x01{kfcm$HZBOUBl;OxaEc`( zQ9Ct@y8u27JR{>QZCYl6DF@!BS<)>z+!y6fKN`C5;Cn6FHi7kwnxxO{9oBFRp8ib zE|SUV$(DpBXfrU)Yy>b(`v81u1^gPY z23T3Ys~}o}t^l9bp%j?pn+8bw8Ud5O{W9JPOuh_;GMcds@-S_8jKmEYFsJ3(EXeI$ zfs#NKFe&WYT1un}(4?SL<|kxkrdrG#mk*k@g8_jc#a)1D^5BUMuV^EUTL4TBnNp^q zhvP=JB}ZeiRphul4*{C_Bw(6ZUl|7hL$)p>X>Bd(rn=1Z?|=wwjdT9k$==17VDhOo z_x-r!TCGRZUw61pzjdl;?&N;AhLm~6d^xc9IL&+8XGGq;dS+gSyV2w33Hehpf9^ST z#t6^Z>wo`r{n1P6CWU(vZoleYn3$v*p0<0_qB9G;ep$Csb%^cSWa{mFPUThm>8OKe z53^B~eE;?Q9_;-3jTzm8)bpO~*6s(ybbluat7M7A%;IX~KVns`MwLI$uDV9^6Irle z}?bl zBMWgvq92M?UQJlFceKzCna~YP(Mf(L3-&Pz2f*tJo-+&cF{pTVR_zn*(hI2(&1yWO z_%ArG*e+6C{pIa!rTqQHMtL}L20okB}t-E zL6IwxUaC@CDI%N1LMDD-(4_!t)4!YE7wkD?4~t_EQbDDqN8 zp%QM$6y#kEd^ijCGx8bCg6jrWh3hZu3a+DAu-eGaXBM?l_y{KpMG^7vGYIZDeTGUD z;xQf+S$CpX@ny{7ZxjxLhy4qC*

*isIK;v_2MxV7S;vabHkJQEcA^CFLSf-cN8` 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 Z1sk53UeE;GCn+R#eOelzXIYyo{td5$ZGQj& delta 7504 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 0.7.0" }, "devDependencies": { + "@apidevtools/swagger-parser": "^10.1.0", "@types/node": "^20.1.4", "bun-types": "^0.7.0", "elysia": "0.7.10", diff --git a/test/index.test.ts b/test/index.test.ts index 4b0e3b0..1a2ab9e 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,7 +1,9 @@ import { Elysia, t } from 'elysia' +import SwaggerParser from '@apidevtools/swagger-parser'; import { swagger } from '../src' import { describe, expect, it } from 'bun:test' +import { fail } from 'assert'; const req = (path: string) => new Request(`http://localhost${path}`) @@ -13,6 +15,13 @@ describe('Swagger', () => { expect(res.status).toBe(200) }) + it('returns a valid Swagger/OpenAPI json config', async () => { + const app = new Elysia().use(swagger()) + const res = await app.handle(req('/swagger/json')).then((x) => x.json()); + expect(res.openapi).toBe("3.0.3"); + await SwaggerParser.validate(res).catch((err) => fail(err)); + }); + it('use custom Swagger version', async () => { const app = new Elysia().use( swagger({ From de06f61292a3e02a7da76030a63a826f935ec383 Mon Sep 17 00:00:00 2001 From: sinasab Date: Mon, 18 Sep 2023 14:55:08 -0700 Subject: [PATCH 2/4] Adding failing validating test --- test/validateSchema.test.ts | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/validateSchema.test.ts diff --git a/test/validateSchema.test.ts b/test/validateSchema.test.ts new file mode 100644 index 0000000..e3f67cc --- /dev/null +++ b/test/validateSchema.test.ts @@ -0,0 +1,45 @@ +import { Elysia, t } from 'elysia' +import SwaggerParser from '@apidevtools/swagger-parser'; +import { swagger } from '../src' + +import { describe, expect, it } from 'bun:test' +import { fail } from 'assert'; + +const req = (path: string) => new Request(`http://localhost${path}`) + +it('returns a valid Swagger/OpenAPI json config for many routes', async () => { + const app = new Elysia() + .use(swagger()) + .get('/', () => 'hi', { response: t.String({ description: 'sample description' }) }) + .get('/unpath/:id', ({ params: { id } }) => id, { response: t.String({ description: 'sample description' }) }) + .get('/unpath/:id/:name/:age', ({ params: { id, name } }) => `${id} ${name}`, + { type: "json", response: t.String({ description: 'sample description' }), params: t.Object({ id: t.String(), name: t.String() }) }) + .post( + '/json/:id', + ({ body, params: { id }, query: { name } }) => ({ + ...body, + id, + name + }), + { + params: t.Object({ + id: t.String() + }), + query: t.Object({ + name: t.String() + }), + body: t.Object({ + username: t.String(), + password: t.String() + }), + response: t.Object({ + username: t.String(), + password: t.String(), + id: t.String(), + name: t.String() + }, { description: 'sample description 3' }) + } + ); + const res = await app.handle(req('/swagger/json')).then((x) => x.json()); + await SwaggerParser.validate(res).catch((err) => fail(err)); +}); From 10e3639cd516a09e40f79883326bd05db979fb5f Mon Sep 17 00:00:00 2001 From: sinasab Date: Mon, 18 Sep 2023 14:55:13 -0700 Subject: [PATCH 3/4] Fixing failing test --- src/index.ts | 4 ++-- src/utils.ts | 28 +++++++++++++++------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/index.ts b/src/index.ts index f4a2e4b..54e505a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -136,7 +136,7 @@ export const swagger = method: route.method, path: route.path, // @ts-ignore - models: app.definitions.type, + models: app.definitions?.type, contentType: route.hooks.type }) }) @@ -161,7 +161,7 @@ export const swagger = ...documentation.components, schemas: { // @ts-ignore - ...app.definitions.type, + ...app.definitions?.type, ...documentation.components?.schemas } } diff --git a/src/utils.ts b/src/utils.ts index 955557c..9e8d4bd 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -22,16 +22,18 @@ export const mapProperties = ( if (schema in models) schema = models[schema] else throw new Error(`Can't find model ${schema}`) - return Object.entries(schema?.properties ?? []).map(([key, value]) => ({ - // @ts-ignore - ...value, - in: name, - name: key, - // @ts-ignore - type: value?.type, - // @ts-ignore - required: schema!.required?.includes(key) ?? false - })) + return Object.entries(schema?.properties ?? []).map(([key, value]) => { + const { type: valueType = undefined, ...rest } = value as any; + return { + // @ts-ignore + ...rest, + schema: { type: valueType }, + in: name, + name: key, + // @ts-ignore + required: schema!.required?.includes(key) ?? false, + }; + }); } const mapTypesResponse = ( @@ -118,7 +120,7 @@ export const registerSchemaPath = ({ if (typeof responseSchema === 'object') { if (Kind in responseSchema) { - const { type, properties, required, ...rest } = + const { type, properties, required, additionalProperties, ...rest } = responseSchema as typeof responseSchema & { type: string properties: Object @@ -162,7 +164,7 @@ export const registerSchemaPath = ({ content: mapTypesResponse(contentTypes, value) } } else { - const { type, properties, required, ...rest } = + const { type, properties, required, additionalProperties, ...rest } = value as typeof value & { type: string properties: Object @@ -286,7 +288,7 @@ export const filterPaths = ( .map((x) => ({ in: 'path', name: x.slice(1, x.length - 1), - type: 'string', + schema: { type: "string" }, required: true })), ...schema.parameters From 53bb5523ba8448d9b33c24eda5af59643a5732c3 Mon Sep 17 00:00:00 2001 From: sinasab Date: Mon, 18 Sep 2023 14:58:28 -0700 Subject: [PATCH 4/4] Fixing readme example --- README.md | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 9796fd6..2b2ac94 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,7 @@ import { swagger } from '@elysiajs/swagger' const app = new Elysia() .use(swagger()) - .get('/', () => 'hi') - .get('/unpath/:id', ({ params: { id } }) => id) - .get('/unpath/:id/:name', ({ params: { id, name } }) => `${id} ${name}`) + .get('/', () => 'hi', { response: t.String({ description: 'sample description' }) }) .post( '/json/:id', ({ body, params: { id }, query: { name } }) => ({ @@ -24,27 +22,25 @@ const app = new Elysia() name }), { - schema: { - params: t.Object({ - id: t.String() - }), - query: t.Object({ - name: t.String() - }), - body: t.Object({ - username: t.String(), - password: t.String() - }), - response: t.Object({ - username: t.String(), - password: t.String(), - id: t.String(), - name: t.String() - }) - } + params: t.Object({ + id: t.String() + }), + query: t.Object({ + name: t.String() + }), + body: t.Object({ + username: t.String(), + password: t.String() + }), + response: t.Object({ + username: t.String(), + password: t.String(), + id: t.String(), + name: t.String() + }, { description: 'sample description' }) } ) - .listen(8080) + .listen(8080); ``` Then go to `http://localhost:8080/swagger`.