+import type Vue from 'vue'
import {
+ GenericStore,
GenericStoreDefinition,
Method,
StateTree,
? StoreObject<L> & Spread<R>
: unknown
+function getCachedStore<
+ Id extends string = string,
+ S extends StateTree = StateTree,
+ G = Record<string, Method>,
+ A = Record<string, Method>
+>(vm: Vue, useStore: StoreDefinition<Id, S, G, A>): Store<Id, S, G, A> {
+ const cache = vm._pStores || (vm._pStores = {})
+ const id = useStore.$id
+ return (cache[id] || (cache[id] = useStore(vm.$pinia))) as Store<Id, S, G, A>
+}
+
/**
- * Allows using stores without the composition API (`setup()`) by generating an object to be spread in the `computed` field of a component.
+ * Allows using stores without the composition API (`setup()`) by generating an
+ * object to be spread in the `computed` field of a component. it accepts a list
+ * of store definitions.
*
* @example
* ```js
* // other computed properties
* ...mapStores(useUserStore, useCartStore)
* },
-
+ *
* created() {
* this.userStore // store with id "user"
* this.cartStore // store with id "cart"
*
* @param stores - list of stores to map to an object
*/
-export function mapStores<Stores extends unknown[]>(
+export function mapStores<Stores extends GenericStoreDefinition[]>(
...stores: [...Stores]
): Spread<Stores> {
return stores.reduce((reduced, useStore) => {
// @ts-ignore: $id is added by defineStore
- reduced[useStore.$id + 'Store'] = function () {
- return (useStore as GenericStoreDefinition)((this as any).$pinia)
+ reduced[useStore.$id + 'Store'] = function (this: Vue) {
+ return getCachedStore(this, useStore)
}
return reduced
}, {} as Spread<Stores>)
): MapStateReturn<S, G> | MapStateObjectReturn<S, G, KeyMapper> {
return Array.isArray(keysOrMapper)
? keysOrMapper.reduce((reduced, key) => {
- // @ts-ignore: too complicated for TS
- reduced[key] = function () {
- return useStore((this as any).$pinia)[key]
+ // @ts-ignore: sorry TS
+ reduced[key] = function (this: Vue) {
+ return getCachedStore(this, useStore)[key]
}
return reduced
}, {} as MapStateReturn<S, G>)
: Object.keys(keysOrMapper).reduce((reduced, key: keyof KeyMapper) => {
- reduced[key] = function () {
- return useStore((this as any).$pinia)[keysOrMapper[key]]
+ reduced[key] = function (this: Vue) {
+ return getCachedStore(this, useStore)[keysOrMapper[key]]
}
return reduced
}, {} as MapStateObjectReturn<S, G, KeyMapper>)
// : never
// }
-// has the actions without the context (this) for typings
/**
* Store type to build a store
*/
Id extends string,
S extends StateTree,
G,
+ // has the actions without the context (this) for typings
A
> = StoreWithState<Id, S> &
S &
}
/**
- * Generic version of Store
+ * Generic version of Store.
*/
export type GenericStore = Store<
string,
>
/**
- * Generic version of `StoreDefinition`
+ * Generic version of `StoreDefinition`.
*/
-export interface GenericStoreDefinition {
- (pinia?: Pinia | null | undefined): Store<
- string,
- StateTree,
- Record<string, Method>,
- Record<string, Method>
- >
- $id: string
-}
+export type GenericStoreDefinition = StoreDefinition<
+ string,
+ StateTree,
+ Record<string, Method>,
+ Record<string, Method>
+>
/**
* Properties that are added to every store by `pinia.use()`