From: Eduardo San Martin Morote Date: Mon, 2 Aug 2021 14:17:49 +0000 (+0200) Subject: feat: add support for Vue 2 X-Git-Tag: v2.0.0-rc.2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e1ea1c8563816dd99963aae778c03335d0577266;p=thirdparty%2Fvuejs%2Fpinia.git feat: add support for Vue 2 --- diff --git a/package.json b/package.json index b7260f24..9e0ee628 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "name": "Eduardo San Martin Morote", "email": "posva13@gmail.com" }, + "funding": "https://github.com/sponsors/posva", "scripts": { "docs": "vitepress dev docs", "docs:build": "vitepress build docs", @@ -96,6 +97,7 @@ "vite": "^2.4.1", "vitepress": "^0.15.6", "vue": "^3.2.0-beta.1", + "vue2": "npm:vue@2", "vue-promised": "^2.1.0", "vue-router": "^4.0.10", "yorkie": "^2.0.0" diff --git a/src/index.ts b/src/index.ts index 17edf463..b15060c9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -61,3 +61,5 @@ export { createTestingPinia } from './testing' export type { TestingOptions, TestingPinia } from './testing' export { acceptHMRUpdate } from './hmr' + +export { PiniaPlugin } from './vue2-plugin' diff --git a/src/mapHelpers.ts b/src/mapHelpers.ts index db847794..de55bfe7 100644 --- a/src/mapHelpers.ts +++ b/src/mapHelpers.ts @@ -1,5 +1,5 @@ -import { ComponentPublicInstance } from 'vue-demi' -import { +import type { ComponentPublicInstance } from 'vue-demi' +import type { GettersTree, _Method, StateTree, @@ -109,7 +109,7 @@ export function mapStores( } return stores.reduce((reduced, useStore) => { - // @ts-ignore: $id is added by defineStore + // @ts-expect-error: $id is added by defineStore reduced[useStore.$id + mapStoreSuffix] = function ( this: ComponentPublicInstance ) { diff --git a/src/store.ts b/src/store.ts index 1b009449..4b4da49c 100644 --- a/src/store.ts +++ b/src/store.ts @@ -17,6 +17,8 @@ import { toRefs, Ref, ref, + set, + isVue2, } from 'vue-demi' import { StateTree, @@ -102,7 +104,11 @@ function createOptionsStore< function setup() { if (!initialState && (!__DEV__ || !hot)) { - pinia.state.value[id] = state ? state() : {} + if (isVue2) { + set(pinia.state.value, id, state ? state() : {}) + } else { + pinia.state.value[id] = state ? state() : {} + } } // avoid creating a state in pinia.state.value @@ -170,7 +176,7 @@ function createSetupStore< // watcher options for $subscribe const $subscribeOptions: WatchOptions = { deep: true, flush: 'sync' } /* istanbul ignore else */ - if (__DEV__) { + if (__DEV__ && !isVue2) { $subscribeOptions.onTrigger = (event) => { if (isListening) { debuggerEvents = event diff --git a/src/vue2-plugin.ts b/src/vue2-plugin.ts new file mode 100644 index 00000000..1fed3917 --- /dev/null +++ b/src/vue2-plugin.ts @@ -0,0 +1,58 @@ +import type { Plugin } from 'vue-demi' +import { piniaSymbol } from './rootStore' + +/** + * Vue 2 Plugin that must be installed for pinia to work. Note **you don't need + * this plugin if you are using Nuxt.js**. Use the `buildModule` instead: + * https://pinia.esm.dev/ssr/nuxt.html. + * + * @example + * ```js + * import Vue from 'vue' + * import { PiniaPlugin, createPinia } from 'pinia' + * + * Vue.use(PiniaPlugin) + * const pinia = createPinia() + * + * new Vue({ + * el: '#app', + * // ... + * pinia, + * }) + * ``` + * + * @param _Vue + */ +export const PiniaPlugin: Plugin = function (_Vue) { + // 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#L30 + /* istanbul ignore else */ + 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 + // avoid adding it to nuxt twice + /* istanbul ignore else */ + if (!this.$pinia) { + this.$pinia = options.pinia + } + } else if (!this.$pinia && options.parent && options.parent.$pinia) { + this.$pinia = options.parent.$pinia + } + }, + destroyed() { + delete this._pStores + }, + }) +}