@boite-beet/api-client v2.1.0
BEET API Client
Beet's API client for WP and Laravel Nova
Installation
In an existing project, open a command line at the root level and run:
yarn add @boite-beet/api-clientUsage
In src/main.js initialize through Vue's plugin api:
// src/main.js
import BeetAPI from '@boite-beet/api-client'
import store from './store'
Vue.use(BeetAPI, {
store,
apiUrl: process.env.VUE_APP_API_URL,
mode: 'nova',
initialData: { userInvoices: {} },
defaultLang: 'fr'
})Configuration
The configuration object accepts three properties:
| Property | Type | Default | Details |
|---|---|---|---|
| store | Vuex instance | required | This plugin needs to add itself as a module in your project's vuex store. |
| apiUrl | String | required | The backend's base URL. Should be stored in .env files. |
| mode | String | 'nova' | Accepts either 'nova' or 'wp'. |
| initialData | Object | {} | An object that will be mixed into the data state every time fetchCoreData is called. This is intended for custom-types that are not returned with the core data, such as private data that requires authentication. |
| defaultLang | String | null | Define the default lang of the backend. (Used to remove lang from the query with wp-json) |
If you are using our Vue project template (which you should ಠ_ಠ) this will already be in place.
Store state structure
The store module's initial state looks like this:
{
pages: {},
options: {},
data: {},
isReady: false
}- The
pagesobject stores all individual page data (home, about, contact, etc.) under a key corresponding to the page's backend slug. - The
optionsobject contains all shared data (company info, social media, etc.) from the options route. - The
dataobject is where all the custom types are stored under a key corresponding to the custom type's backend slug. - Finally,
isReadyis a boolean that will becometrueonce the first call to/dataand/optionshas completed.
The full store path to this state is $store.state.beet but can be accessed more easily through the $beet global injection, detailed below.
Global state
The plugin exposes a global $beet property on all instances of Vue. This property contains all of the same data you'll find in the vuex state except for the data property, which is instead mixed into the object. This means all your custom types are exposed at the root level (eg. $beet.products).
There is also a fetchCoreData method, for retrieving the core data returned from the /data and /options endpoints. This method is detailed below.
Loading core data
The core data, which is found at the /data and /options endpoint in our APIs, is the minimum required dataset needed to ensure the app won't crash due to missing fields.
The ideal place to fetch this data is from src/App.vue seeing as you only want to fetch on first load and when the language changes. The root App.vue component will only be loaded once and is persistent for the rest of the session.
fetchCoreData method
To launch the request to the API, use the fetchCoreData method found on the $beet global injection. It accepts two optional arguments:
- the first is the current language code, which will be passed as the
langquery parameter to the backend. Defaults to undefined and will be omitted from the query. - the second is a function to transform the data before storing it. It will receive the response object as its only argument and the returned object will then be stored in the vuex state.
Detecting when core data is loaded
Once the first call to this method has completed, $beet.isReady will become true. This can be used to universally block rendering at the root level to prevent errors caused by missing core data.
Examples
For single language sites
<template>
<main v-if="$beet.isReady" id="app">
<RouterView />
</main>
</template>
<script>
export default {
name: 'App',
beforeMount() {
this.$beet.fetchCoreData()
}
}
</script>For multi language sites using our LangRouter package
<template>
<main v-if="$beet.isReady" id="app">
<RouterView />
</main>
</template>
<script>
export default {
name: 'App',
watch: {
'$lang.current': {
immediate: true,
handler(lang) {
this.$beet.fetchCoreData(lang)
}
}
}
}
</script>If you're using 'wp' mode, don't forget to setup the 'defaultLang' param in the install of this plugin or wp-json will fail to return a correct response.
Dynamically adding custom types
If for any reason there are custom types that are excluded from the /data route, you can load them manually at any time using the fetchData action which is detailed later.
However the key corresponding to this custom type will not exist in the state until it is fetched. This can cause the app to crash if you try to access items in that dataset before they have finished loading.
To help address this, you can add an initialData property to the options object when you call Vue.use. This will be merged into the data state object every time fetchCoreData is called. With this done, we could safely try to access trainings in this object to see if they existed before attempting to read the data.
Pages
To load the data associated with a given page, use the beetPage component option to indicate which slug to fetch from the API. Once a page's content has been loaded, it will not be fetched again. Instead, the existing content will be returned.
A $page computed property will be created on your component. The property's value will be null until the data has loaded, at which point the object will be accessible through $page. You can leverage this to prevent the content from rendering until the data is ready.
It may however not be desireable to place the v-if attribute on the root element, as this could cause the layout to appear broken or incomplete until the page is loaded. Instead, you can apply the condition to a <template> child element.
Specifying language
If you are using our LangRouter package, the language will be picked up and changes to it will re-fetch content automatically.
In cases where you aren't using the LangRouter, you can specify the language key to watch by adding a beetLang option to your component. This should be a string representing the key of anything reactive accessible on the component's this.
export default {
name: 'Home',
beetPage: 'home',
beetLang: '$i18n.locale'
}If both the LangRouter's $lang.current and beetLang are defined, beetLang takes precedence.
Example
<!-- src/views/Home.vue -->
<template>
<div :class="['home', { '-loading': !$page }]">
<template v-if="$page">
<header class="header">
<h1 class="header__title">{{ $page.title }}</h1>
</header>
<!-- ... -->
</template>
</div>
</template>
<script>
export default {
name: 'Home',
beetPage: 'home'
}
</script>Actions
There are two configurable actions which are intended to be used in your app.
fetchData
This action is used to fetch an index of a custom type's items and store them. This is useful for indexes that are not returned in the core dataset. The action payload is an array of arguments following this usage pattern:
this.$store.dispatch('fetchData', [dataKey, axiosConfig, dataParser])Arguments
| Argument | Required | Details |
|---|---|---|
dataKey | yes | The key under which the dataset is stored in state.data |
axiosConfig | yes | An axios request config object |
dataParser | no | A function to transform the data before it is saved |
Example
This example would load the response from /events into data.events.
this.$store.dispatch('fetchData', ['events', { url: '/events' }])fetchSingle
This action is used to fetch a specific item of a custom type and store it. This can be particularly useful when the index only returns a subset of the item's contents and needs to be completed. The returned object will be mixed into the current value if it exists, preserving any non-duplicate keys. The action payload is an array of arguments following this usage pattern:
this.$store.dispatch('fetchSingle', [dataKey, singleKey, axiosConfig, dataParser])Arguments
| Argument | Required | Details |
|---|---|---|
dataKey | yes | The dataset key under which the item is stored in state.data |
singleKey | yes | The key under which the item is stored in the dataset |
axiosConfig | yes | An axios request config object |
dataParser | no | A function to transform the data before it is saved |
Example
This example would load the response from /events/party into data.events.party.
this.$store.dispatch('fetchSingle', ['events', 'party', { url: '/events/party' }])Notes
Axios request config
Only the baseURL property will be automatically set to the API's URL if it is not provided. This allows you to take full control of how the data is fetched. For example, you can add authentication headers to the request by passing the headers property. See the axios docs for more information.
Detecting request completion
Both of them return a Promise which can be used to know when the data has been loaded and saved in the state:
export default {
name: 'PrivateTraining',
props: {
slug: { type: String, required: true }
},
data() {
return { isDataReady: false }
},
beforeMount() {
const arguments = [
'privateTrainings',
this.slug,
{ url: `/trainings/${this.slug}` }
]
this.$store.dispatch('fetchSingle', arguments)
.then(() => {
this.isDataReady = true
})
}
}Development
Compilation/build is done using Rollup.js.
Installation
Clone the package and install the dependencies.
git clone git@bitbucket.org:boitebeet/beet-api-client.git
cd beet-api-client
yarnScripts
build- compiles the package into thedist/directory.start- compiles the package every time the source changes.
Using local package in a project
Yarn has built in functionality that allows you to link a local package to a project. The "package" is the library that will be installed via npm and the "project" is the app/website in which you want to test it.
In the package's directory
yarn linkThis only needs to be done once, the link remains available until you run yarn unlink. There is no danger or issue created by leaving the link permanently.
In your project's directory
yarn link @boite-beet/api-clientNow, if you run yarn start in the package and yarn start in your project, your project's development server will detect when the package has changed (compile on save) and reload.
Unlinking from your project
Once you are done working on the package and have published, it is recommended to unlink it from your project and reinstall the dependancy to verify that everything has deployed correctly.
To do this, run these commands in your project:
yarn unlink @boite-beet/api-client
yarn add @boite-beet/api-client@latestPublishing
This requires you to be a member of the boite-beet org on npm and for you to be logged in to your npm account (using the npm login command).
Publish from master
Make sure you are in the master branch and that all your changes have been merged.
git checkout master
git merge developUpdate the version
Run the yarn version command and enter the new version as prompted. This will also create a version tag in git. Versions should follow the semver pattern of major.minor.patch
- Patch: bugfixes and inconsequential changes
- Minor: new features
- Major: breaking changes
Push changes including version tags
git push --follow-tagsPublish to npm
npm publishMerge the new package version into develop
git checkout develop
git merge master3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago