From: Eduardo San Martin Morote Date: Wed, 3 Mar 2021 16:29:51 +0000 (+0100) Subject: feat: add PiniaPlugin X-Git-Tag: v0.2.0~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b3db04a807ffdc50e53b4ee7d5a2f2a818da881a;p=thirdparty%2Fvuejs%2Fpinia.git feat: add PiniaPlugin --- diff --git a/__tests__/lifespan.spec.ts b/__tests__/lifespan.spec.ts index 6c501906..3eb55eb1 100644 --- a/__tests__/lifespan.spec.ts +++ b/__tests__/lifespan.spec.ts @@ -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 diff --git a/__tests__/ssr/app/main.ts b/__tests__/ssr/app/main.ts index 7a004c8c..ce98fcdb 100644 --- a/__tests__/ssr/app/main.ts +++ b/__tests__/ssr/app/main.ts @@ -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, diff --git a/src/index.ts b/src/index.ts index 8fc6e85f..67be7fff 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ export { setActivePinia, createPinia, Pinia, + PiniaPlugin, PiniaStorePlugin, PiniaCustomProperties, } from './rootStore' diff --git a/src/rootStore.ts b/src/rootStore.ts index fa9d4870..bf1cbaa4 100644 --- a/src/rootStore.ts +++ b/src/rootStore.ts @@ -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 - /** * root state */ @@ -74,6 +71,36 @@ declare module 'vue/types/options' { } } +export const PiniaPlugin: PluginFunction = 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.` ) diff --git a/src/store.ts b/src/store.ts index e620fbef..403486a1 100644 --- a/src/store.ts +++ b/src/store.ts @@ -28,7 +28,6 @@ import { PiniaCustomProperties, piniaSymbol, } from './rootStore' -import Vue from 'vue' const isClient = typeof window != 'undefined'