## 👉 [Demo](https://vcuiu.csb.app/)
-⚠️⚠️⚠️ This project is experimental, it's an exploration of what a _Store_ could be like using [the composition api](https://vue-composition-api-rfc.netlify.com). It works for Vue 2 by using the [official library](https://github.com/vuejs/composition-api).
+⚠️⚠️⚠️ This project is experimental, it's an exploration of what a _Store_ could be like using [the composition api](https://vue-composition-api-rfc.netlify.com). It works for Vue 2 by using the [official plugin](https://github.com/vuejs/composition-api) to add Composition API support to Vue 2.
**If you are looking for the version compatible with Vue 3.x, check the [`v2` branch](https://github.com/posva/pinia/tree/v2)**
-What I want is to inspire others to think about ways to improve Vuex and come up with something that works very well with the composition api. Ideally it could also be used without it. **@vue/composition-api is necessary**.
+What I want is to inspire others to think about ways to improve Vuex and come up with something that works very well with the composition api. Ideally it could also be used without it. Note **@vue/composition-api must be installed and used by your application** for Pinia to work.
There are the core principles that I try to achieve with this experiment:
You can create as many stores as you want, and they should each exist in different files:
```ts
-import { createStore } from 'pinia'
+import { defineStore } from 'pinia'
-export const useMainStore = createStore({
+export const useMainStore = defineStore({
// name of the store
// it is used in devtools and allows restoring state
id: 'main',
})
```
-`createStore` returns a function that has to be called to get access to the store:
+`defineStore` returns a function that has to be called to get access to the store:
```ts
import { useMainStore } from '@/stores/main'
### Accessing other Stores
-You can `useOtherStore` inside a store `actions` and `getters`:
+You can `useOtherStore()` inside a store `actions` and `getters`:
Actions are simply function that contain business logic. As with components, they **must call `useStore`** to retrieve the store:
```ts
-createStore({
+defineStore({
id: 'cart',
state: () => ({ items: [] }),
getters: {
To prevent this, **we follow the rule above** and we create a new file with a new store:
```ts
-import { createStore } from 'pinia'
+import { defineStore } from 'pinia'
import { useUserStore } from './user'
import { useCartStore } from './cart'
-export const useSharedStore = createStore({
+export const useSharedStore = defineStore({
id: 'shared',
getters: {
summary() {
When an actions needs to use multiple stores, we do the same, we create a new file with a new store:
```ts
-import { createStore } from 'pinia'
+import { defineStore } from 'pinia'
import { useUserStore } from './user'
import { useCartStore } from './cart'
-export const useSharedStore = createStore({
+export const useSharedStore = defineStore({
id: 'shared',
state: () => ({}),
actions: {
})
```
-#### Creating _Pinias_
-
-_Not implemented_. Still under discussion, needs more feedback as this doesn't seem necessary because it can be replaced by shared stores as shown above.
-
-Combine multiple _stores_ (gajos) into a new one:
-
-```ts
-import { pinia } from 'pinia'
-import { useUserStore } from './user'
-import { useCartStore, emptyCart } from './cart'
-
-export const useCartUserStore = pinia(
- {
- user: useUserStore,
- cart: useCartStore,
- },
- {
- getters: {
- combinedGetter () {
- return `Hi ${this.user.name}, you have ${this.cart.list.length} items in your cart. It costs ${this.cart.price}.`,
- }
- },
- actions: {
- async orderCart() {
- try {
- await apiOrderCart(this.user.token, this.cart.items)
- this.cart.emptyCart()
- } catch (err) {
- displayError(err)
- }
- },
- },
- }
-)
-```
-
## TypeScript
Pinia is conceived to make typing automatic, benefiting both, JS and, TS users. There are however different ways of handling types when using TS
name: string
}
-export const useMainStore = createStore({
+export const useMainStore = defineStore({
id: 'main',
state: (): MainState => ({
counter: 0,
})()
}
- const useB = createStore({
+ const useB = defineStore({
id: 'B',
state: () => ({ b: 'b' }),
})
- const useA = createStore({
+ const useA = defineStore({
id: 'A',
state: () => ({ a: 'a' }),
actions: {
})()
}
- const useB = createStore({
+ const useB = defineStore({
id: 'B',
state: () => ({ b: 'b' }),
})
- const useA = createStore({
+ const useA = defineStore({
id: 'A',
state: () => ({ a: 'a' }),
getters: {
-import { createStore } from '../../../src'
+import { defineStore } from '../../../src'
import { useUserStore, UserStore } from './user'
import { PiniaStore, ExtractGettersFromStore } from 'src/store'
-export const useCartStore = createStore({
+export const useCartStore = defineStore({
id: 'cart',
state: () => ({
rawItems: [] as string[],
-import { createStore, WrapStoreWithId } from 'src/store'
+import { defineStore, WrapStoreWithId } from 'src/store'
function apiLogin(a: string, p: string) {
if (a === 'ed' && p === 'ed') return Promise.resolve({ isAdmin: true })
return Promise.reject(new Error('invalid credentials'))
}
-export const useUserStore = createStore({
+export const useUserStore = defineStore({
id: 'user',
state: () => ({
name: 'Eduardo',
-import { createStore, getRootState } from '../src'
+import { defineStore, getRootState } from '../src'
describe('Root State', () => {
- const useA = createStore({
+ const useA = defineStore({
id: 'a',
state: () => ({ a: 'a' }),
})
- const useB = createStore({
+ const useB = defineStore({
id: 'b',
state: () => ({ b: 'b' }),
})
-import { createStore } from '../../../src'
+import { defineStore } from '../../../src'
-export const useStore = createStore({
+export const useStore = defineStore({
id: 'main',
state: () => ({
counter: 0,
-import { createStore } from '../../src'
+import { defineStore } from '../../src'
import { expectType, expectError } from 'tsd'
-const useStore = createStore({
+const useStore = defineStore({
id: 'name',
state: () => ({ a: 'on' as 'on' | 'off' }),
getters: {
}
/** @type {import('@nuxt/types').Plugin} */
-const myPlugin = context => {
+const myPlugin = (context) => {
// console.log('🍍 Pinia Nuxt plugin installed')
if (process.server) {
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import ts from 'rollup-plugin-typescript2'
-import alias from '@rollup/plugin-alias'
import { terser } from 'rollup-plugin-terser'
import path from 'path'
import rimraf from 'rimraf'
// force production mode when minifying
if (minify) env = 'production'
+ const isBundlerESMBuild = format == 'es'
+ const isNodeBuild = format == 'cjs'
+ const isProduction = env == 'production'
+
const config = {
input,
plugins: [
replace({
__VERSION__: pkg.version,
+ __BROWSER__: JSON.stringify(isBrowser),
'process.env.NODE_ENV': `'${env}'`,
- }),
- alias({
- resolve: ['.ts', '.js'],
- // entries: [{ find: 'firebase', replacement: path.join(__dirname, './stub') }],
+ __DEV__:
+ isBundlerESMBuild || (isNodeBuild && !isProduction)
+ ? // preserve to be handled by bundlers
+ `(process.env.NODE_ENV !== 'production')`
+ : // hard coded dev/prod builds
+ JSON.stringify(!isProduction),
}),
],
output: {
--- /dev/null
+import { defineStore } from './store'
+
+/**
+ * {@inheritDoc defineStore}
+ * @deprecated Use {@link defineStore}
+ */
+export const createStore = ((options: any) => {
+ console.warn(
+ '[🍍]: "defineStore" has been deprecated and will be removed on the sable release, use "defineStore" instead.'
+ )
+ return defineStore(options)
+}) as typeof defineStore
--- /dev/null
+export const IS_CLIENT = typeof window !== 'undefined'
--- /dev/null
+// Global compile-time constants
+declare let __DEV__: boolean
+declare let __TEST__: boolean
+declare let __BROWSER__: boolean
+declare let __CI__: boolean
StoreWithState,
} from './types'
export { PiniaSsr } from './ssrPlugin'
+
+export { createStore } from './deprecated'
}
/**
- * Creates a `useStore` function that retrieves the store instance
+ * Defines a `useStore()` function that creates or retrieves the store instance
+ * when called.
+ *
* @param options
*/
-export function createStore<
+export function defineStore<
Id extends string,
S extends StateTree,
G /* extends Record<string, StoreGetterThis> */,