1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | import { getCurrentInstance, inject, toRaw, watch, unref, markRaw, effectScope, ref, isVue2, isRef, isReactive, set, getCurrentScope, onScopeDispose, reactive, toRef, del, nextTick, computed, toRefs } from 'vue-demi';
|
7 | import { setupDevtoolsPlugin } from '@vue/devtools-api';
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | let activePinia;
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | const setActivePinia = (pinia) => (activePinia = pinia);
|
21 |
|
22 |
|
23 |
|
24 | const getActivePinia = () => (getCurrentInstance() && inject(piniaSymbol)) || activePinia;
|
25 | const piniaSymbol = (Symbol('pinia') );
|
26 |
|
27 | function isPlainObject(
|
28 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
29 | o) {
|
30 | return (o &&
|
31 | typeof o === 'object' &&
|
32 | Object.prototype.toString.call(o) === '[object Object]' &&
|
33 | typeof o.toJSON !== 'function');
|
34 | }
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | var MutationType;
|
41 | (function (MutationType) {
|
42 | |
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 | MutationType["direct"] = "direct";
|
50 | |
51 |
|
52 |
|
53 |
|
54 |
|
55 | MutationType["patchObject"] = "patch object";
|
56 | |
57 |
|
58 |
|
59 |
|
60 |
|
61 | MutationType["patchFunction"] = "patch function";
|
62 |
|
63 | })(MutationType || (MutationType = {}));
|
64 |
|
65 | const IS_CLIENT = typeof window !== 'undefined';
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 | const USE_DEVTOOLS = IS_CLIENT;
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 | const _global = (() => typeof window === 'object' && window.window === window
|
85 | ? window
|
86 | : typeof self === 'object' && self.self === self
|
87 | ? self
|
88 | : typeof global === 'object' && global.global === global
|
89 | ? global
|
90 | : typeof globalThis === 'object'
|
91 | ? globalThis
|
92 | : { HTMLElement: null })();
|
93 | function bom(blob, { autoBom = false } = {}) {
|
94 |
|
95 |
|
96 | if (autoBom &&
|
97 | /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
|
98 | return new Blob([String.fromCharCode(0xfeff), blob], { type: blob.type });
|
99 | }
|
100 | return blob;
|
101 | }
|
102 | function download(url, name, opts) {
|
103 | const xhr = new XMLHttpRequest();
|
104 | xhr.open('GET', url);
|
105 | xhr.responseType = 'blob';
|
106 | xhr.onload = function () {
|
107 | saveAs(xhr.response, name, opts);
|
108 | };
|
109 | xhr.onerror = function () {
|
110 | console.error('could not download file');
|
111 | };
|
112 | xhr.send();
|
113 | }
|
114 | function corsEnabled(url) {
|
115 | const xhr = new XMLHttpRequest();
|
116 |
|
117 | xhr.open('HEAD', url, false);
|
118 | try {
|
119 | xhr.send();
|
120 | }
|
121 | catch (e) { }
|
122 | return xhr.status >= 200 && xhr.status <= 299;
|
123 | }
|
124 |
|
125 | function click(node) {
|
126 | try {
|
127 | node.dispatchEvent(new MouseEvent('click'));
|
128 | }
|
129 | catch (e) {
|
130 | const evt = document.createEvent('MouseEvents');
|
131 | evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
|
132 | node.dispatchEvent(evt);
|
133 | }
|
134 | }
|
135 | const _navigator =
|
136 | typeof navigator === 'object' ? navigator : { userAgent: '' };
|
137 |
|
138 |
|
139 |
|
140 | const isMacOSWebView = (() => /Macintosh/.test(_navigator.userAgent) &&
|
141 | /AppleWebKit/.test(_navigator.userAgent) &&
|
142 | !/Safari/.test(_navigator.userAgent))();
|
143 | const saveAs = !IS_CLIENT
|
144 | ? () => { }
|
145 | :
|
146 | typeof HTMLAnchorElement !== 'undefined' &&
|
147 | 'download' in HTMLAnchorElement.prototype &&
|
148 | !isMacOSWebView
|
149 | ? downloadSaveAs
|
150 | :
|
151 | 'msSaveOrOpenBlob' in _navigator
|
152 | ? msSaveAs
|
153 | :
|
154 | fileSaverSaveAs;
|
155 | function downloadSaveAs(blob, name = 'download', opts) {
|
156 | const a = document.createElement('a');
|
157 | a.download = name;
|
158 | a.rel = 'noopener';
|
159 |
|
160 |
|
161 | if (typeof blob === 'string') {
|
162 |
|
163 | a.href = blob;
|
164 | if (a.origin !== location.origin) {
|
165 | if (corsEnabled(a.href)) {
|
166 | download(blob, name, opts);
|
167 | }
|
168 | else {
|
169 | a.target = '_blank';
|
170 | click(a);
|
171 | }
|
172 | }
|
173 | else {
|
174 | click(a);
|
175 | }
|
176 | }
|
177 | else {
|
178 |
|
179 | a.href = URL.createObjectURL(blob);
|
180 | setTimeout(function () {
|
181 | URL.revokeObjectURL(a.href);
|
182 | }, 4e4);
|
183 | setTimeout(function () {
|
184 | click(a);
|
185 | }, 0);
|
186 | }
|
187 | }
|
188 | function msSaveAs(blob, name = 'download', opts) {
|
189 | if (typeof blob === 'string') {
|
190 | if (corsEnabled(blob)) {
|
191 | download(blob, name, opts);
|
192 | }
|
193 | else {
|
194 | const a = document.createElement('a');
|
195 | a.href = blob;
|
196 | a.target = '_blank';
|
197 | setTimeout(function () {
|
198 | click(a);
|
199 | });
|
200 | }
|
201 | }
|
202 | else {
|
203 |
|
204 | navigator.msSaveOrOpenBlob(bom(blob, opts), name);
|
205 | }
|
206 | }
|
207 | function fileSaverSaveAs(blob, name, opts, popup) {
|
208 |
|
209 |
|
210 | popup = popup || open('', '_blank');
|
211 | if (popup) {
|
212 | popup.document.title = popup.document.body.innerText = 'downloading...';
|
213 | }
|
214 | if (typeof blob === 'string')
|
215 | return download(blob, name, opts);
|
216 | const force = blob.type === 'application/octet-stream';
|
217 | const isSafari = /constructor/i.test(String(_global.HTMLElement)) || 'safari' in _global;
|
218 | const isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
|
219 | if ((isChromeIOS || (force && isSafari) || isMacOSWebView) &&
|
220 | typeof FileReader !== 'undefined') {
|
221 |
|
222 | const reader = new FileReader();
|
223 | reader.onloadend = function () {
|
224 | let url = reader.result;
|
225 | if (typeof url !== 'string') {
|
226 | popup = null;
|
227 | throw new Error('Wrong reader.result type');
|
228 | }
|
229 | url = isChromeIOS
|
230 | ? url
|
231 | : url.replace(/^data:[^;]*;/, 'data:attachment/file;');
|
232 | if (popup) {
|
233 | popup.location.href = url;
|
234 | }
|
235 | else {
|
236 | location.assign(url);
|
237 | }
|
238 | popup = null;
|
239 | };
|
240 | reader.readAsDataURL(blob);
|
241 | }
|
242 | else {
|
243 | const url = URL.createObjectURL(blob);
|
244 | if (popup)
|
245 | popup.location.assign(url);
|
246 | else
|
247 | location.href = url;
|
248 | popup = null;
|
249 | setTimeout(function () {
|
250 | URL.revokeObjectURL(url);
|
251 | }, 4e4);
|
252 | }
|
253 | }
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 |
|
261 | function toastMessage(message, type) {
|
262 | const piniaMessage = '🍍 ' + message;
|
263 | if (typeof __VUE_DEVTOOLS_TOAST__ === 'function') {
|
264 | __VUE_DEVTOOLS_TOAST__(piniaMessage, type);
|
265 | }
|
266 | else if (type === 'error') {
|
267 | console.error(piniaMessage);
|
268 | }
|
269 | else if (type === 'warn') {
|
270 | console.warn(piniaMessage);
|
271 | }
|
272 | else {
|
273 | console.log(piniaMessage);
|
274 | }
|
275 | }
|
276 | function isPinia(o) {
|
277 | return '_a' in o && 'install' in o;
|
278 | }
|
279 |
|
280 | function checkClipboardAccess() {
|
281 | if (!('clipboard' in navigator)) {
|
282 | toastMessage(`Your browser doesn't support the Clipboard API`, 'error');
|
283 | return true;
|
284 | }
|
285 | }
|
286 | function checkNotFocusedError(error) {
|
287 | if (error instanceof Error &&
|
288 | error.message.toLowerCase().includes('document is not focused')) {
|
289 | toastMessage('You need to activate the "Emulate a focused page" setting in the "Rendering" panel of devtools.', 'warn');
|
290 | return true;
|
291 | }
|
292 | return false;
|
293 | }
|
294 | async function actionGlobalCopyState(pinia) {
|
295 | if (checkClipboardAccess())
|
296 | return;
|
297 | try {
|
298 | await navigator.clipboard.writeText(JSON.stringify(pinia.state.value));
|
299 | toastMessage('Global state copied to clipboard.');
|
300 | }
|
301 | catch (error) {
|
302 | if (checkNotFocusedError(error))
|
303 | return;
|
304 | toastMessage(`Failed to serialize the state. Check the console for more details.`, 'error');
|
305 | console.error(error);
|
306 | }
|
307 | }
|
308 | async function actionGlobalPasteState(pinia) {
|
309 | if (checkClipboardAccess())
|
310 | return;
|
311 | try {
|
312 | pinia.state.value = JSON.parse(await navigator.clipboard.readText());
|
313 | toastMessage('Global state pasted from clipboard.');
|
314 | }
|
315 | catch (error) {
|
316 | if (checkNotFocusedError(error))
|
317 | return;
|
318 | toastMessage(`Failed to deserialize the state from clipboard. Check the console for more details.`, 'error');
|
319 | console.error(error);
|
320 | }
|
321 | }
|
322 | async function actionGlobalSaveState(pinia) {
|
323 | try {
|
324 | saveAs(new Blob([JSON.stringify(pinia.state.value)], {
|
325 | type: 'text/plain;charset=utf-8',
|
326 | }), 'pinia-state.json');
|
327 | }
|
328 | catch (error) {
|
329 | toastMessage(`Failed to export the state as JSON. Check the console for more details.`, 'error');
|
330 | console.error(error);
|
331 | }
|
332 | }
|
333 | let fileInput;
|
334 | function getFileOpener() {
|
335 | if (!fileInput) {
|
336 | fileInput = document.createElement('input');
|
337 | fileInput.type = 'file';
|
338 | fileInput.accept = '.json';
|
339 | }
|
340 | function openFile() {
|
341 | return new Promise((resolve, reject) => {
|
342 | fileInput.onchange = async () => {
|
343 | const files = fileInput.files;
|
344 | if (!files)
|
345 | return resolve(null);
|
346 | const file = files.item(0);
|
347 | if (!file)
|
348 | return resolve(null);
|
349 | return resolve({ text: await file.text(), file });
|
350 | };
|
351 |
|
352 | fileInput.oncancel = () => resolve(null);
|
353 | fileInput.onerror = reject;
|
354 | fileInput.click();
|
355 | });
|
356 | }
|
357 | return openFile;
|
358 | }
|
359 | async function actionGlobalOpenStateFile(pinia) {
|
360 | try {
|
361 | const open = await getFileOpener();
|
362 | const result = await open();
|
363 | if (!result)
|
364 | return;
|
365 | const { text, file } = result;
|
366 | pinia.state.value = JSON.parse(text);
|
367 | toastMessage(`Global state imported from "${file.name}".`);
|
368 | }
|
369 | catch (error) {
|
370 | toastMessage(`Failed to export the state as JSON. Check the console for more details.`, 'error');
|
371 | console.error(error);
|
372 | }
|
373 | }
|
374 |
|
375 | function formatDisplay(display) {
|
376 | return {
|
377 | _custom: {
|
378 | display,
|
379 | },
|
380 | };
|
381 | }
|
382 | const PINIA_ROOT_LABEL = '🍍 Pinia (root)';
|
383 | const PINIA_ROOT_ID = '_root';
|
384 | function formatStoreForInspectorTree(store) {
|
385 | return isPinia(store)
|
386 | ? {
|
387 | id: PINIA_ROOT_ID,
|
388 | label: PINIA_ROOT_LABEL,
|
389 | }
|
390 | : {
|
391 | id: store.$id,
|
392 | label: store.$id,
|
393 | };
|
394 | }
|
395 | function formatStoreForInspectorState(store) {
|
396 | if (isPinia(store)) {
|
397 | const storeNames = Array.from(store._s.keys());
|
398 | const storeMap = store._s;
|
399 | const state = {
|
400 | state: storeNames.map((storeId) => ({
|
401 | editable: true,
|
402 | key: storeId,
|
403 | value: store.state.value[storeId],
|
404 | })),
|
405 | getters: storeNames
|
406 | .filter((id) => storeMap.get(id)._getters)
|
407 | .map((id) => {
|
408 | const store = storeMap.get(id);
|
409 | return {
|
410 | editable: false,
|
411 | key: id,
|
412 | value: store._getters.reduce((getters, key) => {
|
413 | getters[key] = store[key];
|
414 | return getters;
|
415 | }, {}),
|
416 | };
|
417 | }),
|
418 | };
|
419 | return state;
|
420 | }
|
421 | const state = {
|
422 | state: Object.keys(store.$state).map((key) => ({
|
423 | editable: true,
|
424 | key,
|
425 | value: store.$state[key],
|
426 | })),
|
427 | };
|
428 |
|
429 | if (store._getters && store._getters.length) {
|
430 | state.getters = store._getters.map((getterName) => ({
|
431 | editable: false,
|
432 | key: getterName,
|
433 | value: store[getterName],
|
434 | }));
|
435 | }
|
436 | if (store._customProperties.size) {
|
437 | state.customProperties = Array.from(store._customProperties).map((key) => ({
|
438 | editable: true,
|
439 | key,
|
440 | value: store[key],
|
441 | }));
|
442 | }
|
443 | return state;
|
444 | }
|
445 | function formatEventData(events) {
|
446 | if (!events)
|
447 | return {};
|
448 | if (Array.isArray(events)) {
|
449 |
|
450 | return events.reduce((data, event) => {
|
451 | data.keys.push(event.key);
|
452 | data.operations.push(event.type);
|
453 | data.oldValue[event.key] = event.oldValue;
|
454 | data.newValue[event.key] = event.newValue;
|
455 | return data;
|
456 | }, {
|
457 | oldValue: {},
|
458 | keys: [],
|
459 | operations: [],
|
460 | newValue: {},
|
461 | });
|
462 | }
|
463 | else {
|
464 | return {
|
465 | operation: formatDisplay(events.type),
|
466 | key: formatDisplay(events.key),
|
467 | oldValue: events.oldValue,
|
468 | newValue: events.newValue,
|
469 | };
|
470 | }
|
471 | }
|
472 | function formatMutationType(type) {
|
473 | switch (type) {
|
474 | case MutationType.direct:
|
475 | return 'mutation';
|
476 | case MutationType.patchFunction:
|
477 | return '$patch';
|
478 | case MutationType.patchObject:
|
479 | return '$patch';
|
480 | default:
|
481 | return 'unknown';
|
482 | }
|
483 | }
|
484 |
|
485 |
|
486 | let isTimelineActive = true;
|
487 | const componentStateTypes = [];
|
488 | const MUTATIONS_LAYER_ID = 'pinia:mutations';
|
489 | const INSPECTOR_ID = 'pinia';
|
490 |
|
491 |
|
492 |
|
493 |
|
494 |
|
495 |
|
496 | const getStoreType = (id) => '🍍 ' + id;
|
497 |
|
498 |
|
499 |
|
500 |
|
501 |
|
502 |
|
503 |
|
504 | function registerPiniaDevtools(app, pinia) {
|
505 | setupDevtoolsPlugin({
|
506 | id: 'dev.esm.pinia',
|
507 | label: 'Pinia 🍍',
|
508 | logo: 'https://pinia.vuejs.org/logo.svg',
|
509 | packageName: 'pinia',
|
510 | homepage: 'https://pinia.vuejs.org',
|
511 | componentStateTypes,
|
512 | app,
|
513 | }, (api) => {
|
514 | if (typeof api.now !== 'function') {
|
515 | toastMessage('You seem to be using an outdated version of Vue Devtools. Are you still using the Beta release instead of the stable one? You can find the links at https://devtools.vuejs.org/guide/installation.html.');
|
516 | }
|
517 | api.addTimelineLayer({
|
518 | id: MUTATIONS_LAYER_ID,
|
519 | label: `Pinia 🍍`,
|
520 | color: 0xe5df88,
|
521 | });
|
522 | api.addInspector({
|
523 | id: INSPECTOR_ID,
|
524 | label: 'Pinia 🍍',
|
525 | icon: 'storage',
|
526 | treeFilterPlaceholder: 'Search stores',
|
527 | actions: [
|
528 | {
|
529 | icon: 'content_copy',
|
530 | action: () => {
|
531 | actionGlobalCopyState(pinia);
|
532 | },
|
533 | tooltip: 'Serialize and copy the state',
|
534 | },
|
535 | {
|
536 | icon: 'content_paste',
|
537 | action: async () => {
|
538 | await actionGlobalPasteState(pinia);
|
539 | api.sendInspectorTree(INSPECTOR_ID);
|
540 | api.sendInspectorState(INSPECTOR_ID);
|
541 | },
|
542 | tooltip: 'Replace the state with the content of your clipboard',
|
543 | },
|
544 | {
|
545 | icon: 'save',
|
546 | action: () => {
|
547 | actionGlobalSaveState(pinia);
|
548 | },
|
549 | tooltip: 'Save the state as a JSON file',
|
550 | },
|
551 | {
|
552 | icon: 'folder_open',
|
553 | action: async () => {
|
554 | await actionGlobalOpenStateFile(pinia);
|
555 | api.sendInspectorTree(INSPECTOR_ID);
|
556 | api.sendInspectorState(INSPECTOR_ID);
|
557 | },
|
558 | tooltip: 'Import the state from a JSON file',
|
559 | },
|
560 | ],
|
561 | nodeActions: [
|
562 | {
|
563 | icon: 'restore',
|
564 | tooltip: 'Reset the state (option store only)',
|
565 | action: (nodeId) => {
|
566 | const store = pinia._s.get(nodeId);
|
567 | if (!store) {
|
568 | toastMessage(`Cannot reset "${nodeId}" store because it wasn't found.`, 'warn');
|
569 | }
|
570 | else if (!store._isOptionsAPI) {
|
571 | toastMessage(`Cannot reset "${nodeId}" store because it's a setup store.`, 'warn');
|
572 | }
|
573 | else {
|
574 | store.$reset();
|
575 | toastMessage(`Store "${nodeId}" reset.`);
|
576 | }
|
577 | },
|
578 | },
|
579 | ],
|
580 | });
|
581 | api.on.inspectComponent((payload, ctx) => {
|
582 | const proxy = (payload.componentInstance &&
|
583 | payload.componentInstance.proxy);
|
584 | if (proxy && proxy._pStores) {
|
585 | const piniaStores = payload.componentInstance.proxy._pStores;
|
586 | Object.values(piniaStores).forEach((store) => {
|
587 | payload.instanceData.state.push({
|
588 | type: getStoreType(store.$id),
|
589 | key: 'state',
|
590 | editable: true,
|
591 | value: store._isOptionsAPI
|
592 | ? {
|
593 | _custom: {
|
594 | value: toRaw(store.$state),
|
595 | actions: [
|
596 | {
|
597 | icon: 'restore',
|
598 | tooltip: 'Reset the state of this store',
|
599 | action: () => store.$reset(),
|
600 | },
|
601 | ],
|
602 | },
|
603 | }
|
604 | :
|
605 | Object.keys(store.$state).reduce((state, key) => {
|
606 | state[key] = store.$state[key];
|
607 | return state;
|
608 | }, {}),
|
609 | });
|
610 | if (store._getters && store._getters.length) {
|
611 | payload.instanceData.state.push({
|
612 | type: getStoreType(store.$id),
|
613 | key: 'getters',
|
614 | editable: false,
|
615 | value: store._getters.reduce((getters, key) => {
|
616 | try {
|
617 | getters[key] = store[key];
|
618 | }
|
619 | catch (error) {
|
620 |
|
621 | getters[key] = error;
|
622 | }
|
623 | return getters;
|
624 | }, {}),
|
625 | });
|
626 | }
|
627 | });
|
628 | }
|
629 | });
|
630 | api.on.getInspectorTree((payload) => {
|
631 | if (payload.app === app && payload.inspectorId === INSPECTOR_ID) {
|
632 | let stores = [pinia];
|
633 | stores = stores.concat(Array.from(pinia._s.values()));
|
634 | payload.rootNodes = (payload.filter
|
635 | ? stores.filter((store) => '$id' in store
|
636 | ? store.$id
|
637 | .toLowerCase()
|
638 | .includes(payload.filter.toLowerCase())
|
639 | : PINIA_ROOT_LABEL.toLowerCase().includes(payload.filter.toLowerCase()))
|
640 | : stores).map(formatStoreForInspectorTree);
|
641 | }
|
642 | });
|
643 | api.on.getInspectorState((payload) => {
|
644 | if (payload.app === app && payload.inspectorId === INSPECTOR_ID) {
|
645 | const inspectedStore = payload.nodeId === PINIA_ROOT_ID
|
646 | ? pinia
|
647 | : pinia._s.get(payload.nodeId);
|
648 | if (!inspectedStore) {
|
649 |
|
650 |
|
651 | return;
|
652 | }
|
653 | if (inspectedStore) {
|
654 | payload.state = formatStoreForInspectorState(inspectedStore);
|
655 | }
|
656 | }
|
657 | });
|
658 | api.on.editInspectorState((payload, ctx) => {
|
659 | if (payload.app === app && payload.inspectorId === INSPECTOR_ID) {
|
660 | const inspectedStore = payload.nodeId === PINIA_ROOT_ID
|
661 | ? pinia
|
662 | : pinia._s.get(payload.nodeId);
|
663 | if (!inspectedStore) {
|
664 | return toastMessage(`store "${payload.nodeId}" not found`, 'error');
|
665 | }
|
666 | const { path } = payload;
|
667 | if (!isPinia(inspectedStore)) {
|
668 |
|
669 | if (path.length !== 1 ||
|
670 | !inspectedStore._customProperties.has(path[0]) ||
|
671 | path[0] in inspectedStore.$state) {
|
672 | path.unshift('$state');
|
673 | }
|
674 | }
|
675 | else {
|
676 |
|
677 | path.unshift('state');
|
678 | }
|
679 | isTimelineActive = false;
|
680 | payload.set(inspectedStore, path, payload.state.value);
|
681 | isTimelineActive = true;
|
682 | }
|
683 | });
|
684 | api.on.editComponentState((payload) => {
|
685 | if (payload.type.startsWith('🍍')) {
|
686 | const storeId = payload.type.replace(/^🍍\s*/, '');
|
687 | const store = pinia._s.get(storeId);
|
688 | if (!store) {
|
689 | return toastMessage(`store "${storeId}" not found`, 'error');
|
690 | }
|
691 | const { path } = payload;
|
692 | if (path[0] !== 'state') {
|
693 | return toastMessage(`Invalid path for store "${storeId}":\n${path}\nOnly state can be modified.`);
|
694 | }
|
695 |
|
696 |
|
697 | path[0] = '$state';
|
698 | isTimelineActive = false;
|
699 | payload.set(store, path, payload.state.value);
|
700 | isTimelineActive = true;
|
701 | }
|
702 | });
|
703 | });
|
704 | }
|
705 | function addStoreToDevtools(app, store) {
|
706 | if (!componentStateTypes.includes(getStoreType(store.$id))) {
|
707 | componentStateTypes.push(getStoreType(store.$id));
|
708 | }
|
709 | setupDevtoolsPlugin({
|
710 | id: 'dev.esm.pinia',
|
711 | label: 'Pinia 🍍',
|
712 | logo: 'https://pinia.vuejs.org/logo.svg',
|
713 | packageName: 'pinia',
|
714 | homepage: 'https://pinia.vuejs.org',
|
715 | componentStateTypes,
|
716 | app,
|
717 | settings: {
|
718 | logStoreChanges: {
|
719 | label: 'Notify about new/deleted stores',
|
720 | type: 'boolean',
|
721 | defaultValue: true,
|
722 | },
|
723 |
|
724 |
|
725 |
|
726 |
|
727 |
|
728 | },
|
729 | }, (api) => {
|
730 |
|
731 | const now = typeof api.now === 'function' ? api.now.bind(api) : Date.now;
|
732 | store.$onAction(({ after, onError, name, args }) => {
|
733 | const groupId = runningActionId++;
|
734 | api.addTimelineEvent({
|
735 | layerId: MUTATIONS_LAYER_ID,
|
736 | event: {
|
737 | time: now(),
|
738 | title: '🛫 ' + name,
|
739 | subtitle: 'start',
|
740 | data: {
|
741 | store: formatDisplay(store.$id),
|
742 | action: formatDisplay(name),
|
743 | args,
|
744 | },
|
745 | groupId,
|
746 | },
|
747 | });
|
748 | after((result) => {
|
749 | activeAction = undefined;
|
750 | api.addTimelineEvent({
|
751 | layerId: MUTATIONS_LAYER_ID,
|
752 | event: {
|
753 | time: now(),
|
754 | title: '🛬 ' + name,
|
755 | subtitle: 'end',
|
756 | data: {
|
757 | store: formatDisplay(store.$id),
|
758 | action: formatDisplay(name),
|
759 | args,
|
760 | result,
|
761 | },
|
762 | groupId,
|
763 | },
|
764 | });
|
765 | });
|
766 | onError((error) => {
|
767 | activeAction = undefined;
|
768 | api.addTimelineEvent({
|
769 | layerId: MUTATIONS_LAYER_ID,
|
770 | event: {
|
771 | time: now(),
|
772 | logType: 'error',
|
773 | title: '💥 ' + name,
|
774 | subtitle: 'end',
|
775 | data: {
|
776 | store: formatDisplay(store.$id),
|
777 | action: formatDisplay(name),
|
778 | args,
|
779 | error,
|
780 | },
|
781 | groupId,
|
782 | },
|
783 | });
|
784 | });
|
785 | }, true);
|
786 | store._customProperties.forEach((name) => {
|
787 | watch(() => unref(store[name]), (newValue, oldValue) => {
|
788 | api.notifyComponentUpdate();
|
789 | api.sendInspectorState(INSPECTOR_ID);
|
790 | if (isTimelineActive) {
|
791 | api.addTimelineEvent({
|
792 | layerId: MUTATIONS_LAYER_ID,
|
793 | event: {
|
794 | time: now(),
|
795 | title: 'Change',
|
796 | subtitle: name,
|
797 | data: {
|
798 | newValue,
|
799 | oldValue,
|
800 | },
|
801 | groupId: activeAction,
|
802 | },
|
803 | });
|
804 | }
|
805 | }, { deep: true });
|
806 | });
|
807 | store.$subscribe(({ events, type }, state) => {
|
808 | api.notifyComponentUpdate();
|
809 | api.sendInspectorState(INSPECTOR_ID);
|
810 | if (!isTimelineActive)
|
811 | return;
|
812 |
|
813 | const eventData = {
|
814 | time: now(),
|
815 | title: formatMutationType(type),
|
816 | data: {
|
817 | store: formatDisplay(store.$id),
|
818 | ...formatEventData(events),
|
819 | },
|
820 | groupId: activeAction,
|
821 | };
|
822 |
|
823 | activeAction = undefined;
|
824 | if (type === MutationType.patchFunction) {
|
825 | eventData.subtitle = '⤵️';
|
826 | }
|
827 | else if (type === MutationType.patchObject) {
|
828 | eventData.subtitle = '🧩';
|
829 | }
|
830 | else if (events && !Array.isArray(events)) {
|
831 | eventData.subtitle = events.type;
|
832 | }
|
833 | if (events) {
|
834 | eventData.data['rawEvent(s)'] = {
|
835 | _custom: {
|
836 | display: 'DebuggerEvent',
|
837 | type: 'object',
|
838 | tooltip: 'raw DebuggerEvent[]',
|
839 | value: events,
|
840 | },
|
841 | };
|
842 | }
|
843 | api.addTimelineEvent({
|
844 | layerId: MUTATIONS_LAYER_ID,
|
845 | event: eventData,
|
846 | });
|
847 | }, { detached: true, flush: 'sync' });
|
848 | const hotUpdate = store._hotUpdate;
|
849 | store._hotUpdate = markRaw((newStore) => {
|
850 | hotUpdate(newStore);
|
851 | api.addTimelineEvent({
|
852 | layerId: MUTATIONS_LAYER_ID,
|
853 | event: {
|
854 | time: now(),
|
855 | title: '🔥 ' + store.$id,
|
856 | subtitle: 'HMR update',
|
857 | data: {
|
858 | store: formatDisplay(store.$id),
|
859 | info: formatDisplay(`HMR update`),
|
860 | },
|
861 | },
|
862 | });
|
863 |
|
864 | api.notifyComponentUpdate();
|
865 | api.sendInspectorTree(INSPECTOR_ID);
|
866 | api.sendInspectorState(INSPECTOR_ID);
|
867 | });
|
868 | const { $dispose } = store;
|
869 | store.$dispose = () => {
|
870 | $dispose();
|
871 | api.notifyComponentUpdate();
|
872 | api.sendInspectorTree(INSPECTOR_ID);
|
873 | api.sendInspectorState(INSPECTOR_ID);
|
874 | api.getSettings().logStoreChanges &&
|
875 | toastMessage(`Disposed "${store.$id}" store 🗑`);
|
876 | };
|
877 |
|
878 | api.notifyComponentUpdate();
|
879 | api.sendInspectorTree(INSPECTOR_ID);
|
880 | api.sendInspectorState(INSPECTOR_ID);
|
881 | api.getSettings().logStoreChanges &&
|
882 | toastMessage(`"${store.$id}" store installed 🆕`);
|
883 | });
|
884 | }
|
885 | let runningActionId = 0;
|
886 | let activeAction;
|
887 |
|
888 |
|
889 |
|
890 |
|
891 |
|
892 |
|
893 |
|
894 |
|
895 | function patchActionForGrouping(store, actionNames) {
|
896 |
|
897 | const actions = actionNames.reduce((storeActions, actionName) => {
|
898 |
|
899 | storeActions[actionName] = toRaw(store)[actionName];
|
900 | return storeActions;
|
901 | }, {});
|
902 | for (const actionName in actions) {
|
903 | store[actionName] = function () {
|
904 |
|
905 |
|
906 | const _actionId = runningActionId;
|
907 | const trackedStore = new Proxy(store, {
|
908 | get(...args) {
|
909 | activeAction = _actionId;
|
910 | return Reflect.get(...args);
|
911 | },
|
912 | set(...args) {
|
913 | activeAction = _actionId;
|
914 | return Reflect.set(...args);
|
915 | },
|
916 | });
|
917 | return actions[actionName].apply(trackedStore, arguments);
|
918 | };
|
919 | }
|
920 | }
|
921 |
|
922 |
|
923 |
|
924 | function devtoolsPlugin({ app, store, options }) {
|
925 |
|
926 | if (store.$id.startsWith('__hot:')) {
|
927 | return;
|
928 | }
|
929 |
|
930 | if (options.state) {
|
931 | store._isOptionsAPI = true;
|
932 | }
|
933 |
|
934 |
|
935 | if (typeof options.state === 'function') {
|
936 | patchActionForGrouping(
|
937 |
|
938 | store, Object.keys(options.actions));
|
939 | const originalHotUpdate = store._hotUpdate;
|
940 |
|
941 | toRaw(store)._hotUpdate = function (newStore) {
|
942 | originalHotUpdate.apply(this, arguments);
|
943 | patchActionForGrouping(store, Object.keys(newStore._hmrPayload.actions));
|
944 | };
|
945 | }
|
946 | addStoreToDevtools(app,
|
947 |
|
948 | store);
|
949 | }
|
950 |
|
951 |
|
952 |
|
953 |
|
954 | function createPinia() {
|
955 | const scope = effectScope(true);
|
956 |
|
957 |
|
958 | const state = scope.run(() => ref({}));
|
959 | let _p = [];
|
960 |
|
961 | let toBeInstalled = [];
|
962 | const pinia = markRaw({
|
963 | install(app) {
|
964 |
|
965 |
|
966 | setActivePinia(pinia);
|
967 | if (!isVue2) {
|
968 | pinia._a = app;
|
969 | app.provide(piniaSymbol, pinia);
|
970 | app.config.globalProperties.$pinia = pinia;
|
971 |
|
972 | if (USE_DEVTOOLS) {
|
973 | registerPiniaDevtools(app, pinia);
|
974 | }
|
975 | toBeInstalled.forEach((plugin) => _p.push(plugin));
|
976 | toBeInstalled = [];
|
977 | }
|
978 | },
|
979 | use(plugin) {
|
980 | if (!this._a && !isVue2) {
|
981 | toBeInstalled.push(plugin);
|
982 | }
|
983 | else {
|
984 | _p.push(plugin);
|
985 | }
|
986 | return this;
|
987 | },
|
988 | _p,
|
989 |
|
990 |
|
991 | _a: null,
|
992 | _e: scope,
|
993 | _s: new Map(),
|
994 | state,
|
995 | });
|
996 |
|
997 |
|
998 | if (USE_DEVTOOLS && typeof Proxy !== 'undefined') {
|
999 | pinia.use(devtoolsPlugin);
|
1000 | }
|
1001 | return pinia;
|
1002 | }
|
1003 |
|
1004 |
|
1005 |
|
1006 |
|
1007 |
|
1008 |
|
1009 |
|
1010 | const isUseStore = (fn) => {
|
1011 | return typeof fn === 'function' && typeof fn.$id === 'string';
|
1012 | };
|
1013 |
|
1014 |
|
1015 |
|
1016 |
|
1017 |
|
1018 |
|
1019 |
|
1020 |
|
1021 |
|
1022 | function patchObject(newState, oldState) {
|
1023 |
|
1024 | for (const key in oldState) {
|
1025 | const subPatch = oldState[key];
|
1026 |
|
1027 | if (!(key in newState)) {
|
1028 | continue;
|
1029 | }
|
1030 | const targetValue = newState[key];
|
1031 | if (isPlainObject(targetValue) &&
|
1032 | isPlainObject(subPatch) &&
|
1033 | !isRef(subPatch) &&
|
1034 | !isReactive(subPatch)) {
|
1035 | newState[key] = patchObject(targetValue, subPatch);
|
1036 | }
|
1037 | else {
|
1038 |
|
1039 |
|
1040 | if (isVue2) {
|
1041 | set(newState, key, subPatch);
|
1042 | }
|
1043 | else {
|
1044 | newState[key] = subPatch;
|
1045 | }
|
1046 | }
|
1047 | }
|
1048 | return newState;
|
1049 | }
|
1050 |
|
1051 |
|
1052 |
|
1053 |
|
1054 |
|
1055 |
|
1056 |
|
1057 |
|
1058 |
|
1059 |
|
1060 |
|
1061 |
|
1062 |
|
1063 |
|
1064 | function acceptHMRUpdate(initialUseStore, hot) {
|
1065 | return (newModule) => {
|
1066 | const pinia = hot.data.pinia || initialUseStore._pinia;
|
1067 | if (!pinia) {
|
1068 |
|
1069 | return;
|
1070 | }
|
1071 |
|
1072 | hot.data.pinia = pinia;
|
1073 |
|
1074 | for (const exportName in newModule) {
|
1075 | const useStore = newModule[exportName];
|
1076 |
|
1077 | if (isUseStore(useStore) && pinia._s.has(useStore.$id)) {
|
1078 |
|
1079 | const id = useStore.$id;
|
1080 | if (id !== initialUseStore.$id) {
|
1081 | console.warn(`The id of the store changed from "${initialUseStore.$id}" to "${id}". Reloading.`);
|
1082 |
|
1083 | return hot.invalidate();
|
1084 | }
|
1085 | const existingStore = pinia._s.get(id);
|
1086 | if (!existingStore) {
|
1087 | console.log(`[Pinia]: skipping hmr because store doesn't exist yet`);
|
1088 | return;
|
1089 | }
|
1090 | useStore(pinia, existingStore);
|
1091 | }
|
1092 | }
|
1093 | };
|
1094 | }
|
1095 |
|
1096 | const noop = () => { };
|
1097 | function addSubscription(subscriptions, callback, detached, onCleanup = noop) {
|
1098 | subscriptions.push(callback);
|
1099 | const removeSubscription = () => {
|
1100 | const idx = subscriptions.indexOf(callback);
|
1101 | if (idx > -1) {
|
1102 | subscriptions.splice(idx, 1);
|
1103 | onCleanup();
|
1104 | }
|
1105 | };
|
1106 | if (!detached && getCurrentScope()) {
|
1107 | onScopeDispose(removeSubscription);
|
1108 | }
|
1109 | return removeSubscription;
|
1110 | }
|
1111 | function triggerSubscriptions(subscriptions, ...args) {
|
1112 | subscriptions.slice().forEach((callback) => {
|
1113 | callback(...args);
|
1114 | });
|
1115 | }
|
1116 |
|
1117 | function mergeReactiveObjects(target, patchToApply) {
|
1118 |
|
1119 | if (target instanceof Map && patchToApply instanceof Map) {
|
1120 | patchToApply.forEach((value, key) => target.set(key, value));
|
1121 | }
|
1122 |
|
1123 | if (target instanceof Set && patchToApply instanceof Set) {
|
1124 | patchToApply.forEach(target.add, target);
|
1125 | }
|
1126 |
|
1127 | for (const key in patchToApply) {
|
1128 | if (!patchToApply.hasOwnProperty(key))
|
1129 | continue;
|
1130 | const subPatch = patchToApply[key];
|
1131 | const targetValue = target[key];
|
1132 | if (isPlainObject(targetValue) &&
|
1133 | isPlainObject(subPatch) &&
|
1134 | target.hasOwnProperty(key) &&
|
1135 | !isRef(subPatch) &&
|
1136 | !isReactive(subPatch)) {
|
1137 |
|
1138 |
|
1139 |
|
1140 | target[key] = mergeReactiveObjects(targetValue, subPatch);
|
1141 | }
|
1142 | else {
|
1143 |
|
1144 | target[key] = subPatch;
|
1145 | }
|
1146 | }
|
1147 | return target;
|
1148 | }
|
1149 | const skipHydrateSymbol = Symbol('pinia:skipHydration')
|
1150 | ;
|
1151 | const skipHydrateMap = new WeakMap();
|
1152 |
|
1153 |
|
1154 |
|
1155 |
|
1156 |
|
1157 |
|
1158 |
|
1159 | function skipHydrate(obj) {
|
1160 | return isVue2
|
1161 | ?
|
1162 | skipHydrateMap.set(obj, 1) && obj
|
1163 | : Object.defineProperty(obj, skipHydrateSymbol, {});
|
1164 | }
|
1165 |
|
1166 |
|
1167 |
|
1168 |
|
1169 |
|
1170 |
|
1171 | function shouldHydrate(obj) {
|
1172 | return isVue2
|
1173 | ? !skipHydrateMap.has(obj)
|
1174 | : !isPlainObject(obj) || !obj.hasOwnProperty(skipHydrateSymbol);
|
1175 | }
|
1176 | const { assign } = Object;
|
1177 | function isComputed(o) {
|
1178 | return !!(isRef(o) && o.effect);
|
1179 | }
|
1180 | function createOptionsStore(id, options, pinia, hot) {
|
1181 | const { state, actions, getters } = options;
|
1182 | const initialState = pinia.state.value[id];
|
1183 | let store;
|
1184 | function setup() {
|
1185 | if (!initialState && (!hot)) {
|
1186 |
|
1187 | if (isVue2) {
|
1188 | set(pinia.state.value, id, state ? state() : {});
|
1189 | }
|
1190 | else {
|
1191 | pinia.state.value[id] = state ? state() : {};
|
1192 | }
|
1193 | }
|
1194 |
|
1195 | const localState = hot
|
1196 | ?
|
1197 | toRefs(ref(state ? state() : {}).value)
|
1198 | : toRefs(pinia.state.value[id]);
|
1199 | return assign(localState, actions, Object.keys(getters || {}).reduce((computedGetters, name) => {
|
1200 | if (name in localState) {
|
1201 | console.warn(`[🍍]: A getter cannot have the same name as another state property. Rename one of them. Found with "${name}" in store "${id}".`);
|
1202 | }
|
1203 | computedGetters[name] = markRaw(computed(() => {
|
1204 | setActivePinia(pinia);
|
1205 |
|
1206 | const store = pinia._s.get(id);
|
1207 |
|
1208 |
|
1209 | if (isVue2 && !store._r)
|
1210 | return;
|
1211 |
|
1212 |
|
1213 |
|
1214 | return getters[name].call(store, store);
|
1215 | }));
|
1216 | return computedGetters;
|
1217 | }, {}));
|
1218 | }
|
1219 | store = createSetupStore(id, setup, options, pinia, hot, true);
|
1220 | store.$reset = function $reset() {
|
1221 | const newState = state ? state() : {};
|
1222 |
|
1223 | this.$patch(($state) => {
|
1224 | assign($state, newState);
|
1225 | });
|
1226 | };
|
1227 | return store;
|
1228 | }
|
1229 | function createSetupStore($id, setup, options = {}, pinia, hot, isOptionsStore) {
|
1230 | let scope;
|
1231 | const optionsForPlugin = assign({ actions: {} }, options);
|
1232 |
|
1233 |
|
1234 | if (!pinia._e.active) {
|
1235 | throw new Error('Pinia destroyed');
|
1236 | }
|
1237 |
|
1238 | const $subscribeOptions = {
|
1239 | deep: true,
|
1240 |
|
1241 | };
|
1242 |
|
1243 | if (!isVue2) {
|
1244 | $subscribeOptions.onTrigger = (event) => {
|
1245 |
|
1246 | if (isListening) {
|
1247 | debuggerEvents = event;
|
1248 |
|
1249 | }
|
1250 | else if (isListening == false && !store._hotUpdating) {
|
1251 |
|
1252 |
|
1253 | if (Array.isArray(debuggerEvents)) {
|
1254 | debuggerEvents.push(event);
|
1255 | }
|
1256 | else {
|
1257 | console.error('🍍 debuggerEvents should be an array. This is most likely an internal Pinia bug.');
|
1258 | }
|
1259 | }
|
1260 | };
|
1261 | }
|
1262 |
|
1263 | let isListening;
|
1264 | let isSyncListening;
|
1265 | let subscriptions = markRaw([]);
|
1266 | let actionSubscriptions = markRaw([]);
|
1267 | let debuggerEvents;
|
1268 | const initialState = pinia.state.value[$id];
|
1269 |
|
1270 |
|
1271 | if (!isOptionsStore && !initialState && (!hot)) {
|
1272 |
|
1273 | if (isVue2) {
|
1274 | set(pinia.state.value, $id, {});
|
1275 | }
|
1276 | else {
|
1277 | pinia.state.value[$id] = {};
|
1278 | }
|
1279 | }
|
1280 | const hotState = ref({});
|
1281 |
|
1282 |
|
1283 | let activeListener;
|
1284 | function $patch(partialStateOrMutator) {
|
1285 | let subscriptionMutation;
|
1286 | isListening = isSyncListening = false;
|
1287 |
|
1288 |
|
1289 | {
|
1290 | debuggerEvents = [];
|
1291 | }
|
1292 | if (typeof partialStateOrMutator === 'function') {
|
1293 | partialStateOrMutator(pinia.state.value[$id]);
|
1294 | subscriptionMutation = {
|
1295 | type: MutationType.patchFunction,
|
1296 | storeId: $id,
|
1297 | events: debuggerEvents,
|
1298 | };
|
1299 | }
|
1300 | else {
|
1301 | mergeReactiveObjects(pinia.state.value[$id], partialStateOrMutator);
|
1302 | subscriptionMutation = {
|
1303 | type: MutationType.patchObject,
|
1304 | payload: partialStateOrMutator,
|
1305 | storeId: $id,
|
1306 | events: debuggerEvents,
|
1307 | };
|
1308 | }
|
1309 | const myListenerId = (activeListener = Symbol());
|
1310 | nextTick().then(() => {
|
1311 | if (activeListener === myListenerId) {
|
1312 | isListening = true;
|
1313 | }
|
1314 | });
|
1315 | isSyncListening = true;
|
1316 |
|
1317 | triggerSubscriptions(subscriptions, subscriptionMutation, pinia.state.value[$id]);
|
1318 | }
|
1319 |
|
1320 | const $reset = () => {
|
1321 | throw new Error(`🍍: Store "${$id}" is built using the setup syntax and does not implement $reset().`);
|
1322 | }
|
1323 | ;
|
1324 | function $dispose() {
|
1325 | scope.stop();
|
1326 | subscriptions = [];
|
1327 | actionSubscriptions = [];
|
1328 | pinia._s.delete($id);
|
1329 | }
|
1330 | |
1331 |
|
1332 |
|
1333 |
|
1334 |
|
1335 |
|
1336 |
|
1337 | function wrapAction(name, action) {
|
1338 | return function () {
|
1339 | setActivePinia(pinia);
|
1340 | const args = Array.from(arguments);
|
1341 | const afterCallbackList = [];
|
1342 | const onErrorCallbackList = [];
|
1343 | function after(callback) {
|
1344 | afterCallbackList.push(callback);
|
1345 | }
|
1346 | function onError(callback) {
|
1347 | onErrorCallbackList.push(callback);
|
1348 | }
|
1349 |
|
1350 | triggerSubscriptions(actionSubscriptions, {
|
1351 | args,
|
1352 | name,
|
1353 | store,
|
1354 | after,
|
1355 | onError,
|
1356 | });
|
1357 | let ret;
|
1358 | try {
|
1359 | ret = action.apply(this && this.$id === $id ? this : store, args);
|
1360 |
|
1361 | }
|
1362 | catch (error) {
|
1363 | triggerSubscriptions(onErrorCallbackList, error);
|
1364 | throw error;
|
1365 | }
|
1366 | if (ret instanceof Promise) {
|
1367 | return ret
|
1368 | .then((value) => {
|
1369 | triggerSubscriptions(afterCallbackList, value);
|
1370 | return value;
|
1371 | })
|
1372 | .catch((error) => {
|
1373 | triggerSubscriptions(onErrorCallbackList, error);
|
1374 | return Promise.reject(error);
|
1375 | });
|
1376 | }
|
1377 |
|
1378 | triggerSubscriptions(afterCallbackList, ret);
|
1379 | return ret;
|
1380 | };
|
1381 | }
|
1382 | const _hmrPayload = markRaw({
|
1383 | actions: {},
|
1384 | getters: {},
|
1385 | state: [],
|
1386 | hotState,
|
1387 | });
|
1388 | const partialStore = {
|
1389 | _p: pinia,
|
1390 |
|
1391 | $id,
|
1392 | $onAction: addSubscription.bind(null, actionSubscriptions),
|
1393 | $patch,
|
1394 | $reset,
|
1395 | $subscribe(callback, options = {}) {
|
1396 | const removeSubscription = addSubscription(subscriptions, callback, options.detached, () => stopWatcher());
|
1397 | const stopWatcher = scope.run(() => watch(() => pinia.state.value[$id], (state) => {
|
1398 | if (options.flush === 'sync' ? isSyncListening : isListening) {
|
1399 | callback({
|
1400 | storeId: $id,
|
1401 | type: MutationType.direct,
|
1402 | events: debuggerEvents,
|
1403 | }, state);
|
1404 | }
|
1405 | }, assign({}, $subscribeOptions, options)));
|
1406 | return removeSubscription;
|
1407 | },
|
1408 | $dispose,
|
1409 | };
|
1410 |
|
1411 | if (isVue2) {
|
1412 |
|
1413 | partialStore._r = false;
|
1414 | }
|
1415 | const store = reactive(assign({
|
1416 | _hmrPayload,
|
1417 | _customProperties: markRaw(new Set()),
|
1418 | }, partialStore
|
1419 |
|
1420 |
|
1421 | )
|
1422 | );
|
1423 |
|
1424 |
|
1425 | pinia._s.set($id, store);
|
1426 |
|
1427 | const setupStore = pinia._e.run(() => {
|
1428 | scope = effectScope();
|
1429 | return scope.run(() => setup());
|
1430 | });
|
1431 |
|
1432 | for (const key in setupStore) {
|
1433 | const prop = setupStore[key];
|
1434 | if ((isRef(prop) && !isComputed(prop)) || isReactive(prop)) {
|
1435 |
|
1436 | if (hot) {
|
1437 | set(hotState.value, key, toRef(setupStore, key));
|
1438 | // createOptionStore directly sets the state in pinia.state.value so we
|
1439 | // can just skip that
|
1440 | }
|
1441 | else if (!isOptionsStore) {
|
1442 |
|
1443 | if (initialState && shouldHydrate(prop)) {
|
1444 | if (isRef(prop)) {
|
1445 | prop.value = initialState[key];
|
1446 | }
|
1447 | else {
|
1448 |
|
1449 |
|
1450 | mergeReactiveObjects(prop, initialState[key]);
|
1451 | }
|
1452 | }
|
1453 |
|
1454 |
|
1455 | if (isVue2) {
|
1456 | set(pinia.state.value[$id], key, prop);
|
1457 | }
|
1458 | else {
|
1459 | pinia.state.value[$id][key] = prop;
|
1460 | }
|
1461 | }
|
1462 |
|
1463 | {
|
1464 | _hmrPayload.state.push(key);
|
1465 | }
|
1466 |
|
1467 | }
|
1468 | else if (typeof prop === 'function') {
|
1469 |
|
1470 | const actionValue = hot ? prop : wrapAction(key, prop);
|
1471 |
|
1472 |
|
1473 |
|
1474 | if (isVue2) {
|
1475 | set(setupStore, key, actionValue);
|
1476 | }
|
1477 | else {
|
1478 |
|
1479 | setupStore[key] = actionValue;
|
1480 | }
|
1481 |
|
1482 | {
|
1483 | _hmrPayload.actions[key] = prop;
|
1484 | }
|
1485 |
|
1486 |
|
1487 | optionsForPlugin.actions[key] = prop;
|
1488 | }
|
1489 | else {
|
1490 |
|
1491 | if (isComputed(prop)) {
|
1492 | _hmrPayload.getters[key] = isOptionsStore
|
1493 | ?
|
1494 | options.getters[key]
|
1495 | : prop;
|
1496 | if (IS_CLIENT) {
|
1497 | const getters = setupStore._getters ||
|
1498 |
|
1499 | (setupStore._getters = markRaw([]));
|
1500 | getters.push(key);
|
1501 | }
|
1502 | }
|
1503 | }
|
1504 | }
|
1505 |
|
1506 |
|
1507 | if (isVue2) {
|
1508 | Object.keys(setupStore).forEach((key) => {
|
1509 | set(store, key, setupStore[key]);
|
1510 | });
|
1511 | }
|
1512 | else {
|
1513 | assign(store, setupStore);
|
1514 |
|
1515 |
|
1516 | assign(toRaw(store), setupStore);
|
1517 | }
|
1518 |
|
1519 |
|
1520 |
|
1521 | Object.defineProperty(store, '$state', {
|
1522 | get: () => (hot ? hotState.value : pinia.state.value[$id]),
|
1523 | set: (state) => {
|
1524 |
|
1525 | if (hot) {
|
1526 | throw new Error('cannot set hotState');
|
1527 | }
|
1528 | $patch(($state) => {
|
1529 | assign($state, state);
|
1530 | });
|
1531 | },
|
1532 | });
|
1533 |
|
1534 |
|
1535 | {
|
1536 | store._hotUpdate = markRaw((newStore) => {
|
1537 | store._hotUpdating = true;
|
1538 | newStore._hmrPayload.state.forEach((stateKey) => {
|
1539 | if (stateKey in store.$state) {
|
1540 | const newStateTarget = newStore.$state[stateKey];
|
1541 | const oldStateSource = store.$state[stateKey];
|
1542 | if (typeof newStateTarget === 'object' &&
|
1543 | isPlainObject(newStateTarget) &&
|
1544 | isPlainObject(oldStateSource)) {
|
1545 | patchObject(newStateTarget, oldStateSource);
|
1546 | }
|
1547 | else {
|
1548 |
|
1549 | newStore.$state[stateKey] = oldStateSource;
|
1550 | }
|
1551 | }
|
1552 |
|
1553 |
|
1554 | set(store, stateKey, toRef(newStore.$state, stateKey));
|
1555 | });
|
1556 | // remove deleted state properties
|
1557 | Object.keys(store.$state).forEach((stateKey) => {
|
1558 | if (!(stateKey in newStore.$state)) {
|
1559 | del(store, stateKey);
|
1560 | }
|
1561 | });
|
1562 |
|
1563 | isListening = false;
|
1564 | isSyncListening = false;
|
1565 | pinia.state.value[$id] = toRef(newStore._hmrPayload, 'hotState');
|
1566 | isSyncListening = true;
|
1567 | nextTick().then(() => {
|
1568 | isListening = true;
|
1569 | });
|
1570 | for (const actionName in newStore._hmrPayload.actions) {
|
1571 | const action = newStore[actionName];
|
1572 | set(store, actionName, wrapAction(actionName, action));
|
1573 | }
|
1574 | // TODO: does this work in both setup and option store?
|
1575 | for (const getterName in newStore._hmrPayload.getters) {
|
1576 | const getter = newStore._hmrPayload.getters[getterName];
|
1577 | const getterValue = isOptionsStore
|
1578 | ?
|
1579 | computed(() => {
|
1580 | setActivePinia(pinia);
|
1581 | return getter.call(store, store);
|
1582 | })
|
1583 | : getter;
|
1584 | set(store, getterName, getterValue);
|
1585 | }
|
1586 | // remove deleted getters
|
1587 | Object.keys(store._hmrPayload.getters).forEach((key) => {
|
1588 | if (!(key in newStore._hmrPayload.getters)) {
|
1589 | del(store, key);
|
1590 | }
|
1591 | });
|
1592 |
|
1593 | Object.keys(store._hmrPayload.actions).forEach((key) => {
|
1594 | if (!(key in newStore._hmrPayload.actions)) {
|
1595 | del(store, key);
|
1596 | }
|
1597 | });
|
1598 |
|
1599 | store._hmrPayload = newStore._hmrPayload;
|
1600 | store._getters = newStore._getters;
|
1601 | store._hotUpdating = false;
|
1602 | });
|
1603 | }
|
1604 | if (USE_DEVTOOLS) {
|
1605 | const nonEnumerable = {
|
1606 | writable: true,
|
1607 | configurable: true,
|
1608 |
|
1609 | enumerable: false,
|
1610 | };
|
1611 | ['_p', '_hmrPayload', '_getters', '_customProperties'].forEach((p) => {
|
1612 | Object.defineProperty(store, p, {
|
1613 | value: store[p],
|
1614 | ...nonEnumerable,
|
1615 | });
|
1616 | });
|
1617 | }
|
1618 |
|
1619 | if (isVue2) {
|
1620 |
|
1621 | store._r = true;
|
1622 | }
|
1623 |
|
1624 | pinia._p.forEach((extender) => {
|
1625 |
|
1626 | if (USE_DEVTOOLS) {
|
1627 | const extensions = scope.run(() => extender({
|
1628 | store,
|
1629 | app: pinia._a,
|
1630 | pinia,
|
1631 | options: optionsForPlugin,
|
1632 | }));
|
1633 | Object.keys(extensions || {}).forEach((key) => store._customProperties.add(key));
|
1634 | assign(store, extensions);
|
1635 | }
|
1636 | else {
|
1637 | assign(store, scope.run(() => extender({
|
1638 | store,
|
1639 | app: pinia._a,
|
1640 | pinia,
|
1641 | options: optionsForPlugin,
|
1642 | })));
|
1643 | }
|
1644 | });
|
1645 | if (store.$state &&
|
1646 | typeof store.$state === 'object' &&
|
1647 | typeof store.$state.constructor === 'function' &&
|
1648 | !store.$state.constructor.toString().includes('[native code]')) {
|
1649 | console.warn(`[🍍]: The "state" must be a plain object. It cannot be\n` +
|
1650 | `\tstate: () => new MyClass()\n` +
|
1651 | `Found in store "${store.$id}".`);
|
1652 | }
|
1653 |
|
1654 | if (initialState &&
|
1655 | isOptionsStore &&
|
1656 | options.hydrate) {
|
1657 | options.hydrate(store.$state, initialState);
|
1658 | }
|
1659 | isListening = true;
|
1660 | isSyncListening = true;
|
1661 | return store;
|
1662 | }
|
1663 | function defineStore(
|
1664 | // TODO: add proper types from above
|
1665 | idOrOptions, setup, setupOptions) {
|
1666 | let id;
|
1667 | let options;
|
1668 | const isSetupStore = typeof setup === 'function';
|
1669 | if (typeof idOrOptions === 'string') {
|
1670 | id = idOrOptions;
|
1671 |
|
1672 | options = isSetupStore ? setupOptions : setup;
|
1673 | }
|
1674 | else {
|
1675 | options = idOrOptions;
|
1676 | id = idOrOptions.id;
|
1677 | }
|
1678 | function useStore(pinia, hot) {
|
1679 | const currentInstance = getCurrentInstance();
|
1680 | pinia =
|
1681 |
|
1682 |
|
1683 | (pinia) ||
|
1684 | (currentInstance && inject(piniaSymbol));
|
1685 | if (pinia)
|
1686 | setActivePinia(pinia);
|
1687 | if (!activePinia) {
|
1688 | throw new Error(`[🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia?\n` +
|
1689 | `\tconst pinia = createPinia()\n` +
|
1690 | `\tapp.use(pinia)\n` +
|
1691 | `This will fail in production.`);
|
1692 | }
|
1693 | pinia = activePinia;
|
1694 | if (!pinia._s.has(id)) {
|
1695 |
|
1696 | if (isSetupStore) {
|
1697 | createSetupStore(id, setup, options, pinia);
|
1698 | }
|
1699 | else {
|
1700 | createOptionsStore(id, options, pinia);
|
1701 | }
|
1702 |
|
1703 | {
|
1704 |
|
1705 | useStore._pinia = pinia;
|
1706 | }
|
1707 | }
|
1708 | const store = pinia._s.get(id);
|
1709 | if (hot) {
|
1710 | const hotId = '__hot:' + id;
|
1711 | const newStore = isSetupStore
|
1712 | ? createSetupStore(hotId, setup, options, pinia, true)
|
1713 | : createOptionsStore(hotId, assign({}, options), pinia, true);
|
1714 | hot._hotUpdate(newStore);
|
1715 |
|
1716 | delete pinia.state.value[hotId];
|
1717 | pinia._s.delete(hotId);
|
1718 | }
|
1719 |
|
1720 | if (IS_CLIENT &&
|
1721 | currentInstance &&
|
1722 | currentInstance.proxy &&
|
1723 |
|
1724 | !hot) {
|
1725 | const vm = currentInstance.proxy;
|
1726 | const cache = '_pStores' in vm ? vm._pStores : (vm._pStores = {});
|
1727 | cache[id] = store;
|
1728 | }
|
1729 |
|
1730 | return store;
|
1731 | }
|
1732 | useStore.$id = id;
|
1733 | return useStore;
|
1734 | }
|
1735 |
|
1736 | let mapStoreSuffix = 'Store';
|
1737 |
|
1738 |
|
1739 |
|
1740 |
|
1741 |
|
1742 |
|
1743 |
|
1744 | function setMapStoreSuffix(suffix // could be 'Store' but that would be annoying for JS
|
1745 | ) {
|
1746 | mapStoreSuffix = suffix;
|
1747 | }
|
1748 |
|
1749 |
|
1750 |
|
1751 |
|
1752 |
|
1753 |
|
1754 |
|
1755 |
|
1756 |
|
1757 |
|
1758 |
|
1759 |
|
1760 |
|
1761 |
|
1762 |
|
1763 |
|
1764 |
|
1765 |
|
1766 |
|
1767 |
|
1768 |
|
1769 |
|
1770 | function mapStores(...stores) {
|
1771 | if (Array.isArray(stores[0])) {
|
1772 | console.warn(`[🍍]: Directly pass all stores to "mapStores()" without putting them in an array:\n` +
|
1773 | `Replace\n` +
|
1774 | `\tmapStores([useAuthStore, useCartStore])\n` +
|
1775 | `with\n` +
|
1776 | `\tmapStores(useAuthStore, useCartStore)\n` +
|
1777 | `This will fail in production if not fixed.`);
|
1778 | stores = stores[0];
|
1779 | }
|
1780 | return stores.reduce((reduced, useStore) => {
|
1781 |
|
1782 | reduced[useStore.$id + mapStoreSuffix] = function () {
|
1783 | return useStore(this.$pinia);
|
1784 | };
|
1785 | return reduced;
|
1786 | }, {});
|
1787 | }
|
1788 |
|
1789 |
|
1790 |
|
1791 |
|
1792 |
|
1793 |
|
1794 |
|
1795 |
|
1796 | function mapState(useStore, keysOrMapper) {
|
1797 | return Array.isArray(keysOrMapper)
|
1798 | ? keysOrMapper.reduce((reduced, key) => {
|
1799 | reduced[key] = function () {
|
1800 | return useStore(this.$pinia)[key];
|
1801 | };
|
1802 | return reduced;
|
1803 | }, {})
|
1804 | : Object.keys(keysOrMapper).reduce((reduced, key) => {
|
1805 |
|
1806 | reduced[key] = function () {
|
1807 | const store = useStore(this.$pinia);
|
1808 | const storeKey = keysOrMapper[key];
|
1809 |
|
1810 |
|
1811 | return typeof storeKey === 'function'
|
1812 | ? storeKey.call(this, store)
|
1813 | : store[storeKey];
|
1814 | };
|
1815 | return reduced;
|
1816 | }, {});
|
1817 | }
|
1818 |
|
1819 |
|
1820 |
|
1821 |
|
1822 | const mapGetters = mapState;
|
1823 |
|
1824 |
|
1825 |
|
1826 |
|
1827 |
|
1828 |
|
1829 |
|
1830 |
|
1831 | function mapActions(useStore, keysOrMapper) {
|
1832 | return Array.isArray(keysOrMapper)
|
1833 | ? keysOrMapper.reduce((reduced, key) => {
|
1834 |
|
1835 | reduced[key] = function (...args) {
|
1836 | return useStore(this.$pinia)[key](...args);
|
1837 | };
|
1838 | return reduced;
|
1839 | }, {})
|
1840 | : Object.keys(keysOrMapper).reduce((reduced, key) => {
|
1841 |
|
1842 | reduced[key] = function (...args) {
|
1843 | return useStore(this.$pinia)[keysOrMapper[key]](...args);
|
1844 | };
|
1845 | return reduced;
|
1846 | }, {});
|
1847 | }
|
1848 |
|
1849 |
|
1850 |
|
1851 |
|
1852 |
|
1853 |
|
1854 |
|
1855 |
|
1856 | function mapWritableState(useStore, keysOrMapper) {
|
1857 | return Array.isArray(keysOrMapper)
|
1858 | ? keysOrMapper.reduce((reduced, key) => {
|
1859 |
|
1860 | reduced[key] = {
|
1861 | get() {
|
1862 | return useStore(this.$pinia)[key];
|
1863 | },
|
1864 | set(value) {
|
1865 |
|
1866 | return (useStore(this.$pinia)[key] = value);
|
1867 | },
|
1868 | };
|
1869 | return reduced;
|
1870 | }, {})
|
1871 | : Object.keys(keysOrMapper).reduce((reduced, key) => {
|
1872 |
|
1873 | reduced[key] = {
|
1874 | get() {
|
1875 | return useStore(this.$pinia)[keysOrMapper[key]];
|
1876 | },
|
1877 | set(value) {
|
1878 |
|
1879 | return (useStore(this.$pinia)[keysOrMapper[key]] = value);
|
1880 | },
|
1881 | };
|
1882 | return reduced;
|
1883 | }, {});
|
1884 | }
|
1885 |
|
1886 |
|
1887 |
|
1888 |
|
1889 |
|
1890 |
|
1891 |
|
1892 |
|
1893 |
|
1894 | function storeToRefs(store) {
|
1895 |
|
1896 |
|
1897 | if (isVue2) {
|
1898 |
|
1899 | return toRefs(store);
|
1900 | }
|
1901 | else {
|
1902 | store = toRaw(store);
|
1903 | const refs = {};
|
1904 | for (const key in store) {
|
1905 | const value = store[key];
|
1906 | if (isRef(value) || isReactive(value)) {
|
1907 |
|
1908 | refs[key] =
|
1909 |
|
1910 | toRef(store, key);
|
1911 | }
|
1912 | }
|
1913 | return refs;
|
1914 | }
|
1915 | }
|
1916 |
|
1917 |
|
1918 |
|
1919 |
|
1920 |
|
1921 |
|
1922 |
|
1923 |
|
1924 |
|
1925 |
|
1926 |
|
1927 |
|
1928 |
|
1929 |
|
1930 |
|
1931 |
|
1932 |
|
1933 |
|
1934 |
|
1935 |
|
1936 |
|
1937 |
|
1938 |
|
1939 | const PiniaVuePlugin = function (_Vue) {
|
1940 |
|
1941 |
|
1942 | _Vue.mixin({
|
1943 | beforeCreate() {
|
1944 | const options = this.$options;
|
1945 | if (options.pinia) {
|
1946 | const pinia = options.pinia;
|
1947 |
|
1948 |
|
1949 | if (!this._provided) {
|
1950 | const provideCache = {};
|
1951 | Object.defineProperty(this, '_provided', {
|
1952 | get: () => provideCache,
|
1953 | set: (v) => Object.assign(provideCache, v),
|
1954 | });
|
1955 | }
|
1956 | this._provided[piniaSymbol] = pinia;
|
1957 | // propagate the pinia instance in an SSR friendly way
|
1958 | // avoid adding it to nuxt twice
|
1959 | /* istanbul ignore else */
|
1960 | if (!this.$pinia) {
|
1961 | this.$pinia = pinia;
|
1962 | }
|
1963 | pinia._a = this;
|
1964 | if (IS_CLIENT) {
|
1965 |
|
1966 |
|
1967 | setActivePinia(pinia);
|
1968 | }
|
1969 | if (USE_DEVTOOLS) {
|
1970 | registerPiniaDevtools(pinia._a, pinia);
|
1971 | }
|
1972 | }
|
1973 | else if (!this.$pinia && options.parent && options.parent.$pinia) {
|
1974 | this.$pinia = options.parent.$pinia;
|
1975 | }
|
1976 | },
|
1977 | destroyed() {
|
1978 | delete this._pStores;
|
1979 | },
|
1980 | });
|
1981 | };
|
1982 |
|
1983 | export { MutationType, PiniaVuePlugin, acceptHMRUpdate, createPinia, defineStore, getActivePinia, mapActions, mapGetters, mapState, mapStores, mapWritableState, setActivePinia, setMapStoreSuffix, skipHydrate, storeToRefs };
|