From 1eb23f41d9e2160b528be998357136291d1a35c9 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 9 Feb 2021 18:12:03 +0100 Subject: [PATCH] refactor: preparing for migration --- README.md | 60 +++++++--------------------------- __tests__/actions.spec.ts | 4 +-- __tests__/getters.spec.ts | 4 +-- __tests__/pinia/stores/cart.ts | 4 +-- __tests__/pinia/stores/user.ts | 4 +-- __tests__/rootState.spec.ts | 6 ++-- __tests__/ssr/app/store.ts | 4 +-- __tests__/tds/store.test-d.ts | 4 +-- nuxt/plugin.js | 2 +- rollup.config.js | 16 ++++++--- src/deprecated.ts | 12 +++++++ src/env.ts | 1 + src/global.d.ts | 5 +++ src/index.ts | 2 ++ src/store.ts | 6 ++-- 15 files changed, 63 insertions(+), 71 deletions(-) create mode 100644 src/deprecated.ts create mode 100644 src/env.ts create mode 100644 src/global.d.ts diff --git a/README.md b/README.md index 0243b0cf..9fdf7c73 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ ## 👉 [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: @@ -89,9 +89,9 @@ Note: **The Vue Composition API plugin must be installed for Pinia to work** 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', @@ -120,7 +120,7 @@ export const useMainStore = createStore({ }) ``` -`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' @@ -351,12 +351,12 @@ setStateProvider(() => window.__PINIA_STATE__) ### 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: { @@ -391,11 +391,11 @@ If you need to compute a value based on the `state` and/or `getters` of multiple 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() { @@ -413,11 +413,11 @@ export const useSharedStore = createStore({ 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: { @@ -436,42 +436,6 @@ export const useSharedStore = createStore({ }) ``` -#### 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 @@ -486,7 +450,7 @@ interface MainState { name: string } -export const useMainStore = createStore({ +export const useMainStore = defineStore({ id: 'main', state: (): MainState => ({ counter: 0, diff --git a/__tests__/actions.spec.ts b/__tests__/actions.spec.ts index fb7aee81..76b56cb9 100644 --- a/__tests__/actions.spec.ts +++ b/__tests__/actions.spec.ts @@ -41,12 +41,12 @@ describe('Actions', () => { })() } - const useB = createStore({ + const useB = defineStore({ id: 'B', state: () => ({ b: 'b' }), }) - const useA = createStore({ + const useA = defineStore({ id: 'A', state: () => ({ a: 'a' }), actions: { diff --git a/__tests__/getters.spec.ts b/__tests__/getters.spec.ts index 3fce3aa4..3617c7fa 100644 --- a/__tests__/getters.spec.ts +++ b/__tests__/getters.spec.ts @@ -40,12 +40,12 @@ describe('Getters', () => { })() } - const useB = createStore({ + const useB = defineStore({ id: 'B', state: () => ({ b: 'b' }), }) - const useA = createStore({ + const useA = defineStore({ id: 'A', state: () => ({ a: 'a' }), getters: { diff --git a/__tests__/pinia/stores/cart.ts b/__tests__/pinia/stores/cart.ts index 98942645..f2b3480b 100644 --- a/__tests__/pinia/stores/cart.ts +++ b/__tests__/pinia/stores/cart.ts @@ -1,8 +1,8 @@ -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[], diff --git a/__tests__/pinia/stores/user.ts b/__tests__/pinia/stores/user.ts index 2dc94425..33f15fdf 100644 --- a/__tests__/pinia/stores/user.ts +++ b/__tests__/pinia/stores/user.ts @@ -1,11 +1,11 @@ -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', diff --git a/__tests__/rootState.spec.ts b/__tests__/rootState.spec.ts index d3ee12f7..5c9519ae 100644 --- a/__tests__/rootState.spec.ts +++ b/__tests__/rootState.spec.ts @@ -1,12 +1,12 @@ -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' }), }) diff --git a/__tests__/ssr/app/store.ts b/__tests__/ssr/app/store.ts index 4a40174c..708e63ac 100644 --- a/__tests__/ssr/app/store.ts +++ b/__tests__/ssr/app/store.ts @@ -1,6 +1,6 @@ -import { createStore } from '../../../src' +import { defineStore } from '../../../src' -export const useStore = createStore({ +export const useStore = defineStore({ id: 'main', state: () => ({ counter: 0, diff --git a/__tests__/tds/store.test-d.ts b/__tests__/tds/store.test-d.ts index a6d03231..ebee55ba 100644 --- a/__tests__/tds/store.test-d.ts +++ b/__tests__/tds/store.test-d.ts @@ -1,7 +1,7 @@ -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: { diff --git a/nuxt/plugin.js b/nuxt/plugin.js index 58900058..c00ea7a9 100644 --- a/nuxt/plugin.js +++ b/nuxt/plugin.js @@ -8,7 +8,7 @@ if (process.server) { } /** @type {import('@nuxt/types').Plugin} */ -const myPlugin = context => { +const myPlugin = (context) => { // console.log('🍍 Pinia Nuxt plugin installed') if (process.server) { diff --git a/rollup.config.js b/rollup.config.js index a802a89c..ee8bb1f0 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -2,7 +2,6 @@ import replace from '@rollup/plugin-replace' 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' @@ -33,16 +32,23 @@ function createEntry({ // 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: { diff --git a/src/deprecated.ts b/src/deprecated.ts new file mode 100644 index 00000000..e79cb525 --- /dev/null +++ b/src/deprecated.ts @@ -0,0 +1,12 @@ +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 diff --git a/src/env.ts b/src/env.ts new file mode 100644 index 00000000..53538e85 --- /dev/null +++ b/src/env.ts @@ -0,0 +1 @@ +export const IS_CLIENT = typeof window !== 'undefined' diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 00000000..516fe4da --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,5 @@ +// Global compile-time constants +declare let __DEV__: boolean +declare let __TEST__: boolean +declare let __BROWSER__: boolean +declare let __CI__: boolean diff --git a/src/index.ts b/src/index.ts index f1c3086c..56b883ff 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,3 +8,5 @@ export { StoreWithState, } from './types' export { PiniaSsr } from './ssrPlugin' + +export { createStore } from './deprecated' diff --git a/src/store.ts b/src/store.ts index 876c7f7a..78708e45 100644 --- a/src/store.ts +++ b/src/store.ts @@ -174,10 +174,12 @@ export function buildStore< } /** - * 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 */, -- 2.47.3