vue-restful
v1.0.0
Published
Vue composables for streamlined RESTful API endpoint interactions.
Downloads
7
Readme
This is a TypeScript library to make RESTful API interactions reactive. It wraps an Axios instance for easy compatibility with any existing interceptors and headers you have. It also leverages Axios's request cancellation feature to avoid common race conditions and guarantee consistent states.
Here is an example of loading a "foo" object along with all its associated
"bar"s based on a fooId
prop to the component. In practice fooId
might come
from other locations such as a route or query parameter.
setup(props) {
const { fooId } = toRefs(props);
const { data: foo } = useDetailApi<Foo>('/foo/', fooId);
const { data: bars } = useListApi<Bar>('/bar/', {
params: { foo: fooId },
});
return {
foo,
bars,
}
},
If fooId
is initially 123
, this will load data from /foo/123/
and
/bars/?foo=123
. The resulting types are foo: Maybe<Foo>
and bars: Bar[]
.
Any time fooId
changes, any previous results from both endpoints are cleared,
in-flight requests are canceled, and the new requests are sent out.
Common API
There are four variations of useApi
right now, but they all share a few
common inputs (options) and provide many common outputs (refs and functions).
Options
axiosInstance
- The Axios instance to use. Defaults to the global instance.auto
- Controls whether the data is automatically fetched (immediately and reactively) or not. Defaults totrue
. Can be passed as a ref.params
- The query parameters to pass with the GET request. Supports either a ref containing an optional object, an object containing refs, or a plain object. Passing a ref containing an object or an object containing refs makes the system reactive to changes of those ref's values. If the object ref's value isnull
, requests are suppressed.extractResponseData
- Tells the library how to get the data item(s) from the response. The function gets passedresponse.data
and defaults tox => x
.trailingSlash
- Exists for all variants exceptuseEndpointApi
; controls how an ID is concatenated with the base URL for detail endpoints.allowGlobal
- Developers unfamiliar with the Composition API have a tendency to misuse the composables, so by default they throw an error if called from outside an active EffectScope (typically a component'ssetup()
function). Set this to true to suppress the error if you're sure it's what you intend to do.
Refs
data
- The currently loaded data; either aMaybe<T>>
orT[]
depending on the form.mostRecentData
loaded data; not cleared out when changingparams
,auto
, orurl
.loading
- Whether any requests are in-flight.loaded
- Whether a GET has returned successfully since the lastclear
.error
- The lastError
encountered by any requests made, ornull
.
Functions
list
ordetail
- GET the data from the endpoint.post
- POST a new item to the endpoint.put
- PUT an item to the endpoint.patch
- PATCH an existing item to the endpoint.remove
- DELETE an existing item from the endpoint.clear
- Resets all internal state and cancels any in-flight requests. This method is called automatically for reactive updates.
useDetailApi and useEndpointApi
These variations are for use with an API that returns a single value. The
data
ref will be a Maybe<T>
for both of them. The only difference between
them is that useDetailApi
requires an ID as an argument and automatically
constructs the final URL using it. Technically useDetailApi
is a special case
of useEndpointApi
, but it is expected to be far more commonly used.
Whenever the URL (or ID, for detail) refs are null
, data loading is
suppressed. This can be used to delay requests until all the necessary
prerequisite data is available.
useListApi
This variation is for use with an API endpoint that returns a list. The data
ref will be a T[]
. Results are stored in an object map keyed by their ID
(accessible via the byId
ref) but their order is maintained by an array of
IDs. These two data structures are then mapped together to produce the output
data
ref. This approach guarantees a consistent internal state for any given
item ID.
It is expected that the detail endpoint for each item returned can be
constructed by appending the ID of the item to the base URL in accordance with
the trailingSlash
property. For example, if you pass /foo/
as the URL, and
it returns a Foo with ID 123, /foo/123/
should be the endpoint for
PUT/PATCH/DELETE requests.
List Options
getId
- How to extract the ID for an item. The function is passed an item of typeT
and must return astring
ornumber
.extractResponseCount
- A function to get the response's total count of results fromresponse.data
. Should return a number and defaults to() => 0
.
List Refs
byId
- Maps item IDs to their values.count
- The total count of items this endpoint can return (e.g. ignoring anylimit
clauses). Always zero unlessextractResponseCount
is set.
useInfiniteScrollApi
This variation builds on top of useListApi
to provide a convenient mechanism
for use with infinite scroll UIs. The limit
option controls how many items
are loaded at a time, and an internal offset
state is tracked. Each call to
list
will increment offset
by the value of limit
and append the results.
This means that unlike every other variant, it is expected that list
will
need to be manually called when more results are needed (generally auto
reactivity is sufficient for other variants).
Infinite Scroll Options
limit
- The amount of items to load at a time. Can be a number or a number ref. Defaults to100
.
Infinite Scroll Refs
offset
- The offset that will be used for the nextlist
call.
Provide/Inject
If you are using things bound from the use*Api
call at multiple levels of the
component tree, it is recommended to use Vue's provide/inject framework to
provide the entire result of the call to your component tree using an
InjectionKey
symbol for type checking.
Sharing Configuration
Since it is likely that multiple endpoints will be used from a server with a shared Axios instance and response shapes, it is recommended to create wrapper functions for each variant that inject those options by default.