Last active
July 12, 2018 17:50
-
-
Save Mrtenz/d4c0791ea060d7563d78f66e6938bb3c to your computer and use it in GitHub Desktop.
Utility functions for interacting with a JSON API in TypeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Generate request data. | |
* @param {"POST" | "GET" | "DELETE" | "PUT" | "PATCH"} method | |
* @param body | |
* @return {{[key: string]: any}} | |
*/ | |
const generateData = (method: 'POST' | 'GET' | 'DELETE' | 'PUT' | 'PATCH', body?: any): { [key: string]: any } => { | |
return { | |
method, | |
credentials: 'include', | |
headers: { | |
'Accepts': 'application/json', | |
'Content-Type': 'application/json' | |
}, | |
body: JSON.stringify(body) | |
}; | |
}; | |
/** | |
* Generate a request. | |
* @param {string} path | |
* @param {"POST" | "GET" | "DELETE" | "PUT" | "PATCH"} method | |
* @param {Data} body | |
* @return {Promise<Data>} | |
*/ | |
const generateRequest = <Data> (path: string, method: 'POST' | 'GET' | 'DELETE' | 'PUT' | 'PATCH', body?: Data): Promise<Data> => { | |
return new Promise<Data>((resolve, reject) => { | |
fetch(path, generateData(method, body)) | |
.then(data => handleResponse<Data>(data)) | |
.then(resolve) | |
.catch(reject); | |
}); | |
}; | |
/** | |
* Handle the response of a request. This assumes the response status code is 200 and throws an error otherwise. | |
* @param {Response} response | |
* @return {Promise<Data>} | |
*/ | |
const handleResponse = async <Data> (response: Response): Promise<Data> => { | |
const json = await response.json(); | |
if (response.status === 200) { | |
return json; | |
} | |
throw new Error(json.message); | |
}; | |
/** | |
* Execute a HTTP GET request. | |
* @param {string} path | |
* @param params | |
* @returns {Promise<Data>} | |
*/ | |
export const get = <Data = any> (path: string, params?: { [key: string]: string }): Promise<Data> => { | |
let queryString = ''; | |
if (params) { | |
queryString = Object.keys(params).map(key => key + '=' + params[key]).join('&'); | |
} | |
return generateRequest<Data>(`${path}${queryString}`, 'GET'); | |
}; | |
/** | |
* Execute a HTTP POST request. | |
* @param {string} path | |
* @param body | |
* @returns {Promise<Data>} | |
*/ | |
export const post = <Data = any> (path: string, body?: any): Promise<Data> => { | |
return generateRequest<Data>(path, 'POST', body); | |
}; | |
/** | |
* Execute a HTTP DELETE request. | |
* @param {string} path | |
* @param body | |
* @return {Promise<Data>} | |
*/ | |
export const del = <Data = any> (path: string, body?: any): Promise<Data> => { | |
return generateRequest<Data>(path, 'DELETE', body); | |
}; | |
/** | |
* Execute a HTTP PUT request. | |
* @param {string} path | |
* @param body | |
* @return {Promise<Data>} | |
*/ | |
export const put = <Data = any> (path: string, body?: any): Promise<Data> => { | |
return generateRequest<Data>(path, 'PUT', body); | |
}; | |
/** | |
* Execute a HTTP PATCH request. | |
* @param {string} path | |
* @param body | |
* @return {Promise<Data>} | |
*/ | |
export const patch = <Data = any> (path: string, body?: any): Promise<Data> => { | |
return generateRequest<Data>(path, 'PATCH', body); | |
}; | |
/** | |
* Wrapper for promises to make it easier to catch errors when using async/await. | |
* | |
* Example usage: | |
* const { error, data } = await to(getUsers()); | |
* @type <T> | |
* @param {Promise<T>} promise | |
* @returns {Promise<{error?: Error, data?: T}>} | |
*/ | |
export const to = <T> (promise: Promise<T>): Promise<{ error?: Error, data?: T }> => { | |
return promise | |
.then(data => ({ | |
data | |
})) | |
.catch(error => ({ | |
error | |
})); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment