Skip to content

Commit ccc7c1a

Browse files
committed
Improve error message for parsing failure
1 parent 0b43425 commit ccc7c1a

File tree

3 files changed

+46
-26
lines changed

3 files changed

+46
-26
lines changed

apps/api/src/lib/validate-openapi.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe("Validate OpenAPI", function () {
1919
}`,
2020
fileExtension: "json",
2121
});
22-
assert.isTrue(result);
22+
assert.isTrue(result.isValid);
2323
});
2424

2525
it("Validates file falsy", async function () {
@@ -35,6 +35,6 @@ describe("Validate OpenAPI", function () {
3535
}`,
3636
fileExtension: "json",
3737
});
38-
assert.isFalse(result);
38+
assert.isFalse(result.isValid);
3939
});
4040
});

apps/api/src/lib/validate-openapi.ts

+30-14
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { ApiError, Problems } from "@zuplo/errors";
1+
import { ProblemDetails, Problems } from "@zuplo/errors";
22
import { load } from "js-yaml";
33
import { OpenApiFileExtension } from "./types.js";
44
import spectralCore, { Document } from "@stoplight/spectral-core";
55
import SpectralParsers from "@stoplight/spectral-parsers";
66

77
export const checkFileIsJsonOrYaml = (
88
fileContentString: string,
9-
): OpenApiFileExtension => {
9+
): OpenApiFileExtension | ProblemDetails => {
1010
try {
1111
JSON.parse(fileContentString);
1212
return "json";
@@ -21,16 +21,16 @@ export const checkFileIsJsonOrYaml = (
2121
// Ignore
2222
}
2323

24-
throw new ApiError({
24+
return {
2525
...Problems.BAD_REQUEST,
2626
detail: "Invalid file format. Only JSON and YAML are supported.",
27-
});
27+
};
2828
};
2929

3030
const validateOpenapi = (options: {
3131
fileContent: string;
3232
fileExtension: string;
33-
}) => {
33+
}): { isValid: true } | { isValid: false; error: ProblemDetails } => {
3434
const parser =
3535
options.fileExtension === "json"
3636
? SpectralParsers.Json
@@ -44,27 +44,43 @@ const validateOpenapi = (options: {
4444
options.fileExtension,
4545
);
4646
} catch (err) {
47-
throw new ApiError({
48-
...Problems.BAD_REQUEST,
49-
detail: "Could not parse OpenAPI file. Possible syntax error.",
50-
});
47+
return {
48+
isValid: false,
49+
error: {
50+
...Problems.BAD_REQUEST,
51+
detail: "Could not parse OpenAPI file. Possible syntax error.",
52+
},
53+
};
5154
}
5255

53-
// TODO: clean this up
5456
// eslint-disable-next-line @typescript-eslint/no-explicit-any
55-
const openAPIFileVersion = (openApiSpectralDoc.data as any)?.openapi || "";
57+
const openAPIFileVersion = (openApiSpectralDoc.data as any)?.openapi;
5658

5759
if (!openAPIFileVersion) {
5860
// if no version is specified, assume it's a swagger file
59-
return false;
61+
return {
62+
isValid: false,
63+
error: {
64+
...Problems.BAD_REQUEST,
65+
detail: "No OpenAPI version specified. Only OpenAPI v3.x is supported.",
66+
},
67+
};
6068
}
6169

6270
const validVersionExists =
6371
["3.0.0", "3.0.1", "3.0.2", "3.0.3", "3.1.0"].find((version) =>
6472
openAPIFileVersion.includes(version),
6573
) !== undefined;
66-
67-
return validVersionExists;
74+
if (!validVersionExists) {
75+
return {
76+
isValid: false,
77+
error: {
78+
...Problems.BAD_REQUEST,
79+
detail: `Invalid OpenAPI version. Only OpenAPI v3.x is supported. Found: ${openAPIFileVersion}.`,
80+
},
81+
};
82+
}
83+
return { isValid: true };
6884
};
6985

7086
export default validateOpenapi;

apps/api/src/routes/upload.ts

+14-10
Original file line numberDiff line numberDiff line change
@@ -105,22 +105,26 @@ export async function parseMultipartUpload(
105105
if (!fileContent) {
106106
throw new ApiError({
107107
...Problems.BAD_REQUEST,
108-
detail: "Invalid request body, no file content",
108+
detail: `Invalid request body, no file content. Uploader: ${email}.`,
109109
});
110110
}
111111
const fileContentString = fileContent.toString();
112112

113113
const fileIsJsonOrYamlResult = checkFileIsJsonOrYaml(fileContentString);
114-
115-
if (
116-
!validateOpenapi({
117-
fileContent: fileContentString,
118-
fileExtension: fileIsJsonOrYamlResult,
119-
})
120-
) {
114+
if (typeof fileIsJsonOrYamlResult !== "string") {
121115
throw new ApiError({
122-
...Problems.BAD_REQUEST,
123-
detail: "Invalid OpenAPI version. Only OpenAPI v3.x is supported.",
116+
...fileIsJsonOrYamlResult,
117+
detail: `${fileIsJsonOrYamlResult.detail} Uploader: ${email}.`,
118+
});
119+
}
120+
const openApiValidationResult = validateOpenapi({
121+
fileContent: fileContentString,
122+
fileExtension: fileIsJsonOrYamlResult,
123+
});
124+
if (!openApiValidationResult.isValid) {
125+
throw new ApiError({
126+
...openApiValidationResult.error,
127+
detail: `${openApiValidationResult.error.detail} Uploader: ${email}. File extension: ${fileIsJsonOrYamlResult}.`,
124128
});
125129
}
126130

0 commit comments

Comments
 (0)