Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

pinia

Package Overview
Dependencies
Maintainers
1
Versions
119
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pinia - npm Package Compare versions

Comparing version 2.0.0-alpha.7 to 2.0.0-alpha.8

11

CHANGELOG.md

@@ -0,1 +1,12 @@

# [2.0.0-alpha.8](https://github.com/posva/pinia/compare/v2.0.0-alpha.7...v2.0.0-alpha.8) (2021-03-29)
### Bug Fixes
- use assign instead of spread ([b2bb5ba](https://github.com/posva/pinia/commit/b2bb5ba4faf52c41479a7d77490b85016b853229))
- **cjs:** ensure dev checks on cjs build ([a255735](https://github.com/posva/pinia/commit/a255735211b796120d5f76470ea18759f1eb5d97))
### Features
- **devtools:** logo and titles ([0963fd0](https://github.com/posva/pinia/commit/0963fd0b647b0e5414782f78167c770cbab24a83))
# [2.0.0-alpha.7](https://github.com/posva/pinia/compare/v2.0.0-alpha.6...v2.0.0-alpha.7) (2021-01-21)

@@ -2,0 +13,0 @@

63

dist/pinia.cjs.js
/*!
* pinia v2.0.0-alpha.7
* pinia v2.0.0-alpha.8
* (c) 2021 Eduardo San Martin Morote

@@ -30,3 +30,3 @@ * @license MIT

const getActivePinia = () => {
if ( !activePinia) {
if ((process.env.NODE_ENV !== 'production') && !activePinia) {
vue.warn(`[🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia?\n\n` +

@@ -40,9 +40,10 @@ `const pinia = createPinia()\n` +

/**
* The api needs more work we must be able to use the store easily in any
* function by calling `useStore` to get the store Instance and we also need to
* be able to reset the store instance between applications on the server
* Map of stores based on a Pinia instance. Allows setting and retrieving stores
* for the current running application (with its pinia).
*/
const storesMap = new WeakMap();
const piniaSymbol = ( Symbol('pinia')
);
const piniaSymbol = ((process.env.NODE_ENV !== 'production')
? Symbol('pinia')
: /* istanbul ignore next */
Symbol());
/**

@@ -68,2 +69,6 @@ * Creates a Pinia instance to be used by the application

use(plugin) {
/* istanbul ignore next */
if ((process.env.NODE_ENV !== 'production')) {
console.warn(`[🍍]: The plugin API has plans to change to bring better extensibility. "pinia.use()" signature will change in the next release. It is recommended to avoid using this API.`);
}
if (!localApp) {

@@ -106,2 +111,3 @@ toBeInstalled.push(plugin);

}
const { assign } = Object;
/**

@@ -134,4 +140,4 @@ * Create an object of computed properties referring to

function initStore($id, buildState = () => ({}), initialState) {
const _p = getActivePinia();
_p.state.value[$id] = initialState || buildState();
const pinia = getActivePinia();
pinia.state.value[$id] = initialState || buildState();
// const state: Ref<S> = toRef(_p.state.value, $id)

@@ -142,7 +148,7 @@ let isListening = true;

isListening = false;
innerPatch(_p.state.value[$id], partialState);
innerPatch(pinia.state.value[$id], partialState);
isListening = true;
// because we paused the watcher, we need to manually call the subscriptions
subscriptions.forEach((callback) => {
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, _p.state.value[$id]);
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, pinia.state.value[$id]);
});

@@ -154,3 +160,3 @@ }

// e.g. inside the setup of a component
const stopWatcher = vue.watch(() => _p.state.value[$id], (state) => {
const stopWatcher = vue.watch(() => pinia.state.value[$id], (state) => {
if (isListening) {

@@ -175,7 +181,7 @@ subscriptions.forEach((callback) => {

subscriptions = [];
_p.state.value[$id] = buildState();
pinia.state.value[$id] = buildState();
}
const storeWithState = {
$id,
_p,
_p: pinia,
// $state is added underneath

@@ -189,6 +195,6 @@ $patch,

{
get: () => _p.state.value[$id],
get: () => pinia.state.value[$id],
set: (newState) => {
isListening = false;
_p.state.value[$id] = newState;
pinia.state.value[$id] = newState;
isListening = true;

@@ -212,7 +218,7 @@ },

function buildStoreToUse(partialStore, descriptor, $id, getters = {}, actions = {}) {
const _p = getActivePinia();
const pinia = getActivePinia();
const computedGetters = {};
for (const getterName in getters) {
computedGetters[getterName] = vue.computed(() => {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line @typescript-eslint/no-use-before-define

@@ -225,3 +231,3 @@ return getters[getterName].call(store, store);

wrappedActions[actionName] = function () {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line

@@ -231,14 +237,6 @@ return actions[actionName].apply(store, arguments);

}
const extensions = _p._p.reduce((extended, extender) => ({
...extended,
...extender(),
}), {});
const store = vue.reactive({
...extensions,
...partialStore,
// using this means no new properties can be added as state
...computedFromState(_p.state, $id),
...computedGetters,
...wrappedActions,
});
const extensions = pinia._p.reduce((extended, extender) => assign({}, extended, extender()), {});
const store = vue.reactive(assign({}, extensions, partialStore,
// using this means no new properties can be added as state
computedFromState(pinia.state, $id), computedGetters, wrappedActions));
// use this instead of a computed with setter to be able to create it anywhere

@@ -275,3 +273,4 @@ // without linking the computed lifespan to wherever the store is first

false &&
true /*|| __FEATURE_PROD_DEVTOOLS__*/) {
(process.env.NODE_ENV !== 'production') /*|| __FEATURE_PROD_DEVTOOLS__*/) {
/* istanbul ignore else */
if (!isDevWarned && !false) {

@@ -278,0 +277,0 @@ isDevWarned = true;

/*!
* pinia v2.0.0-alpha.7
* pinia v2.0.0-alpha.8
* (c) 2021 Eduardo San Martin Morote

@@ -33,8 +33,8 @@ * @license MIT

/**
* The api needs more work we must be able to use the store easily in any
* function by calling `useStore` to get the store Instance and we also need to
* be able to reset the store instance between applications on the server
* Map of stores based on a Pinia instance. Allows setting and retrieving stores
* for the current running application (with its pinia).
*/
const storesMap = new WeakMap();
const piniaSymbol = ( Symbol());
const piniaSymbol = (/* istanbul ignore next */
Symbol());
/**

@@ -97,2 +97,3 @@ * Creates a Pinia instance to be used by the application

}
const { assign } = Object;
/**

@@ -125,4 +126,4 @@ * Create an object of computed properties referring to

function initStore($id, buildState = () => ({}), initialState) {
const _p = getActivePinia();
_p.state.value[$id] = initialState || buildState();
const pinia = getActivePinia();
pinia.state.value[$id] = initialState || buildState();
// const state: Ref<S> = toRef(_p.state.value, $id)

@@ -133,7 +134,7 @@ let isListening = true;

isListening = false;
innerPatch(_p.state.value[$id], partialState);
innerPatch(pinia.state.value[$id], partialState);
isListening = true;
// because we paused the watcher, we need to manually call the subscriptions
subscriptions.forEach((callback) => {
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, _p.state.value[$id]);
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, pinia.state.value[$id]);
});

@@ -145,3 +146,3 @@ }

// e.g. inside the setup of a component
const stopWatcher = vue.watch(() => _p.state.value[$id], (state) => {
const stopWatcher = vue.watch(() => pinia.state.value[$id], (state) => {
if (isListening) {

@@ -166,7 +167,7 @@ subscriptions.forEach((callback) => {

subscriptions = [];
_p.state.value[$id] = buildState();
pinia.state.value[$id] = buildState();
}
const storeWithState = {
$id,
_p,
_p: pinia,
// $state is added underneath

@@ -180,6 +181,6 @@ $patch,

{
get: () => _p.state.value[$id],
get: () => pinia.state.value[$id],
set: (newState) => {
isListening = false;
_p.state.value[$id] = newState;
pinia.state.value[$id] = newState;
isListening = true;

@@ -203,7 +204,7 @@ },

function buildStoreToUse(partialStore, descriptor, $id, getters = {}, actions = {}) {
const _p = getActivePinia();
const pinia = getActivePinia();
const computedGetters = {};
for (const getterName in getters) {
computedGetters[getterName] = vue.computed(() => {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line @typescript-eslint/no-use-before-define

@@ -216,3 +217,3 @@ return getters[getterName].call(store, store);

wrappedActions[actionName] = function () {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line

@@ -222,14 +223,6 @@ return actions[actionName].apply(store, arguments);

}
const extensions = _p._p.reduce((extended, extender) => ({
...extended,
...extender(),
}), {});
const store = vue.reactive({
...extensions,
...partialStore,
// using this means no new properties can be added as state
...computedFromState(_p.state, $id),
...computedGetters,
...wrappedActions,
});
const extensions = pinia._p.reduce((extended, extender) => assign({}, extended, extender()), {});
const store = vue.reactive(assign({}, extensions, partialStore,
// using this means no new properties can be added as state
computedFromState(pinia.state, $id), computedGetters, wrappedActions));
// use this instead of a computed with setter to be able to create it anywhere

@@ -267,2 +260,3 @@ // without linking the computed lifespan to wherever the store is first

false /*|| __FEATURE_PROD_DEVTOOLS__*/) {
/* istanbul ignore else */
if (!isDevWarned && !false) {

@@ -269,0 +263,0 @@ isDevWarned = true;

/*!
* pinia v2.0.0-alpha.7
* pinia v2.0.0-alpha.8
* (c) 2021 Eduardo San Martin Morote

@@ -26,3 +26,3 @@ * @license MIT

const getActivePinia = () => {
if ( !activePinia) {
if (!activePinia) {
warn(`[🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia?\n\n` +

@@ -36,5 +36,4 @@ `const pinia = createPinia()\n` +

/**
* The api needs more work we must be able to use the store easily in any
* function by calling `useStore` to get the store Instance and we also need to
* be able to reset the store instance between applications on the server
* Map of stores based on a Pinia instance. Allows setting and retrieving stores
* for the current running application (with its pinia).
*/

@@ -48,3 +47,3 @@ const storesMap = new WeakMap();

const getClientApp = () => clientApp;
const piniaSymbol = ( Symbol('pinia')
const piniaSymbol = (Symbol('pinia')
);

@@ -70,3 +69,3 @@ /**

// only set the app on client for devtools
if ( IS_CLIENT) {
if (IS_CLIENT) {
setClientApp(app);

@@ -80,2 +79,6 @@ // this allows calling useStore() outside of a component setup after

use(plugin) {
/* istanbul ignore next */
{
console.warn(`[🍍]: The plugin API has plans to change to bring better extensibility. "pinia.use()" signature will change in the next release. It is recommended to avoid using this API.`);
}
if (!localApp) {

@@ -93,10 +96,2 @@ toBeInstalled.push(plugin);

}
/**
* Registered stores
*/
const stores = /*#__PURE__*/ new Set();
function registerStore(store) {
stores.add(store);
}
const getRegisteredStores = () => stores;

@@ -148,2 +143,6 @@ function isPlainObject(

}
/**
* Registered stores used for devtools.
*/
const registeredStores = /*#__PURE__*/ new Set();
function toastMessage(message, type) {

@@ -165,19 +164,15 @@ const piniaMessage = '🍍 ' + message;

let isAlreadyInstalled;
const componentStateTypes = [];
function addDevtools(app, store) {
registerStore(store);
registeredStores.add(store);
componentStateTypes.push('🍍 ' + store.$id);
setupDevtoolsPlugin({
id: 'pinia',
id: 'dev.esm.pinia',
label: 'Pinia 🍍',
logo: 'https://pinia.esm.dev/logo.svg',
packageName: 'pinia',
homepage: 'https://pinia.esm.dev',
componentStateTypes,
app,
}, (api) => {
api.on.inspectComponent((payload, ctx) => {
if (payload.instanceData) {
payload.instanceData.state.push({
type: '🍍 ' + store.$id,
key: 'state',
editable: false,
value: store.$state,
});
}
});
// watch(router.currentRoute, () => {

@@ -190,2 +185,12 @@ // // @ts-ignore

if (!isAlreadyInstalled) {
api.on.inspectComponent((payload, ctx) => {
if (payload.instanceData) {
payload.instanceData.state.push({
type: '🍍 ' + store.$id,
key: 'state',
editable: false,
value: store.$state,
});
}
});
api.addTimelineLayer({

@@ -205,3 +210,2 @@ id: mutationsLayerId,

else {
// @ts-ignore
api.notifyComponentUpdate();

@@ -215,3 +219,3 @@ api.sendInspectorTree(piniaInspectorId);

store: formatDisplay(mutation.storeName),
type: formatDisplay(mutation.type),
// type: formatDisplay(mutation.type),
};

@@ -221,3 +225,2 @@ if (mutation.payload) {

}
// @ts-ignore
api.notifyComponentUpdate();

@@ -229,5 +232,4 @@ api.sendInspectorState(piniaInspectorId);

time: Date.now(),
title: mutation.type,
data,
// TODO: remove when fixed
meta: {},
},

@@ -238,3 +240,3 @@ });

if (payload.app === app && payload.inspectorId === piniaInspectorId) {
const stores = Array.from(getRegisteredStores());
const stores = Array.from(registeredStores);
payload.rootNodes = (payload.filter

@@ -247,3 +249,3 @@ ? stores.filter((store) => store.$id.toLowerCase().includes(payload.filter.toLowerCase()))

if (payload.app === app && payload.inspectorId === piniaInspectorId) {
const stores = Array.from(getRegisteredStores());
const stores = Array.from(registeredStores);
const store = stores.find((store) => store.$id === payload.nodeId);

@@ -296,2 +298,3 @@ if (store) {

}
const { assign } = Object;
/**

@@ -324,4 +327,4 @@ * Create an object of computed properties referring to

function initStore($id, buildState = () => ({}), initialState) {
const _p = getActivePinia();
_p.state.value[$id] = initialState || buildState();
const pinia = getActivePinia();
pinia.state.value[$id] = initialState || buildState();
// const state: Ref<S> = toRef(_p.state.value, $id)

@@ -332,7 +335,7 @@ let isListening = true;

isListening = false;
innerPatch(_p.state.value[$id], partialState);
innerPatch(pinia.state.value[$id], partialState);
isListening = true;
// because we paused the watcher, we need to manually call the subscriptions
subscriptions.forEach((callback) => {
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, _p.state.value[$id]);
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, pinia.state.value[$id]);
});

@@ -344,3 +347,3 @@ }

// e.g. inside the setup of a component
const stopWatcher = watch(() => _p.state.value[$id], (state) => {
const stopWatcher = watch(() => pinia.state.value[$id], (state) => {
if (isListening) {

@@ -365,7 +368,7 @@ subscriptions.forEach((callback) => {

subscriptions = [];
_p.state.value[$id] = buildState();
pinia.state.value[$id] = buildState();
}
const storeWithState = {
$id,
_p,
_p: pinia,
// $state is added underneath

@@ -379,6 +382,6 @@ $patch,

{
get: () => _p.state.value[$id],
get: () => pinia.state.value[$id],
set: (newState) => {
isListening = false;
_p.state.value[$id] = newState;
pinia.state.value[$id] = newState;
isListening = true;

@@ -402,7 +405,7 @@ },

function buildStoreToUse(partialStore, descriptor, $id, getters = {}, actions = {}) {
const _p = getActivePinia();
const pinia = getActivePinia();
const computedGetters = {};
for (const getterName in getters) {
computedGetters[getterName] = computed(() => {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line @typescript-eslint/no-use-before-define

@@ -415,3 +418,3 @@ return getters[getterName].call(store, store);

wrappedActions[actionName] = function () {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line

@@ -421,14 +424,6 @@ return actions[actionName].apply(store, arguments);

}
const extensions = _p._p.reduce((extended, extender) => ({
...extended,
...extender(),
}), {});
const store = reactive({
...extensions,
...partialStore,
// using this means no new properties can be added as state
...computedFromState(_p.state, $id),
...computedGetters,
...wrappedActions,
});
const extensions = pinia._p.reduce((extended, extender) => assign({}, extended, extender()), {});
const store = reactive(assign({}, extensions, partialStore,
// using this means no new properties can be added as state
computedFromState(pinia.state, $id), computedGetters, wrappedActions));
// use this instead of a computed with setter to be able to create it anywhere

@@ -467,2 +462,3 @@ // without linking the computed lifespan to wherever the store is first

const app = getClientApp();
/* istanbul ignore else */
if (app) {

@@ -469,0 +465,0 @@ addDevtools(app, store);

/*!
* pinia v2.0.0-alpha.7
* pinia v2.0.0-alpha.8
* (c) 2021 Eduardo San Martin Morote

@@ -35,5 +35,4 @@ * @license MIT

/**
* The api needs more work we must be able to use the store easily in any
* function by calling `useStore` to get the store Instance and we also need to
* be able to reset the store instance between applications on the server
* Map of stores based on a Pinia instance. Allows setting and retrieving stores
* for the current running application (with its pinia).
*/

@@ -49,3 +48,4 @@ const storesMap = new WeakMap();

? Symbol('pinia')
: Symbol());
: /* istanbul ignore next */
Symbol());
/**

@@ -70,3 +70,3 @@ * Creates a Pinia instance to be used by the application

// only set the app on client for devtools
if ( IS_CLIENT) {
if (IS_CLIENT) {
setClientApp(app);

@@ -80,2 +80,6 @@ // this allows calling useStore() outside of a component setup after

use(plugin) {
/* istanbul ignore next */
if ((process.env.NODE_ENV !== 'production')) {
console.warn(`[🍍]: The plugin API has plans to change to bring better extensibility. "pinia.use()" signature will change in the next release. It is recommended to avoid using this API.`);
}
if (!localApp) {

@@ -93,10 +97,2 @@ toBeInstalled.push(plugin);

}
/**
* Registered stores
*/
const stores = /*#__PURE__*/ new Set();
function registerStore(store) {
stores.add(store);
}
const getRegisteredStores = () => stores;

@@ -148,2 +144,6 @@ function isPlainObject(

}
/**
* Registered stores used for devtools.
*/
const registeredStores = /*#__PURE__*/ new Set();
function toastMessage(message, type) {

@@ -165,19 +165,15 @@ const piniaMessage = '🍍 ' + message;

let isAlreadyInstalled;
const componentStateTypes = [];
function addDevtools(app, store) {
registerStore(store);
registeredStores.add(store);
componentStateTypes.push('🍍 ' + store.$id);
setupDevtoolsPlugin({
id: 'pinia',
id: 'dev.esm.pinia',
label: 'Pinia 🍍',
logo: 'https://pinia.esm.dev/logo.svg',
packageName: 'pinia',
homepage: 'https://pinia.esm.dev',
componentStateTypes,
app,
}, (api) => {
api.on.inspectComponent((payload, ctx) => {
if (payload.instanceData) {
payload.instanceData.state.push({
type: '🍍 ' + store.$id,
key: 'state',
editable: false,
value: store.$state,
});
}
});
// watch(router.currentRoute, () => {

@@ -190,2 +186,12 @@ // // @ts-ignore

if (!isAlreadyInstalled) {
api.on.inspectComponent((payload, ctx) => {
if (payload.instanceData) {
payload.instanceData.state.push({
type: '🍍 ' + store.$id,
key: 'state',
editable: false,
value: store.$state,
});
}
});
api.addTimelineLayer({

@@ -205,3 +211,2 @@ id: mutationsLayerId,

else {
// @ts-ignore
api.notifyComponentUpdate();

@@ -215,3 +220,3 @@ api.sendInspectorTree(piniaInspectorId);

store: formatDisplay(mutation.storeName),
type: formatDisplay(mutation.type),
// type: formatDisplay(mutation.type),
};

@@ -221,3 +226,2 @@ if (mutation.payload) {

}
// @ts-ignore
api.notifyComponentUpdate();

@@ -229,5 +233,4 @@ api.sendInspectorState(piniaInspectorId);

time: Date.now(),
title: mutation.type,
data,
// TODO: remove when fixed
meta: {},
},

@@ -238,3 +241,3 @@ });

if (payload.app === app && payload.inspectorId === piniaInspectorId) {
const stores = Array.from(getRegisteredStores());
const stores = Array.from(registeredStores);
payload.rootNodes = (payload.filter

@@ -247,3 +250,3 @@ ? stores.filter((store) => store.$id.toLowerCase().includes(payload.filter.toLowerCase()))

if (payload.app === app && payload.inspectorId === piniaInspectorId) {
const stores = Array.from(getRegisteredStores());
const stores = Array.from(registeredStores);
const store = stores.find((store) => store.$id === payload.nodeId);

@@ -296,2 +299,3 @@ if (store) {

}
const { assign } = Object;
/**

@@ -324,4 +328,4 @@ * Create an object of computed properties referring to

function initStore($id, buildState = () => ({}), initialState) {
const _p = getActivePinia();
_p.state.value[$id] = initialState || buildState();
const pinia = getActivePinia();
pinia.state.value[$id] = initialState || buildState();
// const state: Ref<S> = toRef(_p.state.value, $id)

@@ -332,7 +336,7 @@ let isListening = true;

isListening = false;
innerPatch(_p.state.value[$id], partialState);
innerPatch(pinia.state.value[$id], partialState);
isListening = true;
// because we paused the watcher, we need to manually call the subscriptions
subscriptions.forEach((callback) => {
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, _p.state.value[$id]);
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, pinia.state.value[$id]);
});

@@ -344,3 +348,3 @@ }

// e.g. inside the setup of a component
const stopWatcher = watch(() => _p.state.value[$id], (state) => {
const stopWatcher = watch(() => pinia.state.value[$id], (state) => {
if (isListening) {

@@ -365,7 +369,7 @@ subscriptions.forEach((callback) => {

subscriptions = [];
_p.state.value[$id] = buildState();
pinia.state.value[$id] = buildState();
}
const storeWithState = {
$id,
_p,
_p: pinia,
// $state is added underneath

@@ -379,6 +383,6 @@ $patch,

{
get: () => _p.state.value[$id],
get: () => pinia.state.value[$id],
set: (newState) => {
isListening = false;
_p.state.value[$id] = newState;
pinia.state.value[$id] = newState;
isListening = true;

@@ -402,7 +406,7 @@ },

function buildStoreToUse(partialStore, descriptor, $id, getters = {}, actions = {}) {
const _p = getActivePinia();
const pinia = getActivePinia();
const computedGetters = {};
for (const getterName in getters) {
computedGetters[getterName] = computed(() => {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line @typescript-eslint/no-use-before-define

@@ -415,3 +419,3 @@ return getters[getterName].call(store, store);

wrappedActions[actionName] = function () {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line

@@ -421,14 +425,6 @@ return actions[actionName].apply(store, arguments);

}
const extensions = _p._p.reduce((extended, extender) => ({
...extended,
...extender(),
}), {});
const store = reactive({
...extensions,
...partialStore,
// using this means no new properties can be added as state
...computedFromState(_p.state, $id),
...computedGetters,
...wrappedActions,
});
const extensions = pinia._p.reduce((extended, extender) => assign({}, extended, extender()), {});
const store = reactive(assign({}, extensions, partialStore,
// using this means no new properties can be added as state
computedFromState(pinia.state, $id), computedGetters, wrappedActions));
// use this instead of a computed with setter to be able to create it anywhere

@@ -467,2 +463,3 @@ // without linking the computed lifespan to wherever the store is first

const app = getClientApp();
/* istanbul ignore else */
if (app) {

@@ -469,0 +466,0 @@ addDevtools(app, store);

/*!
* pinia v2.0.0-alpha.7
* pinia v2.0.0-alpha.8
* (c) 2021 Eduardo San Martin Morote

@@ -27,3 +27,3 @@ * @license MIT

const getActivePinia = () => {
if ( !activePinia) {
if (!activePinia) {
vue.warn(`[🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia?\n\n` +

@@ -37,5 +37,4 @@ `const pinia = createPinia()\n` +

/**
* The api needs more work we must be able to use the store easily in any
* function by calling `useStore` to get the store Instance and we also need to
* be able to reset the store instance between applications on the server
* Map of stores based on a Pinia instance. Allows setting and retrieving stores
* for the current running application (with its pinia).
*/

@@ -49,3 +48,3 @@ const storesMap = new WeakMap();

const getClientApp = () => clientApp;
const piniaSymbol = ( Symbol('pinia')
const piniaSymbol = (Symbol('pinia')
);

@@ -71,3 +70,3 @@ /**

// only set the app on client for devtools
if ( IS_CLIENT) {
if (IS_CLIENT) {
setClientApp(app);

@@ -81,2 +80,6 @@ // this allows calling useStore() outside of a component setup after

use(plugin) {
/* istanbul ignore next */
{
console.warn(`[🍍]: The plugin API has plans to change to bring better extensibility. "pinia.use()" signature will change in the next release. It is recommended to avoid using this API.`);
}
if (!localApp) {

@@ -94,10 +97,2 @@ toBeInstalled.push(plugin);

}
/**
* Registered stores
*/
const stores = /*#__PURE__*/ new Set();
function registerStore(store) {
stores.add(store);
}
const getRegisteredStores = () => stores;

@@ -149,2 +144,6 @@ function isPlainObject(

}
/**
* Registered stores used for devtools.
*/
const registeredStores = /*#__PURE__*/ new Set();
function toastMessage(message, type) {

@@ -166,19 +165,15 @@ const piniaMessage = '🍍 ' + message;

let isAlreadyInstalled;
const componentStateTypes = [];
function addDevtools(app, store) {
registerStore(store);
registeredStores.add(store);
componentStateTypes.push('🍍 ' + store.$id);
setupDevtoolsPlugin({
id: 'pinia',
id: 'dev.esm.pinia',
label: 'Pinia 🍍',
logo: 'https://pinia.esm.dev/logo.svg',
packageName: 'pinia',
homepage: 'https://pinia.esm.dev',
componentStateTypes,
app,
}, (api) => {
api.on.inspectComponent((payload, ctx) => {
if (payload.instanceData) {
payload.instanceData.state.push({
type: '🍍 ' + store.$id,
key: 'state',
editable: false,
value: store.$state,
});
}
});
// watch(router.currentRoute, () => {

@@ -191,2 +186,12 @@ // // @ts-ignore

if (!isAlreadyInstalled) {
api.on.inspectComponent((payload, ctx) => {
if (payload.instanceData) {
payload.instanceData.state.push({
type: '🍍 ' + store.$id,
key: 'state',
editable: false,
value: store.$state,
});
}
});
api.addTimelineLayer({

@@ -206,3 +211,2 @@ id: mutationsLayerId,

else {
// @ts-ignore
api.notifyComponentUpdate();

@@ -216,3 +220,3 @@ api.sendInspectorTree(piniaInspectorId);

store: formatDisplay(mutation.storeName),
type: formatDisplay(mutation.type),
// type: formatDisplay(mutation.type),
};

@@ -222,3 +226,2 @@ if (mutation.payload) {

}
// @ts-ignore
api.notifyComponentUpdate();

@@ -230,5 +233,4 @@ api.sendInspectorState(piniaInspectorId);

time: Date.now(),
title: mutation.type,
data,
// TODO: remove when fixed
meta: {},
},

@@ -239,3 +241,3 @@ });

if (payload.app === app && payload.inspectorId === piniaInspectorId) {
const stores = Array.from(getRegisteredStores());
const stores = Array.from(registeredStores);
payload.rootNodes = (payload.filter

@@ -248,3 +250,3 @@ ? stores.filter((store) => store.$id.toLowerCase().includes(payload.filter.toLowerCase()))

if (payload.app === app && payload.inspectorId === piniaInspectorId) {
const stores = Array.from(getRegisteredStores());
const stores = Array.from(registeredStores);
const store = stores.find((store) => store.$id === payload.nodeId);

@@ -297,2 +299,3 @@ if (store) {

}
const { assign } = Object;
/**

@@ -325,4 +328,4 @@ * Create an object of computed properties referring to

function initStore($id, buildState = () => ({}), initialState) {
const _p = getActivePinia();
_p.state.value[$id] = initialState || buildState();
const pinia = getActivePinia();
pinia.state.value[$id] = initialState || buildState();
// const state: Ref<S> = toRef(_p.state.value, $id)

@@ -333,7 +336,7 @@ let isListening = true;

isListening = false;
innerPatch(_p.state.value[$id], partialState);
innerPatch(pinia.state.value[$id], partialState);
isListening = true;
// because we paused the watcher, we need to manually call the subscriptions
subscriptions.forEach((callback) => {
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, _p.state.value[$id]);
callback({ storeName: $id, type: '⤵️ patch', payload: partialState }, pinia.state.value[$id]);
});

@@ -345,3 +348,3 @@ }

// e.g. inside the setup of a component
const stopWatcher = vue.watch(() => _p.state.value[$id], (state) => {
const stopWatcher = vue.watch(() => pinia.state.value[$id], (state) => {
if (isListening) {

@@ -366,7 +369,7 @@ subscriptions.forEach((callback) => {

subscriptions = [];
_p.state.value[$id] = buildState();
pinia.state.value[$id] = buildState();
}
const storeWithState = {
$id,
_p,
_p: pinia,
// $state is added underneath

@@ -380,6 +383,6 @@ $patch,

{
get: () => _p.state.value[$id],
get: () => pinia.state.value[$id],
set: (newState) => {
isListening = false;
_p.state.value[$id] = newState;
pinia.state.value[$id] = newState;
isListening = true;

@@ -403,7 +406,7 @@ },

function buildStoreToUse(partialStore, descriptor, $id, getters = {}, actions = {}) {
const _p = getActivePinia();
const pinia = getActivePinia();
const computedGetters = {};
for (const getterName in getters) {
computedGetters[getterName] = vue.computed(() => {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line @typescript-eslint/no-use-before-define

@@ -416,3 +419,3 @@ return getters[getterName].call(store, store);

wrappedActions[actionName] = function () {
setActivePinia(_p);
setActivePinia(pinia);
// eslint-disable-next-line

@@ -422,14 +425,6 @@ return actions[actionName].apply(store, arguments);

}
const extensions = _p._p.reduce((extended, extender) => ({
...extended,
...extender(),
}), {});
const store = vue.reactive({
...extensions,
...partialStore,
// using this means no new properties can be added as state
...computedFromState(_p.state, $id),
...computedGetters,
...wrappedActions,
});
const extensions = pinia._p.reduce((extended, extender) => assign({}, extended, extender()), {});
const store = vue.reactive(assign({}, extensions, partialStore,
// using this means no new properties can be added as state
computedFromState(pinia.state, $id), computedGetters, wrappedActions));
// use this instead of a computed with setter to be able to create it anywhere

@@ -468,2 +463,3 @@ // without linking the computed lifespan to wherever the store is first

const app = getClientApp();
/* istanbul ignore else */
if (app) {

@@ -470,0 +466,0 @@ addDevtools(app, store);

/*!
* pinia v2.0.0-alpha.7
* pinia v2.0.0-alpha.8
* (c) 2021 Eduardo San Martin Morote
* @license MIT
*/
var Pinia=function(e,t){"use strict";const n="undefined"!=typeof window;let o;const c=e=>o=e,a=()=>o,r=new WeakMap;let s;const u=Symbol();function i(e){return e&&"object"==typeof e&&"[object Object]"===Object.prototype.toString.call(e)&&"function"!=typeof e.toJSON}function l(e,t){for(const n in t){const o=t[n],c=e[n];e[n]=i(c)&&i(o)?l(c,o):o}return e}function f(e,n){const o={},c=e.value[n];for(const a in c)o[a]=t.computed({get:()=>e.value[n][a],set:t=>e.value[n][a]=t});return o}function p(e,n=(()=>({})),o){const c=a();c.state.value[e]=o||n();let r=!0,s=[];return[{$id:e,_p:c,$patch:function(t){r=!1,l(c.state.value[e],t),r=!0,s.forEach(n=>{n({storeName:e,type:"⤵️ patch",payload:t},c.state.value[e])})},$subscribe:function(n){s.push(n);const o=t.watch(()=>c.state.value[e],t=>{r&&s.forEach(n=>{n({storeName:e,type:"🧩 in place",payload:{}},t)})},{deep:!0,flush:"sync"});return()=>{const e=s.indexOf(n);e>-1&&(s.splice(e,1),o())}},$reset:function(){s=[],c.state.value[e]=n()}},{get:()=>c.state.value[e],set:t=>{r=!1,c.state.value[e]=t,r=!0}}]}function d(e,n,o,r={},s={}){const u=a(),i={};for(const e in r)i[e]=t.computed(()=>(c(u),r[e].call(d,d)));const l={};for(const e in s)l[e]=function(){return c(u),s[e].apply(d,arguments)};const p=u._p.reduce((e,t)=>({...e,...t()}),{}),d=t.reactive({...p,...e,...f(u.state,o),...i,...l});return Object.defineProperty(d,"$state",n),d}function v(e){const{id:n,state:o,getters:s,actions:i}=e;return function(e){(e=e||t.getCurrentInstance()&&t.inject(u))&&c(e),e=a();let l=r.get(e);l||r.set(e,l=new Map);let f=l.get(n);if(!f){f=p(n,o,e.state.value[n]),l.set(n,f);const t=d(f[0],f[1],n,s,i);return t}return d(f[0],f[1],n,s,i)}}return e.createPinia=function(){const e=t.ref({});let o,a=[];const r=[],i={install(e){o=e,e.provide(u,i),e.config.globalProperties.$pinia=i,n&&((e=>{s=e})(e),c(i)),r.forEach(e=>a.push(e.bind(null,o)))},use(e){o?a.push(e.bind(null,o)):r.push(e)},_p:a,state:e};return i},e.createStore=e=>(console.warn('[🍍]: "createStore" has been deprecated and will be removed on the sable release, use "defineStore" instead.'),v(e)),e.defineStore=v,e.setActivePinia=c,Object.defineProperty(e,"__esModule",{value:!0}),e}({},Vue);
var Pinia=function(e,t){"use strict";const n="undefined"!=typeof window;let o;const c=e=>o=e,s=()=>o,a=new WeakMap;let r;const u=Symbol();function i(e){return e&&"object"==typeof e&&"[object Object]"===Object.prototype.toString.call(e)&&"function"!=typeof e.toJSON}function l(e,t){for(const n in t){const o=t[n],c=e[n];e[n]=i(c)&&i(o)?l(c,o):o}return e}const{assign:f}=Object;function p(e,n=(()=>({})),o){const c=s();c.state.value[e]=o||n();let a=!0,r=[];return[{$id:e,_p:c,$patch:function(t){a=!1,l(c.state.value[e],t),a=!0,r.forEach(n=>{n({storeName:e,type:"⤵️ patch",payload:t},c.state.value[e])})},$subscribe:function(n){r.push(n);const o=t.watch(()=>c.state.value[e],t=>{a&&r.forEach(n=>{n({storeName:e,type:"🧩 in place",payload:{}},t)})},{deep:!0,flush:"sync"});return()=>{const e=r.indexOf(n);e>-1&&(r.splice(e,1),o())}},$reset:function(){r=[],c.state.value[e]=n()}},{get:()=>c.state.value[e],set:t=>{a=!1,c.state.value[e]=t,a=!0}}]}function d(e,n,o,a={},r={}){const u=s(),i={};for(const e in a)i[e]=t.computed(()=>(c(u),a[e].call(d,d)));const l={};for(const e in r)l[e]=function(){return c(u),r[e].apply(d,arguments)};const p=u._p.reduce((e,t)=>f({},e,t()),{}),d=t.reactive(f({},p,e,function(e,n){const o={},c=e.value[n];for(const s in c)o[s]=t.computed({get:()=>e.value[n][s],set:t=>e.value[n][s]=t});return o}(u.state,o),i,l));return Object.defineProperty(d,"$state",n),d}function v(e){const{id:n,state:o,getters:r,actions:i}=e;return function(e){(e=e||t.getCurrentInstance()&&t.inject(u))&&c(e),e=s();let l=a.get(e);l||a.set(e,l=new Map);let f=l.get(n);if(!f){f=p(n,o,e.state.value[n]),l.set(n,f);const t=d(f[0],f[1],n,r,i);return t}return d(f[0],f[1],n,r,i)}}return e.createPinia=function(){const e=t.ref({});let o,s=[];const a=[],i={install(e){o=e,e.provide(u,i),e.config.globalProperties.$pinia=i,n&&((e=>{r=e})(e),c(i)),a.forEach(e=>s.push(e.bind(null,o)))},use(e){o?s.push(e.bind(null,o)):a.push(e)},_p:s,state:e};return i},e.createStore=e=>(console.warn('[🍍]: "createStore" has been deprecated and will be removed on the sable release, use "defineStore" instead.'),v(e)),e.defineStore=v,e.setActivePinia=c,Object.defineProperty(e,"__esModule",{value:!0}),e}({},Vue);
{
"name": "pinia",
"version": "2.0.0-alpha.7",
"description": "Some awesome description",
"version": "2.0.0-alpha.8",
"description": "Intuitive, type safe and flexible Store for Vue",
"main": "dist/pinia.cjs.js",

@@ -10,2 +10,10 @@ "module": "dist/pinia.esm-bundler.js",

"types": "dist/pinia.d.ts",
"exports": {
".": {
"require": "./dist/pinia.cjs.js",
"browser": "./dist/pinia.esm-browser.js",
"import": "./dist/pinia.esm-bundler.js"
},
"./package.json": "./package.json"
},
"sideEffects": false,

@@ -17,3 +25,5 @@ "author": {

"scripts": {
"build": "rollup -c rollup.config.js",
"docs": "vitepress dev docs",
"docs:build": "vitepress build docs",
"build": "rimraf dist && rollup -c rollup.config.js",
"build:dts": "api-extractor run --local --verbose",

@@ -42,3 +52,5 @@ "size": "rollup -c size-checks/rollup.config.js && node scripts/check-size.js",

"store",
"pina",
"pinia",
"piña",
"pigna",
"composition",

@@ -55,27 +67,29 @@ "api",

"devDependencies": {
"@microsoft/api-extractor": "7.12.1",
"@nuxt/types": "^2.14.6",
"@rollup/plugin-alias": "^3.1.1",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-replace": "^2.3.3",
"@types/jest": "^26.0.14",
"@types/node": "^14.11.2",
"@vue/devtools-api": "^6.0.0-beta.2",
"@vue/server-renderer": "^3.0.0",
"@vue/test-utils": "^2.0.0-beta.5",
"@microsoft/api-extractor": "7.13.2",
"@nuxt/types": "^2.15.3",
"@rollup/plugin-alias": "^3.1.2",
"@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-node-resolve": "^11.2.1",
"@rollup/plugin-replace": "^2.4.2",
"@types/jest": "^26.0.22",
"@types/node": "^14.14.37",
"@vue/devtools-api": "^6.0.0-beta.7",
"@vue/server-renderer": "^3.0.9",
"@vue/test-utils": "^2.0.0-rc.4",
"brotli": "^1.3.2",
"codecov": "^3.6.1",
"conventional-changelog-cli": "^2.1.0",
"jest": "^26.4.2",
"lint-staged": "^10.2.11",
"codecov": "^3.8.1",
"conventional-changelog-cli": "^2.1.1",
"jest": "^26.6.3",
"jest-mock-warn": "^1.1.0",
"lint-staged": "^10.5.4",
"pascalcase": "^1.0.0",
"prettier": "^2.1.2",
"rimraf": "^3.0.1",
"rollup": "^2.28.1",
"prettier": "^2.2.1",
"rimraf": "^3.0.2",
"rollup": "^2.44.0",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.29.0",
"ts-jest": "^26.4.0",
"typescript": "^4.0.3",
"vue": "^3.0.0",
"rollup-plugin-typescript2": "^0.30.0",
"ts-jest": "^26.5.4",
"typescript": "^4.2.3",
"vitepress": "^0.12.2",
"vue": "^3.0.7",
"yorkie": "^2.0.0"

@@ -82,0 +96,0 @@ },

@@ -1,27 +0,31 @@

# Pinia [![Build Status](https://badgen.net/circleci/github/posva/pinia/v2)](https://circleci.com/gh/posva/pinia) [![npm package](https://badgen.net/npm/v/pinia/next)](https://www.npmjs.com/package/pinia) [![coverage](https://badgen.net/codecov/c/github/posva/pinia/next)](https://codecov.io/github/posva/pinia) [![thanks](https://badgen.net/badge/thanks/♥/pink)](https://github.com/posva/thanks)
<p align="center">
<a href="https://pinia.esm.dev" target="_blank" rel="noopener noreferrer">
<img width="180" src="https://pinia.esm.dev/logo.svg" alt="Pinia logo">
</a>
</p>
<br/>
<p align="center">
<a href="https://npmjs.com/package/pinia"><img src="https://badgen.net/npm/v/pinia/next" alt="npm package"></a>
<a href="https://github.com/posva/pinia/actions/workflows/test.yml"><img src="https://github.com/posva/pinia/workflows/test/badge.svg?branch=v2" alt="build status"></a>
<a href="https://codecov.io/github/posva/pinia"><img src="https://badgen.net/codecov/c/github/posva/pinia/v2" alt="code coverage"></a>
</p>
<br/>
> Pronounced like the fruit in Spanish, _Piña_
>
> _Piña_ is also an invalid package name... that's why it has to be _pinia_ which sounds very similar
# Pinia
🍍 Automatically Typed, Modular and lightweight (but **Experimental**) Store for Vue 3.x based on the composition api with devtools support
> Intuitive, type safe and flexible Store for Vue
## 👉 [Demo on CodeSandbox](https://j4qzw.csb.app/)
- 💡 Intuitive
- 🔑 Type Safe
- ⚙️ Devtools support
- 🔌 Extensible
- 🏗 Modular by design
- 📦 Extremely light
⚠️⚠️⚠️ 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 both for Vue 2.x and Vue 3.x and you are currently on the branch that supports Vue 3.x. [Go here for the Vue 2.x compatible version](https://github.com/posva/pinia/tree/v1).
Pinia works both for Vue 2.x and Vue 3.x and you are currently on the branch that supports Vue 3.x. **If you are looking for the version compatible with Vue 2.x, check the [`v1` branch](https://github.com/posva/pinia/tree/v1)**.
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.
Pinia is is the most similar English pronunciation of the word _pineapple_ in Spanish: _piña_. A pineapple is in reality a group of individual flowers that join together to create a multiple fruit. Similar to stores, each one is born individually, but they are all connected at the end. It's also a delicious tropical fruit indigenous to South America.
These are the core principles that I try to achieve with this experiment:
## 👉 [Demo on CodeSandbox](https://j4qzw.csb.app/)
- Autocompletion: even if you write your code in JavaScript!
- Flat modular structure 🍍 No nesting, only stores, compose them as needed
- Light layer on top of Vue 💨 keep it very lightweight
- Only `state`, `getters` and `actions`
- No more verbose mutations, 👐 `patch` is _**the** mutation_
- Actions are like _methods_ ⚗️ Group your business logic there
- Import what you need, let webpack code split 📦 No need for dynamically registered modules
- SSR support ⚙️
- DevTools support 💻 Which is crucial to make this enjoyable
## Help me keep working on this project 💚

@@ -35,2 +39,10 @@

<h4 align="center">Gold Sponsors</h4>
<p align="center">
<a href="https://passionatepeople.io/" target="_blank" rel="noopener noreferrer">
<img src="https://img2.storyblok.com/0x200/filters::format(webp)/f/86387/x/4cf6a70a8c/logo-white-text.svg" height="72px" alt="Passionate People">
</a>
</p>
<h4 align="center">Silver Sponsors</h4>

@@ -40,8 +52,12 @@

<a href="https://www.vuemastery.com" target="_blank" rel="noopener noreferrer">
<img src="https://www.vuemastery.com/images/vuemastery.svg" height="48px" alt="Vue Mastery">
<img src="https://www.vuemastery.com/images/vuemastery.svg" height="42px" alt="Vue Mastery">
</a>
<a href="https://vuetifyjs.com" target="_blank" rel="noopener noreferrer">
<img src="https://cdn.vuetifyjs.com/docs/images/logos/vuetify-logo-light-text.svg" alt="Vuetify" height="48px">
<img src="https://cdn.vuetifyjs.com/docs/images/logos/vuetify-logo-light-text.svg" alt="Vuetify" height="42px">
</a>
<a href="https://www.codestream.com/?utm_source=github&utm_campaign=vuerouter&utm_medium=banner" target="_blank" rel="noopener noreferrer">
<img src="https://alt-images.codestream.com/codestream_logo_vuerouter.png" alt="CodeStream" height="42px">
</a>
</p>

@@ -84,3 +100,3 @@

```sh
```bash
yarn add pinia@next

@@ -104,3 +120,2 @@ # or with npm

This will also add devtools support. Some features like time traveling and editing are still not supported because vue-devtools doesn't expose the necessary APIs yet.
**NOTE**: this API is still experimental and is currently only used for devtools and SSR but that might change in the future.

@@ -130,3 +145,3 @@ ### Creating a Store

doubleCountPlusOne() {
return this.doubleCount * 2
return this.doubleCount * 2 + 1
},

@@ -165,269 +180,8 @@ },

Note: the SSR implementation on Pinia might change, but if you intend having SSR on your application, you should avoid using `useStore` functions at the root level of a file to make sure the correct store is retrieved for your currently running application instance. Here is an example:
## Documentation
**Avoid doing this**:
To learn more about Pinia, check [its documentation](https://pinia.esm.dev).
```ts
import { createRouter } from 'vue-router'
const router = createRouter({
// ...
})
// ❌ Depending on where you do this it will fail
const main = useMainStore()
router.beforeEach((to, from, next) => {
if (main.isLoggedIn) next()
else next('/login')
})
```
Instead, call `useMainStore()` at the top of `setup`, like `inject` and `provide` in Vue:
```ts
export default defineComponent({
setup() {
// ✅ This will work
const main = useMainStore()
return {}
},
})
// In a different file...
const pinia = createPinia()
app.use(pinia)
router.beforeEach((to) => {
// ✅ This will work (requires pinia param when outside of setup on both
// Client and Server. See the SSR section below for more information)
const main = useMainStore(pinia)
if (to.meta.requiresAuth && !main.isLoggedIn) return '/login'
})
```
⚠️: Note that if you are developing an SSR application, [you will need to do a bit more](#ssr).
You can access any property defined in `state` and `getters` directly on the store, similar to `data` and `computed` properties in a Vue component.
```ts
export default defineComponent({
setup() {
const main = useMainStore()
const text = main.name // "eduardo"
const doubleCount = main.doubleCount // 2
return {
text, // will always be "eduardo"
textDynamic: computed(() => main.name), // reactive value
}
},
})
```
The `main` store in an object wrapped with `reactive`, meaning there is no need to write `.value` after getters but, like `props` in `setup`, we cannot destructure it:
```ts
export default defineComponent({
setup() {
// ❌ This won't work because it breaks reactivity
// it's the same as destructuring from `props`
const { name, doubleCount } = useMainStore()
return { name, doubleCount }
},
})
```
Actions are invoked like methods:
```ts
export default defineComponent({
setup() {
const main = useMainStore()
// call the action as a method of the store
main.reset()
return {}
},
})
```
### Mutating the `state`
To mutate the state you can either directly change something:
```ts
main.counter++
```
or call the method `$patch` that allows you apply multiple changes at the same time with a partial `state` object:
```ts
main.$patch({
counter: -1,
name: 'Abalam',
})
```
The main difference here is that `$patch` allows you to group multiple changes into one single entry in the devtools.
### Replacing the `state`
Simply set it to a new object;
```ts
main.state = { counter: 666, name: 'Paimon' }
```
### SSR
Creating stores with Pinia should work out of the box for SSR as long as you call your `useStore()` functions at the top of `setup` functions, `getters` and `actions`:
```ts
export default defineComponent({
setup() {
// this works because pinia knows what application is running
const main = useMainStore()
return { main }
},
})
```
If you need to use the store somewhere else, you need to pass the `pinia` instance [that was passed to the app](#install-the-plugin) to the `useStore()` function call:
```ts
const pinia = createPinia()
const app = createApp(App)
app.use(router)
app.use(pinia)
router.beforeEach((to) => {
// ✅ This will work make sure the correct store is used for the current running app
const main = useMainStore(pinia)
if (to.meta.requiresAuth && !main.isLoggedIn) return '/login'
})
```
To hydrate the initial state, you need to make sure the rootState is included somewhere in the HTML for Pinia to pick it up later on:
```js
import { createPinia } from 'pinia'
// retrieve the rootState server side
const pinia = createPinia()
const app = createApp(App)
app.use(router)
app.use(pinia)
// after rendering the page, the root state is build and can be read
// serialize, escape (VERY important if the content of the state can be changed
// by the user, which is almost always the case), and place it somewhere on
// the page, for example, as a global variable.
JSON.stringify(pinia.state.value)
```
On client side, you must hydrate pinia's state before calling any `useStore()` function. For example, if we serialize the state into a `<script>` tag to make it accessible globally on client side through `window.__pinia`, we can write this:
```js
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
// must be set by the user
if (isClient) {
pinia.state.value = JSON.parse(window.__pinia)
}
```
### Composing Stores
Composing stores may look hard at first glance but there is only one rule to follow really:
If **multiple stores use each other** or you need to use **multiple stores** at the same time, you must create a **separate file** where you import all of them.
If one store uses an other store, there is no need to create a new file, you can directly import it. Think of it as nesting.
You can call `useOtherStore()` at the top of any getter an action:
```ts
import { useUserStore } from './user'
export const cartStore = defineStore({
id: 'cart',
getters: {
// ... other getters
summary() {
const user = useUserStore()
return `Hi ${user.name}, you have ${this.list.length} items in your cart. It costs ${this.price}.`
},
},
actions: {
purchase() {
const user = useUserStore()
return apiPurchase(user.id, this.list)
},
},
})
```
#### Shared Getters
If you need to compute a value based on the `state` and/or `getters` of multiple stores, you may be able to import all the stores but one into the remaining store, but depending on how your stores are used across your application, **this would hurt your code splitting** because importing the store that imports all others stores, would result in **one single big chunk** with all of your stores.
To prevent this, **we follow the rule above** and we create a new file with a new store:
```ts
import { defineStore } from 'pinia'
import { useUserStore } from './user'
import { useCartStore } from './cart'
export const useSharedStore = defineStore({
id: 'shared',
getters: {
summary() {
const user = useUserStore()
const cart = useCartStore()
return `Hi ${user.name}, you have ${cart.list.length} items in your cart. It costs ${cart.price}.`
},
},
})
```
#### Shared Actions
When an actions needs to use multiple stores, we do the same, we create a new file with a new store:
```ts
import { defineStore } from 'pinia'
import { useUserStore } from './user'
import { useCartStore } from './cart'
export const useSharedStore = defineStore({
id: 'shared',
state: () => ({}),
actions: {
async orderCart() {
const user = useUserStore()
const cart = useCartStore()
try {
await apiOrderCart(user.token, cart.items)
cart.emptyCart()
} catch (err) {
displayError(err)
}
},
},
})
```
## Related
## License
[MIT](http://opensource.org/licenses/MIT)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc