I have a Vue3 app in which I use the following approach to API calls:
- there's an
apifolder, inside which lie functions that directly make a call to the backend. For example:
export async function getCourses(): Promise<Course[]> {
const response = await axios.get(`/courses/`);
return response.data;
}
export async function getCourse(courseId: string): Promise<Course> {
const response = await axios.get(`/courses/${courseId}/`);
return response.data
}
export async function getExercises(courseId: string): Promise<Exercise[]> {
const response = await axios.get(`/courses/${courseId}/exercises/`);
return response.data
}
there a Vuex store, whose actions invoke those functions in the
apifolders and commit data to the store's stateVue components access the store state and dispatch actions to it in order to retrieve data
The problem I have with this approach is that the api functions get extremely repetitive. I have to define 4 different functions just to enable CRUD on an entity, and all of them take almost the same parameters (for example, in my app, all resources are sub resource of a course and hence require the courseId parameter for fetching) and have the same structure (await an axios call and return the response's data).
I'd much prefer a method where I declaratively define the routes and the parameters they expect (as far as url components such as id's), and then be able to type-safely do something like this:
getApiService().courses(courseId).delete() // deletes a course
getApiService().courses(courseId).exercises().get(exerciseId) // returns an exercise
getApiService().courses(courseId).exercises().post(payload) // creates and returns an exercise
getApiService().courses(courseId).exercises().get(exerciseId).choices().list() // returns the list of choices for an exercise
// and so on
What would be a good way to accomplish this? Are there any existing packages that do this for Vue3?
getApiService().courses(courseId).exercises().get(exerciseId).choices().list()is going to work. It's asynchronous and can't return a result immediately to chain it. Is it supposed to be Fluent interface pattern?list(). The previous chained methods would pretty much just build the call url.thiswith each method exceptlist, and and execute a command withlist. If you do this for your own use, not for learning purpose or public lib with fancy api, this is 100% overengineering you'll regret later. Most times KISS beats DRY, just takes some practice to see when it really doesn't