@medusa-v2-vue/core v0.2.1
Medusa V2 Vue
Vue 3 composables and components for seamless and streamlined interaction with a Medusa.
If you're building a custom vue based storefront that consumes a medusa backend and find yourself wishing you had something nice at hands like medusa-react
to streamline your data management - this might be your library!
Installation
The library uses @tanstack/vue-query under the hood.
For the core composables run:
npm install @medusa-v2-vue/core
# or
yarn add @medusa-v2-vue/core
For the components (WIP :construction_worker:):
npm install @medusa-v2-vue/components
# or
yarn add @medusa-v2-vue/components
Quick Start
In order to use the composables exposed by this library you need to register it as a plugin in your main file before mounting your app. The plugin takes a config object that needs at least a baseUrl
where it can reach your server. Optionally, it allows you to pass additional props to configure both the underlying medusa-js
and the vue-query
client. Here's the complete interface. Refer to these and these docs, respectively to get an idea on how the parts work together.
interface MedusaVueClientProps {
baseUrl: string;
maxRetries?: number;
/**
* Authentication token
*/
apiKey?: string;
/**
* PublishableApiKey identifier that defines the scope of resources
* available within the request
*/
publishableApiKey?: string;
queryClientProviderProps?: VueQueryPluginOptions;
}
Plug it in:
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import { createMedusaVueClient } from '@medusa-v2-vue/core';
const client = createMedusaVueClient({
baseUrl: '<YOUR_SERVER_BASE_URL>',
});
const app = createApp(App);
app.use(client).mount('#app');
The hooks exposed by medusa-v2-vue
fall into two main categories: queries and mutations.
Queries
Queries simply wrap around vue-query's useQuery
hook to fetch some data from your medusa server
// ./my-product-list.vue
<script setup lang="ts">
import { watch } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
import { useProducts } from '@medusa-v2-vue/core';
const { data, error, isLoading } = useProducts();
</script>
<template>
<ul v-for="products in data?.products">
<li>...</li>
</ul>
</template>
Note: If you've worked with @medusajs/medusa-react you might be used to being able to destructure the recordset returned by the server, i.e. const { products } = useProducts()
. This is however not possible with vue due to the way it's reactive system works.
Mutations
Mutations wrap around vue-query's useMutation
to mutate data and perform server-side effects on your medusa server. If you are not entirely familiar with this idea of "mutations", creating a cart would be a mutation because it creates a cart in your server (and database). Mutations also have to be invoked imperatively, meaning that calling for the mutation to take action, you will have to call a mutate()
function returned from mutation hooks.
<script setup lang="ts">
import { useCreateCart } from '@medusa-v2-vue/core';
const createCart = useCreateCart();
const handleClick = () => {
createCart.mutate({}); // create an empty cart
};
</script>
<template>
<Button isLoading="{createCart.isLoading}" onClick="{handleClick}">
Create cart
</Button>
</template>
The mutation hooks will return exactly what vue-query's useMutation
returns. In addition, the options you pass in to the hooks will be passed along to useMutation
.
Components
NOTE: This is still work in progress and new components will gradually be added!:construction_worker:
If you prefer declarative templates, @medusa-v2-vue/components
provided (almost) renderless components to use directly in your template and provide data through slot-props
. This allows for extremely streamlinend and declarative templating:
<script setup lang="ts">
import { UseProducts } from '@medusa-v2-vue/components';
</script>
<template>
<use-products v-slot="{ data, isLoading }">
<loading-spinner v-if="isLoading" />
<product-list :products="data.products" />
</use-products>
</template>
The component also allows to pass down the laoding indicating component via a slot:
<script setup lang="ts">
import { UseProducts } from '@medusa-v2-vue/components';
</script>
<template>
<use-products>
<template #fallback>
<div>Loading....</div>
</template>
<template v-slot="{ data, isLoading }">
<product-list :products="data.products" />
</template>
</use-products>
</template>
Utilities
A set of utility functions are also exposed from the library to make your life easier when dealing with displaying money amounts
formatAmount()
formatAmount(params: FormatAmountParams): string
type FormatAmountParams = {
amount: number;
region: RegionInfo;
includeTaxes?: boolean;
minimumFractionDigits?: number;
maximumFractionDigits?: number;
locale?: string;
};
Returns a localized string based on the input params representing the amount (i.e: "$10.99").
Credits
Based on and inspired by medusa-react. Keep up the good work! :beers: