]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
feat: add PiniaPlugin
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 3 Mar 2021 16:29:51 +0000 (17:29 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 8 Mar 2021 14:50:05 +0000 (15:50 +0100)
__tests__/lifespan.spec.ts
__tests__/ssr/app/main.ts
src/index.ts
src/rootStore.ts
src/store.ts

index 6c5019068960aff339fd51714d22b1d31ecb28a7..3eb55eb1b42a916533e889c2b5d5832655b0db39 100644 (file)
@@ -1,4 +1,4 @@
-import { createPinia, defineStore, setActivePinia } from '../src'
+import { createPinia, defineStore, PiniaPlugin } from '../src'
 import { createLocalVue, mount } from '@vue/test-utils'
 import VueCompositionAPI, {
   watch,
@@ -32,7 +32,7 @@ describe('Store Lifespan', () => {
   const localVue = createLocalVue()
   localVue.use(VueCompositionAPI)
   const pinia = createPinia()
-  localVue.use(pinia)
+  localVue.use(PiniaPlugin)
 
   // FIXME: https://github.com/vuejs/vue-test-utils/issues/1799
 
index 7a004c8cb728897113c568063b91992e3832d430..ce98fcdb807aa9703a39c354dfb4acb9f91a4978 100644 (file)
@@ -1,4 +1,4 @@
-import { createPinia } from '../../../src'
+import { createPinia, PiniaPlugin } from '../../../src'
 import Vue from 'vue'
 // import VueCompositionApi from '@vue/composition-api'
 import App from './App'
@@ -9,7 +9,7 @@ import App from './App'
 export function createApp() {
   // create the app instance, injecting both the router and the store
   const pinia = createPinia()
-  Vue.use(pinia)
+  Vue.use(PiniaPlugin)
   const app = new Vue({
     // @ts-ignore
     pinia,
index 8fc6e85febbb8076e586c29082328ea20524ce93..67be7fff3bb5582a879edb2b4f7015bf908a8f5c 100644 (file)
@@ -2,6 +2,7 @@ export {
   setActivePinia,
   createPinia,
   Pinia,
+  PiniaPlugin,
   PiniaStorePlugin,
   PiniaCustomProperties,
 } from './rootStore'
index fa9d4870471104d991d82927b8003d425172e592..bf1cbaa4d86c096a2ddca777958d1e8f3298f67e 100644 (file)
@@ -1,7 +1,6 @@
 import { InjectionKey, ref, Ref } from '@vue/composition-api'
 import { StateTree, StoreWithState, StateDescriptor } from './types'
 import Vue, { PluginFunction, VueConstructor } from 'vue'
-import { IS_CLIENT } from './env'
 
 /**
  * The api needs more work we must be able to use the store easily in any
@@ -35,8 +34,6 @@ export interface PiniaStorePlugin {
  * Every application must own its own pinia to be able to create stores
  */
 export interface Pinia {
-  install: PluginFunction<void>
-
   /**
    * root state
    */
@@ -74,6 +71,36 @@ declare module 'vue/types/options' {
   }
 }
 
+export const PiniaPlugin: PluginFunction<void> = function (_Vue) {
+  // Equivalent of
+  // app.config.globalProperties.$pinia = pinia
+  Vue.mixin({
+    beforeCreate() {
+      const options = this.$options
+      if (options.pinia) {
+        options.pinia.Vue = _Vue
+        // this allows calling useStore() outside of a component setup after
+        // installing pinia's plugin
+        setActivePinia(options.pinia)
+        // HACK: taken from provide(): https://github.com/vuejs/composition-api/blob/master/src/apis/inject.ts#L25
+        if (!(this as any)._provided) {
+          const provideCache = {}
+          Object.defineProperty(this, '_provided', {
+            get: () => provideCache,
+            set: (v) => Object.assign(provideCache, v),
+          })
+        }
+        ;(this as any)._provided[piniaSymbol as any] = options.pinia
+
+        // propagate the pinia instance in an SSR friendly way
+        this.$pinia = options.pinia
+      } else if (options.parent && options.parent.$pinia) {
+        this.$pinia = options.parent.$pinia
+      }
+    },
+  })
+}
+
 /**
  * Creates a Pinia instance to be used by the application
  */
@@ -83,49 +110,13 @@ export function createPinia(): Pinia {
   const state = ref({})
 
   const _p: Pinia['_p'] = []
-  // plugins added before calling app.use(pinia)
-  const toBeInstalled: PiniaStorePlugin[] = []
 
   const pinia: Pinia = {
     // this one is set in install
     Vue: {} as any,
-    install(Vue) {
-      // localApp = app
-      this.Vue = Vue
-      Vue.prototype.$pinia = pinia
-
-      // Equivalent of
-      // app.config.globalProperties.$pinia = pinia
-      Vue.mixin({
-        beforeCreate() {
-          const options = this.$options
-          if (options.pinia) {
-            // HACK: taken from provide(): https://github.com/vuejs/composition-api/blob/master/src/apis/inject.ts#L25
-            if (!(this as any)._provided) {
-              const provideCache = {}
-              Object.defineProperty(this, '_provided', {
-                get: () => provideCache,
-                set: (v) => Object.assign(provideCache, v),
-              })
-            }
-            ;(this as any)._provided[piniaSymbol as any] = options.pinia
-          }
-        },
-      })
-
-      // this allows calling useStore() outside of a component setup after
-      // installing pinia's plugin
-      setActivePinia(pinia)
-
-      toBeInstalled.forEach((plugin) => _p.push(plugin.bind(null, pinia)))
-    },
 
     use(plugin) {
-      if (!pinia.Vue) {
-        toBeInstalled.push(plugin)
-      } else {
-        _p.push(plugin.bind(null, pinia))
-      }
+      _p.push(plugin.bind(null, pinia))
     },
 
     _p,
@@ -158,8 +149,9 @@ export const getActivePinia = () => {
   if (__DEV__ && !activePinia) {
     console.warn(
       `[🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia and inject it?\n\n` +
+        `import { PiniaPlugin, createPinia } from 'pinia'\n\n` +
+        `Vue.use(PiniaPlugin)\n` +
         `const pinia = createPinia()\n` +
-        `Vue.use(pinia)\n` +
         `new Vue({ el: '#app', pinia })\n\n` +
         `This will fail in production.`
     )
index e620fbefe2188de5f1cf63aabfdb4d3d16544b7c..403486a1c8cf9b0901830c53fe0cf03f5aea8eec 100644 (file)
@@ -28,7 +28,6 @@ import {
   PiniaCustomProperties,
   piniaSymbol,
 } from './rootStore'
-import Vue from 'vue'
 
 const isClient = typeof window != 'undefined'