Skip to content

Commit 8da8d4e

Browse files
committed
Original file
1 parent d28771a commit 8da8d4e

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

vanilla/library/src/scripts/apiv2.ts

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Entrypoint for the APIv2 calls. Prepulates an axios instance with some config settings.
3+
*
4+
* @copyright 2009-2019 Vanilla Forums Inc.
5+
* @license GPL-2.0-only
6+
*/
7+
8+
import { formatUrl, t, getMeta, siteUrl } from "@library/utility/appUtils";
9+
import { indexArrayByKey } from "@vanilla/utils";
10+
import axios, { AxiosResponse, AxiosRequestConfig } from "axios";
11+
import qs from "qs";
12+
import { sprintf } from "sprintf-js";
13+
import { humanFileSize } from "@library/utility/fileUtils";
14+
import { IApiError, IFieldError } from "@library/@types/api/core";
15+
import { IUserFragment } from "@library/@types/api/users";
16+
17+
function fieldErrorTransformer(responseData) {
18+
if (responseData && responseData.status >= 400 && responseData.errors && responseData.errors.length > 0) {
19+
responseData.errors = indexArrayByKey(responseData.errors, "field");
20+
}
21+
22+
return responseData;
23+
}
24+
25+
const apiv2 = axios.create({
26+
baseURL: siteUrl("/api/v2/"),
27+
headers: {
28+
common: {
29+
"X-Requested-With": "vanilla",
30+
},
31+
},
32+
transformResponse: [...(axios.defaults.transformResponse as any), fieldErrorTransformer],
33+
paramsSerializer: params => qs.stringify(params),
34+
});
35+
36+
export default apiv2;
37+
38+
export type ProgressHandler = (progressEvent: any) => void;
39+
40+
export function createTrackableRequest(
41+
requestFunction: (progressHandler: ProgressHandler) => () => Promise<AxiosResponse>,
42+
) {
43+
return (onUploadProgress: ProgressHandler) => {
44+
return requestFunction(onUploadProgress);
45+
};
46+
}
47+
/**
48+
* Upload an image using Vanilla's API v2.
49+
*
50+
* @param file - The file to upload.
51+
*/
52+
export async function uploadFile(file: File, requestConfig: AxiosRequestConfig = {}) {
53+
let allowedExtensions = getMeta("upload.allowedExtensions", []) as string[];
54+
allowedExtensions = allowedExtensions.map((ext: string) => ext.toLowerCase());
55+
const maxSize = getMeta("upload.maxSize", 0);
56+
const filePieces = file.name.split(".");
57+
const extension = filePieces[filePieces.length - 1] || "";
58+
59+
if (file.size > maxSize) {
60+
const humanSize = humanFileSize(maxSize);
61+
const stringTotal: string = humanSize.amount + humanSize.unitAbbr;
62+
const message = sprintf(t("The uploaded file was too big (max %s)."), stringTotal);
63+
throw new Error(message);
64+
} else if (!allowedExtensions.includes(extension.toLowerCase())) {
65+
const attachmentsString = allowedExtensions.join(", ");
66+
const message = sprintf(
67+
t(
68+
"The uploaded file did not have an allowed extension. \nOnly the following extensions are allowed. \n%s.",
69+
),
70+
attachmentsString,
71+
);
72+
throw new Error(message);
73+
}
74+
75+
const data = new FormData();
76+
data.append("file", file, file.name);
77+
78+
const result = await apiv2.post("/media", data, requestConfig);
79+
return result.data;
80+
}
81+
82+
/**
83+
* Extract a field specific error from an ILoadable if applicable.
84+
*
85+
* @param apiError - The error to extract from.
86+
* @param field - The field to extract.
87+
*
88+
* @returns an array of IFieldErrors if found or undefined.
89+
*/
90+
export function getFieldErrors(apiError: IApiError | undefined, field: string): IFieldError[] | undefined {
91+
if (!apiError) {
92+
return;
93+
}
94+
95+
const serverError = apiError.response.data;
96+
if (serverError && serverError.errors && serverError.errors[field]) {
97+
return serverError.errors[field];
98+
}
99+
}
100+
101+
/**
102+
* Extract a global error message out of an ILoadable if applicable.
103+
*
104+
* @param apiError - The error to extract from.
105+
* @param validFields - Field to check for overriding fields errors from. A global error only shows if there are no valid field errors.
106+
*
107+
* @returns A global error message or an undefined.
108+
*/
109+
export function getGlobalErrorMessage(apiError: IApiError | undefined, validFields: string[] = []): string | undefined {
110+
if (!apiError) {
111+
return;
112+
}
113+
for (const field of validFields) {
114+
if (getFieldErrors(apiError, field)) {
115+
return;
116+
}
117+
}
118+
119+
const serverError = apiError.response && apiError.response.data;
120+
if (serverError && serverError.message) {
121+
return serverError.message;
122+
}
123+
124+
return t("Something went wrong while contacting the server.");
125+
}

0 commit comments

Comments
 (0)