From a040487d28845a58ab1bcbb25ba6d67ab603aa08 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Fri, 28 Jun 2024 11:41:54 -0500 Subject: [PATCH 1/2] make zod parsing failures look more like real API 400s --- .../src/client/msw-handlers.ts | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/oxide-openapi-gen-ts/src/client/msw-handlers.ts b/oxide-openapi-gen-ts/src/client/msw-handlers.ts index 356be5b..a28a90d 100644 --- a/oxide-openapi-gen-ts/src/client/msw-handlers.ts +++ b/oxide-openapi-gen-ts/src/client/msw-handlers.ts @@ -90,10 +90,10 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { ? `body: Json,` : ""; const pathParams = conf.parameters?.filter( - (param) => "name" in param && param.schema && param.in === "path" + (param) => "name" in param && param.schema && param.in === "path", ); const queryParams = conf.parameters?.filter( - (param) => "name" in param && param.schema && param.in === "query" + (param) => "name" in param && param.schema && param.in === "query", ); const pathParamsType = pathParams?.length ? `path: Api.${snakeToPascal(opId)}PathParams,` @@ -133,9 +133,10 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { // if any of the errors come from path params, just 404 — the resource cannot // exist if there's no valid name - const { issues } = result.error - const status = issues.some(e => e.path[0] === 'path') ? 404 : 400 - return { paramsErr: json(issues, { status }) } + const status = result.error.issues.some((e) => e.path[0] === 'path') ? 404 : 400 + const error_code = status === 404 ? 'NotFound' : 'InvalidRequest' + const message = 'Zod error for params: ' + JSON.stringify(result.error) + return { paramsErr: json({ error_code, message }, { status }) } } const handler = (handler: MSWHandlers[keyof MSWHandlers], paramSchema: ZodSchema | null, bodySchema: ZodSchema | null) => @@ -151,7 +152,7 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { const { params, paramsErr } = paramSchema ? validateParams(paramSchema, req, pathParams) : { params: {}, paramsErr: undefined }; - if (paramsErr) return json(paramsErr, { status: 400 }); + if (paramsErr) return paramsErr; const { path, query } = params @@ -159,7 +160,10 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { if (bodySchema) { const rawBody = await req.json() const result = bodySchema.transform(snakeify).safeParse(rawBody); - if (!result.success) return json(result.error.issues, { status: 400 }) + if (!result.success) { + const message = 'Zod error for body: ' + JSON.stringify(result.error) + return json({ error_code: 'InvalidRequest', message }, { status: 400 }) + } body = result.data } @@ -172,9 +176,6 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { if (typeof result === "number") { return new HttpResponse(null, { status: result }); } - if (typeof result === "function") { - return result(); - } if (result instanceof Response) { return result; } @@ -183,17 +184,23 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { if (typeof thrown === 'number') { return new HttpResponse(null, { status: thrown }); } - if (typeof thrown === "function") { - return thrown(); - } if (typeof thrown === "string") { return json({ message: thrown }, { status: 400 }); } if (thrown instanceof Response) { return thrown; } + + // if it's not one of those, then we don't know what to do with it console.error('Unexpected mock error', thrown) - return json({ message: "Unknown Server Error" }, { status: 500 }); + if (typeof thrown === 'function') { + console.error( + "It looks like you've accidentally thrown an error constructor function from a mock handler without calling it!" + ) + } + // rethrow so everything breaks because this isn't supposed to happen + throw thrown + } } @@ -215,8 +222,8 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document, destDir: string) { w( `http.${method}('${formatPath( - path - )}', handler(handlers['${handler}'], ${paramSchema}, ${bodySchema})),` + path, + )}', handler(handlers['${handler}'], ${paramSchema}, ${bodySchema})),`, ); } w(`]}`); From afa9d09961f2e21ad1664301ddf1dcc5f9c07d0b Mon Sep 17 00:00:00 2001 From: David Crespo Date: Fri, 28 Jun 2024 11:44:46 -0500 Subject: [PATCH 2/2] npm version minor --- oxide-openapi-gen-ts/package-lock.json | 4 ++-- oxide-openapi-gen-ts/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/oxide-openapi-gen-ts/package-lock.json b/oxide-openapi-gen-ts/package-lock.json index 6adef72..303979e 100644 --- a/oxide-openapi-gen-ts/package-lock.json +++ b/oxide-openapi-gen-ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@oxide/openapi-gen-ts", - "version": "0.2.2", + "version": "0.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@oxide/openapi-gen-ts", - "version": "0.2.2", + "version": "0.3.0", "license": "MPL-2.0", "dependencies": { "minimist": "^1.2.8", diff --git a/oxide-openapi-gen-ts/package.json b/oxide-openapi-gen-ts/package.json index 1970c76..6305e53 100644 --- a/oxide-openapi-gen-ts/package.json +++ b/oxide-openapi-gen-ts/package.json @@ -1,6 +1,6 @@ { "name": "@oxide/openapi-gen-ts", - "version": "0.2.2", + "version": "0.3.0", "description": "OpenAPI client generator used to generate Oxide TypeScript SDK", "keywords": [ "oxide",