unknown
2 weeks ago
89 changed files with 12906 additions and 106 deletions
-
3config/api.js
-
4config/request.js
-
3main.js
-
2manifest.json
-
15node_modules/.bin/vue-demi-fix
-
17node_modules/.bin/vue-demi-fix.cmd
-
18node_modules/.bin/vue-demi-fix.ps1
-
15node_modules/.bin/vue-demi-switch
-
17node_modules/.bin/vue-demi-switch.cmd
-
18node_modules/.bin/vue-demi-switch.ps1
-
2node_modules/@vue/devtools-api/lib/cjs/api/api.js
-
2node_modules/@vue/devtools-api/lib/cjs/api/app.js
-
2node_modules/@vue/devtools-api/lib/cjs/api/component.js
-
2node_modules/@vue/devtools-api/lib/cjs/api/context.js
-
2node_modules/@vue/devtools-api/lib/cjs/api/hooks.js
-
22node_modules/@vue/devtools-api/lib/cjs/api/index.js
-
2node_modules/@vue/devtools-api/lib/cjs/api/util.js
-
5node_modules/@vue/devtools-api/lib/cjs/const.js
-
17node_modules/@vue/devtools-api/lib/cjs/env.js
-
45node_modules/@vue/devtools-api/lib/cjs/index.js
-
2node_modules/@vue/devtools-api/lib/cjs/plugin.js
-
111node_modules/@vue/devtools-api/lib/cjs/proxy.js
-
28node_modules/@vue/devtools-api/lib/cjs/time.js
-
108node_modules/@vue/devtools-api/lib/esm/api/api.d.ts
-
1node_modules/@vue/devtools-api/lib/esm/api/api.js
-
1node_modules/@vue/devtools-api/lib/esm/api/app.d.ts
-
1node_modules/@vue/devtools-api/lib/esm/api/app.js
-
78node_modules/@vue/devtools-api/lib/esm/api/component.d.ts
-
1node_modules/@vue/devtools-api/lib/esm/api/component.js
-
5node_modules/@vue/devtools-api/lib/esm/api/context.d.ts
-
1node_modules/@vue/devtools-api/lib/esm/api/context.js
-
180node_modules/@vue/devtools-api/lib/esm/api/hooks.d.ts
-
1node_modules/@vue/devtools-api/lib/esm/api/hooks.js
-
6node_modules/@vue/devtools-api/lib/esm/api/index.d.ts
-
6node_modules/@vue/devtools-api/lib/esm/api/index.js
-
4node_modules/@vue/devtools-api/lib/esm/api/util.d.ts
-
1node_modules/@vue/devtools-api/lib/esm/api/util.js
-
2node_modules/@vue/devtools-api/lib/esm/const.d.ts
-
2node_modules/@vue/devtools-api/lib/esm/const.js
-
15node_modules/@vue/devtools-api/lib/esm/env.d.ts
-
12node_modules/@vue/devtools-api/lib/esm/env.js
-
18node_modules/@vue/devtools-api/lib/esm/index.d.ts
-
27node_modules/@vue/devtools-api/lib/esm/index.js
-
47node_modules/@vue/devtools-api/lib/esm/plugin.d.ts
-
1node_modules/@vue/devtools-api/lib/esm/plugin.js
-
20node_modules/@vue/devtools-api/lib/esm/proxy.d.ts
-
107node_modules/@vue/devtools-api/lib/esm/proxy.js
-
2node_modules/@vue/devtools-api/lib/esm/time.d.ts
-
23node_modules/@vue/devtools-api/lib/esm/time.js
-
67node_modules/@vue/devtools-api/package.json
-
21node_modules/pinia/LICENSE
-
24node_modules/pinia/README.md
-
2059node_modules/pinia/dist/pinia.cjs
-
1064node_modules/pinia/dist/pinia.d.ts
-
2035node_modules/pinia/dist/pinia.esm-browser.js
-
2221node_modules/pinia/dist/pinia.iife.js
-
6node_modules/pinia/dist/pinia.iife.prod.js
-
2043node_modules/pinia/dist/pinia.mjs
-
844node_modules/pinia/dist/pinia.prod.cjs
-
7node_modules/pinia/index.cjs
-
7node_modules/pinia/index.js
-
126node_modules/pinia/package.json
-
21node_modules/vue-demi/LICENSE
-
229node_modules/vue-demi/README.md
-
3node_modules/vue-demi/bin/vue-demi-fix.js
-
3node_modules/vue-demi/bin/vue-demi-switch.js
-
29node_modules/vue-demi/lib/index.cjs
-
22node_modules/vue-demi/lib/index.d.ts
-
126node_modules/vue-demi/lib/index.iife.js
-
34node_modules/vue-demi/lib/index.mjs
-
60node_modules/vue-demi/lib/v2.7/index.cjs
-
38node_modules/vue-demi/lib/v2.7/index.d.ts
-
80node_modules/vue-demi/lib/v2.7/index.mjs
-
34node_modules/vue-demi/lib/v2/index.cjs
-
33node_modules/vue-demi/lib/v2/index.d.ts
-
49node_modules/vue-demi/lib/v2/index.mjs
-
29node_modules/vue-demi/lib/v3/index.cjs
-
22node_modules/vue-demi/lib/v3/index.d.ts
-
34node_modules/vue-demi/lib/v3/index.mjs
-
83node_modules/vue-demi/package.json
-
19node_modules/vue-demi/scripts/postinstall.js
-
18node_modules/vue-demi/scripts/switch-cli.js
-
62node_modules/vue-demi/scripts/utils.js
-
33package-lock.json
-
12package.json
-
358pages/exercises/brushQuestions/brushQuestions.vue
-
6pages/index/index.vue
-
9store/index.js
-
18store/modules/car.js
@ -0,0 +1,15 @@ |
|||
#!/bin/sh |
|||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") |
|||
|
|||
case `uname` in |
|||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; |
|||
esac |
|||
|
|||
if [ -x "$basedir/node" ]; then |
|||
"$basedir/node" "$basedir/../vue-demi/bin/vue-demi-fix.js" "$@" |
|||
ret=$? |
|||
else |
|||
node "$basedir/../vue-demi/bin/vue-demi-fix.js" "$@" |
|||
ret=$? |
|||
fi |
|||
exit $ret |
@ -0,0 +1,17 @@ |
|||
@ECHO off |
|||
SETLOCAL |
|||
CALL :find_dp0 |
|||
|
|||
IF EXIST "%dp0%\node.exe" ( |
|||
SET "_prog=%dp0%\node.exe" |
|||
) ELSE ( |
|||
SET "_prog=node" |
|||
SET PATHEXT=%PATHEXT:;.JS;=;% |
|||
) |
|||
|
|||
"%_prog%" "%dp0%\..\vue-demi\bin\vue-demi-fix.js" %* |
|||
ENDLOCAL |
|||
EXIT /b %errorlevel% |
|||
:find_dp0 |
|||
SET dp0=%~dp0 |
|||
EXIT /b |
@ -0,0 +1,18 @@ |
|||
#!/usr/bin/env pwsh |
|||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent |
|||
|
|||
$exe="" |
|||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { |
|||
# Fix case when both the Windows and Linux builds of Node |
|||
# are installed in the same directory |
|||
$exe=".exe" |
|||
} |
|||
$ret=0 |
|||
if (Test-Path "$basedir/node$exe") { |
|||
& "$basedir/node$exe" "$basedir/../vue-demi/bin/vue-demi-fix.js" $args |
|||
$ret=$LASTEXITCODE |
|||
} else { |
|||
& "node$exe" "$basedir/../vue-demi/bin/vue-demi-fix.js" $args |
|||
$ret=$LASTEXITCODE |
|||
} |
|||
exit $ret |
@ -0,0 +1,15 @@ |
|||
#!/bin/sh |
|||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") |
|||
|
|||
case `uname` in |
|||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; |
|||
esac |
|||
|
|||
if [ -x "$basedir/node" ]; then |
|||
"$basedir/node" "$basedir/../vue-demi/bin/vue-demi-switch.js" "$@" |
|||
ret=$? |
|||
else |
|||
node "$basedir/../vue-demi/bin/vue-demi-switch.js" "$@" |
|||
ret=$? |
|||
fi |
|||
exit $ret |
@ -0,0 +1,17 @@ |
|||
@ECHO off |
|||
SETLOCAL |
|||
CALL :find_dp0 |
|||
|
|||
IF EXIST "%dp0%\node.exe" ( |
|||
SET "_prog=%dp0%\node.exe" |
|||
) ELSE ( |
|||
SET "_prog=node" |
|||
SET PATHEXT=%PATHEXT:;.JS;=;% |
|||
) |
|||
|
|||
"%_prog%" "%dp0%\..\vue-demi\bin\vue-demi-switch.js" %* |
|||
ENDLOCAL |
|||
EXIT /b %errorlevel% |
|||
:find_dp0 |
|||
SET dp0=%~dp0 |
|||
EXIT /b |
@ -0,0 +1,18 @@ |
|||
#!/usr/bin/env pwsh |
|||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent |
|||
|
|||
$exe="" |
|||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { |
|||
# Fix case when both the Windows and Linux builds of Node |
|||
# are installed in the same directory |
|||
$exe=".exe" |
|||
} |
|||
$ret=0 |
|||
if (Test-Path "$basedir/node$exe") { |
|||
& "$basedir/node$exe" "$basedir/../vue-demi/bin/vue-demi-switch.js" $args |
|||
$ret=$LASTEXITCODE |
|||
} else { |
|||
& "node$exe" "$basedir/../vue-demi/bin/vue-demi-switch.js" $args |
|||
$ret=$LASTEXITCODE |
|||
} |
|||
exit $ret |
@ -0,0 +1,2 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
@ -0,0 +1,2 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
@ -0,0 +1,2 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
@ -0,0 +1,2 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
@ -0,0 +1,2 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
@ -0,0 +1,22 @@ |
|||
"use strict"; |
|||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { |
|||
if (k2 === undefined) k2 = k; |
|||
var desc = Object.getOwnPropertyDescriptor(m, k); |
|||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { |
|||
desc = { enumerable: true, get: function() { return m[k]; } }; |
|||
} |
|||
Object.defineProperty(o, k2, desc); |
|||
}) : (function(o, m, k, k2) { |
|||
if (k2 === undefined) k2 = k; |
|||
o[k2] = m[k]; |
|||
})); |
|||
var __exportStar = (this && this.__exportStar) || function(m, exports) { |
|||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); |
|||
}; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
|||
__exportStar(require("./api.js"), exports); |
|||
__exportStar(require("./app.js"), exports); |
|||
__exportStar(require("./component.js"), exports); |
|||
__exportStar(require("./context.js"), exports); |
|||
__exportStar(require("./hooks.js"), exports); |
|||
__exportStar(require("./util.js"), exports); |
@ -0,0 +1,2 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
@ -0,0 +1,5 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
|||
exports.HOOK_PLUGIN_SETTINGS_SET = exports.HOOK_SETUP = void 0; |
|||
exports.HOOK_SETUP = 'devtools-plugin:setup'; |
|||
exports.HOOK_PLUGIN_SETTINGS_SET = 'plugin:settings:set'; |
@ -0,0 +1,17 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
|||
exports.isProxyAvailable = exports.getTarget = exports.getDevtoolsGlobalHook = void 0; |
|||
function getDevtoolsGlobalHook() { |
|||
return getTarget().__VUE_DEVTOOLS_GLOBAL_HOOK__; |
|||
} |
|||
exports.getDevtoolsGlobalHook = getDevtoolsGlobalHook; |
|||
function getTarget() { |
|||
// @ts-expect-error navigator and windows are not available in all environments
|
|||
return (typeof navigator !== 'undefined' && typeof window !== 'undefined') |
|||
? window |
|||
: typeof globalThis !== 'undefined' |
|||
? globalThis |
|||
: {}; |
|||
} |
|||
exports.getTarget = getTarget; |
|||
exports.isProxyAvailable = typeof Proxy === 'function'; |
@ -0,0 +1,45 @@ |
|||
"use strict"; |
|||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { |
|||
if (k2 === undefined) k2 = k; |
|||
var desc = Object.getOwnPropertyDescriptor(m, k); |
|||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { |
|||
desc = { enumerable: true, get: function() { return m[k]; } }; |
|||
} |
|||
Object.defineProperty(o, k2, desc); |
|||
}) : (function(o, m, k, k2) { |
|||
if (k2 === undefined) k2 = k; |
|||
o[k2] = m[k]; |
|||
})); |
|||
var __exportStar = (this && this.__exportStar) || function(m, exports) { |
|||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); |
|||
}; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
|||
exports.setupDevtoolsPlugin = void 0; |
|||
const env_js_1 = require("./env.js"); |
|||
const const_js_1 = require("./const.js"); |
|||
const proxy_js_1 = require("./proxy.js"); |
|||
__exportStar(require("./api/index.js"), exports); |
|||
__exportStar(require("./plugin.js"), exports); |
|||
__exportStar(require("./time.js"), exports); |
|||
function setupDevtoolsPlugin(pluginDescriptor, setupFn) { |
|||
const descriptor = pluginDescriptor; |
|||
const target = (0, env_js_1.getTarget)(); |
|||
const hook = (0, env_js_1.getDevtoolsGlobalHook)(); |
|||
const enableProxy = env_js_1.isProxyAvailable && descriptor.enableEarlyProxy; |
|||
if (hook && (target.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__ || !enableProxy)) { |
|||
hook.emit(const_js_1.HOOK_SETUP, pluginDescriptor, setupFn); |
|||
} |
|||
else { |
|||
const proxy = enableProxy ? new proxy_js_1.ApiProxy(descriptor, hook) : null; |
|||
const list = target.__VUE_DEVTOOLS_PLUGINS__ = target.__VUE_DEVTOOLS_PLUGINS__ || []; |
|||
list.push({ |
|||
pluginDescriptor: descriptor, |
|||
setupFn, |
|||
proxy, |
|||
}); |
|||
if (proxy) { |
|||
setupFn(proxy.proxiedTarget); |
|||
} |
|||
} |
|||
} |
|||
exports.setupDevtoolsPlugin = setupDevtoolsPlugin; |
@ -0,0 +1,2 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
@ -0,0 +1,111 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
|||
exports.ApiProxy = void 0; |
|||
const const_js_1 = require("./const.js"); |
|||
const time_js_1 = require("./time.js"); |
|||
class ApiProxy { |
|||
constructor(plugin, hook) { |
|||
this.target = null; |
|||
this.targetQueue = []; |
|||
this.onQueue = []; |
|||
this.plugin = plugin; |
|||
this.hook = hook; |
|||
const defaultSettings = {}; |
|||
if (plugin.settings) { |
|||
for (const id in plugin.settings) { |
|||
const item = plugin.settings[id]; |
|||
defaultSettings[id] = item.defaultValue; |
|||
} |
|||
} |
|||
const localSettingsSaveId = `__vue-devtools-plugin-settings__${plugin.id}`; |
|||
let currentSettings = Object.assign({}, defaultSettings); |
|||
try { |
|||
const raw = localStorage.getItem(localSettingsSaveId); |
|||
const data = JSON.parse(raw); |
|||
Object.assign(currentSettings, data); |
|||
} |
|||
catch (e) { |
|||
// noop
|
|||
} |
|||
this.fallbacks = { |
|||
getSettings() { |
|||
return currentSettings; |
|||
}, |
|||
setSettings(value) { |
|||
try { |
|||
localStorage.setItem(localSettingsSaveId, JSON.stringify(value)); |
|||
} |
|||
catch (e) { |
|||
// noop
|
|||
} |
|||
currentSettings = value; |
|||
}, |
|||
now() { |
|||
return (0, time_js_1.now)(); |
|||
}, |
|||
}; |
|||
if (hook) { |
|||
hook.on(const_js_1.HOOK_PLUGIN_SETTINGS_SET, (pluginId, value) => { |
|||
if (pluginId === this.plugin.id) { |
|||
this.fallbacks.setSettings(value); |
|||
} |
|||
}); |
|||
} |
|||
this.proxiedOn = new Proxy({}, { |
|||
get: (_target, prop) => { |
|||
if (this.target) { |
|||
return this.target.on[prop]; |
|||
} |
|||
else { |
|||
return (...args) => { |
|||
this.onQueue.push({ |
|||
method: prop, |
|||
args, |
|||
}); |
|||
}; |
|||
} |
|||
}, |
|||
}); |
|||
this.proxiedTarget = new Proxy({}, { |
|||
get: (_target, prop) => { |
|||
if (this.target) { |
|||
return this.target[prop]; |
|||
} |
|||
else if (prop === 'on') { |
|||
return this.proxiedOn; |
|||
} |
|||
else if (Object.keys(this.fallbacks).includes(prop)) { |
|||
return (...args) => { |
|||
this.targetQueue.push({ |
|||
method: prop, |
|||
args, |
|||
resolve: () => { }, |
|||
}); |
|||
return this.fallbacks[prop](...args); |
|||
}; |
|||
} |
|||
else { |
|||
return (...args) => { |
|||
return new Promise((resolve) => { |
|||
this.targetQueue.push({ |
|||
method: prop, |
|||
args, |
|||
resolve, |
|||
}); |
|||
}); |
|||
}; |
|||
} |
|||
}, |
|||
}); |
|||
} |
|||
async setRealTarget(target) { |
|||
this.target = target; |
|||
for (const item of this.onQueue) { |
|||
this.target.on[item.method](...item.args); |
|||
} |
|||
for (const item of this.targetQueue) { |
|||
item.resolve(await this.target[item.method](...item.args)); |
|||
} |
|||
} |
|||
} |
|||
exports.ApiProxy = ApiProxy; |
@ -0,0 +1,28 @@ |
|||
"use strict"; |
|||
Object.defineProperty(exports, "__esModule", { value: true }); |
|||
exports.now = exports.isPerformanceSupported = void 0; |
|||
let supported; |
|||
let perf; |
|||
function isPerformanceSupported() { |
|||
var _a; |
|||
if (supported !== undefined) { |
|||
return supported; |
|||
} |
|||
if (typeof window !== 'undefined' && window.performance) { |
|||
supported = true; |
|||
perf = window.performance; |
|||
} |
|||
else if (typeof globalThis !== 'undefined' && ((_a = globalThis.perf_hooks) === null || _a === void 0 ? void 0 : _a.performance)) { |
|||
supported = true; |
|||
perf = globalThis.perf_hooks.performance; |
|||
} |
|||
else { |
|||
supported = false; |
|||
} |
|||
return supported; |
|||
} |
|||
exports.isPerformanceSupported = isPerformanceSupported; |
|||
function now() { |
|||
return isPerformanceSupported() ? perf.now() : Date.now(); |
|||
} |
|||
exports.now = now; |
@ -0,0 +1,108 @@ |
|||
import type { ComponentBounds, Hookable } from './hooks.js'; |
|||
import type { Context } from './context.js'; |
|||
import type { ComponentInstance, ComponentState, StateBase } from './component.js'; |
|||
import type { App } from './app.js'; |
|||
import type { ID } from './util.js'; |
|||
export interface DevtoolsPluginApi<TSettings> { |
|||
on: Hookable<Context>; |
|||
notifyComponentUpdate: (instance?: ComponentInstance) => void; |
|||
addTimelineLayer: (options: TimelineLayerOptions) => void; |
|||
addTimelineEvent: (options: TimelineEventOptions) => void; |
|||
addInspector: (options: CustomInspectorOptions) => void; |
|||
sendInspectorTree: (inspectorId: string) => void; |
|||
sendInspectorState: (inspectorId: string) => void; |
|||
selectInspectorNode: (inspectorId: string, nodeId: string) => void; |
|||
getComponentBounds: (instance: ComponentInstance) => Promise<ComponentBounds>; |
|||
getComponentName: (instance: ComponentInstance) => Promise<string>; |
|||
getComponentInstances: (app: App) => Promise<ComponentInstance[]>; |
|||
highlightElement: (instance: ComponentInstance) => void; |
|||
unhighlightElement: () => void; |
|||
getSettings: (pluginId?: string) => TSettings; |
|||
now: () => number; |
|||
/** |
|||
* @private |
|||
*/ |
|||
setSettings: (values: TSettings) => void; |
|||
} |
|||
export interface AppRecord { |
|||
id: string; |
|||
name: string; |
|||
instanceMap: Map<string, ComponentInstance>; |
|||
rootInstance: ComponentInstance; |
|||
} |
|||
export interface TimelineLayerOptions<TData = any, TMeta = any> { |
|||
id: string; |
|||
label: string; |
|||
color: number; |
|||
skipScreenshots?: boolean; |
|||
groupsOnly?: boolean; |
|||
ignoreNoDurationGroups?: boolean; |
|||
screenshotOverlayRender?: (event: TimelineEvent<TData, TMeta> & ScreenshotOverlayEvent, ctx: ScreenshotOverlayRenderContext) => ScreenshotOverlayRenderResult | Promise<ScreenshotOverlayRenderResult>; |
|||
} |
|||
export interface ScreenshotOverlayEvent { |
|||
layerId: string; |
|||
renderMeta: any; |
|||
} |
|||
export interface ScreenshotOverlayRenderContext<TData = any, TMeta = any> { |
|||
screenshot: ScreenshotData; |
|||
events: (TimelineEvent<TData, TMeta> & ScreenshotOverlayEvent)[]; |
|||
index: number; |
|||
} |
|||
export type ScreenshotOverlayRenderResult = HTMLElement | string | false; |
|||
export interface ScreenshotData { |
|||
time: number; |
|||
} |
|||
export interface TimelineEventOptions { |
|||
layerId: string; |
|||
event: TimelineEvent; |
|||
all?: boolean; |
|||
} |
|||
export interface TimelineEvent<TData = any, TMeta = any> { |
|||
time: number; |
|||
data: TData; |
|||
logType?: 'default' | 'warning' | 'error'; |
|||
meta?: TMeta; |
|||
groupId?: ID; |
|||
title?: string; |
|||
subtitle?: string; |
|||
} |
|||
export interface TimelineMarkerOptions { |
|||
id: string; |
|||
time: number; |
|||
color: number; |
|||
label: string; |
|||
all?: boolean; |
|||
} |
|||
export interface CustomInspectorOptions { |
|||
id: string; |
|||
label: string; |
|||
icon?: string; |
|||
treeFilterPlaceholder?: string; |
|||
stateFilterPlaceholder?: string; |
|||
noSelectionText?: string; |
|||
actions?: { |
|||
icon: string; |
|||
tooltip?: string; |
|||
action: () => void | Promise<void>; |
|||
}[]; |
|||
nodeActions?: { |
|||
icon: string; |
|||
tooltip?: string; |
|||
action: (nodeId: string) => void | Promise<void>; |
|||
}[]; |
|||
} |
|||
export interface CustomInspectorNode { |
|||
id: string; |
|||
label: string; |
|||
children?: CustomInspectorNode[]; |
|||
tags?: InspectorNodeTag[]; |
|||
} |
|||
export interface InspectorNodeTag { |
|||
label: string; |
|||
textColor: number; |
|||
backgroundColor: number; |
|||
tooltip?: string; |
|||
} |
|||
export interface CustomInspectorState { |
|||
[key: string]: (StateBase | Omit<ComponentState, 'type'>)[]; |
|||
} |
@ -0,0 +1 @@ |
|||
export {}; |
@ -0,0 +1 @@ |
|||
export type App = any; |
@ -0,0 +1 @@ |
|||
export {}; |
@ -0,0 +1,78 @@ |
|||
import type { InspectorNodeTag } from './api.js'; |
|||
import type { ID } from './util.js'; |
|||
export type ComponentInstance = any; |
|||
export interface ComponentTreeNode { |
|||
uid: ID; |
|||
id: string; |
|||
name: string; |
|||
renderKey: string | number; |
|||
inactive: boolean; |
|||
isFragment: boolean; |
|||
hasChildren: boolean; |
|||
children: ComponentTreeNode[]; |
|||
domOrder?: number[]; |
|||
consoleId?: string; |
|||
isRouterView?: boolean; |
|||
macthedRouteSegment?: string; |
|||
tags: InspectorNodeTag[]; |
|||
autoOpen: boolean; |
|||
meta?: any; |
|||
} |
|||
export interface InspectedComponentData { |
|||
id: string; |
|||
name: string; |
|||
file: string; |
|||
state: ComponentState[]; |
|||
functional?: boolean; |
|||
} |
|||
export interface StateBase { |
|||
key: string; |
|||
value: any; |
|||
editable?: boolean; |
|||
objectType?: 'ref' | 'reactive' | 'computed' | 'other'; |
|||
raw?: string; |
|||
} |
|||
export interface ComponentStateBase extends StateBase { |
|||
type: string; |
|||
} |
|||
export interface ComponentPropState extends ComponentStateBase { |
|||
meta?: { |
|||
type: string; |
|||
required: boolean; |
|||
/** Vue 1 only */ |
|||
mode?: 'default' | 'sync' | 'once'; |
|||
}; |
|||
} |
|||
export type ComponentBuiltinCustomStateTypes = 'function' | 'map' | 'set' | 'reference' | 'component' | 'component-definition' | 'router' | 'store'; |
|||
export interface ComponentCustomState extends ComponentStateBase { |
|||
value: CustomState; |
|||
} |
|||
export interface CustomState { |
|||
_custom: { |
|||
type: ComponentBuiltinCustomStateTypes | string; |
|||
objectType?: string; |
|||
display?: string; |
|||
tooltip?: string; |
|||
value?: any; |
|||
abstract?: boolean; |
|||
file?: string; |
|||
uid?: number; |
|||
readOnly?: boolean; |
|||
/** Configure immediate child fields */ |
|||
fields?: { |
|||
abstract?: boolean; |
|||
}; |
|||
id?: any; |
|||
actions?: { |
|||
icon: string; |
|||
tooltip?: string; |
|||
action: () => void | Promise<void>; |
|||
}[]; |
|||
/** internal */ |
|||
_reviveId?: number; |
|||
}; |
|||
} |
|||
export type ComponentState = ComponentStateBase | ComponentPropState | ComponentCustomState; |
|||
export interface ComponentDevtoolsOptions { |
|||
hide?: boolean; |
|||
} |
@ -0,0 +1 @@ |
|||
export {}; |
@ -0,0 +1,5 @@ |
|||
import type { AppRecord } from './api.js'; |
|||
export interface Context { |
|||
currentTab: string; |
|||
currentAppRecord: AppRecord; |
|||
} |
@ -0,0 +1 @@ |
|||
export {}; |
@ -0,0 +1,180 @@ |
|||
import type { ComponentDevtoolsOptions, ComponentInstance, ComponentTreeNode, InspectedComponentData } from './component.js'; |
|||
import type { App } from './app.js'; |
|||
import type { CustomInspectorNode, CustomInspectorState, TimelineEvent } from './api.js'; |
|||
export declare const enum Hooks { |
|||
TRANSFORM_CALL = "transformCall", |
|||
GET_APP_RECORD_NAME = "getAppRecordName", |
|||
GET_APP_ROOT_INSTANCE = "getAppRootInstance", |
|||
REGISTER_APPLICATION = "registerApplication", |
|||
WALK_COMPONENT_TREE = "walkComponentTree", |
|||
VISIT_COMPONENT_TREE = "visitComponentTree", |
|||
WALK_COMPONENT_PARENTS = "walkComponentParents", |
|||
INSPECT_COMPONENT = "inspectComponent", |
|||
GET_COMPONENT_BOUNDS = "getComponentBounds", |
|||
GET_COMPONENT_NAME = "getComponentName", |
|||
GET_COMPONENT_INSTANCES = "getComponentInstances", |
|||
GET_ELEMENT_COMPONENT = "getElementComponent", |
|||
GET_COMPONENT_ROOT_ELEMENTS = "getComponentRootElements", |
|||
EDIT_COMPONENT_STATE = "editComponentState", |
|||
GET_COMPONENT_DEVTOOLS_OPTIONS = "getAppDevtoolsOptions", |
|||
GET_COMPONENT_RENDER_CODE = "getComponentRenderCode", |
|||
INSPECT_TIMELINE_EVENT = "inspectTimelineEvent", |
|||
TIMELINE_CLEARED = "timelineCleared", |
|||
GET_INSPECTOR_TREE = "getInspectorTree", |
|||
GET_INSPECTOR_STATE = "getInspectorState", |
|||
EDIT_INSPECTOR_STATE = "editInspectorState", |
|||
SET_PLUGIN_SETTINGS = "setPluginSettings" |
|||
} |
|||
export interface ComponentBounds { |
|||
left: number; |
|||
top: number; |
|||
width: number; |
|||
height: number; |
|||
} |
|||
export interface HookPayloads { |
|||
[Hooks.TRANSFORM_CALL]: { |
|||
callName: string; |
|||
inArgs: any[]; |
|||
outArgs: any[]; |
|||
}; |
|||
[Hooks.GET_APP_RECORD_NAME]: { |
|||
app: App; |
|||
name: string; |
|||
}; |
|||
[Hooks.GET_APP_ROOT_INSTANCE]: { |
|||
app: App; |
|||
root: ComponentInstance; |
|||
}; |
|||
[Hooks.REGISTER_APPLICATION]: { |
|||
app: App; |
|||
}; |
|||
[Hooks.WALK_COMPONENT_TREE]: { |
|||
componentInstance: ComponentInstance; |
|||
componentTreeData: ComponentTreeNode[]; |
|||
maxDepth: number; |
|||
filter: string; |
|||
recursively: boolean; |
|||
}; |
|||
[Hooks.VISIT_COMPONENT_TREE]: { |
|||
app: App; |
|||
componentInstance: ComponentInstance; |
|||
treeNode: ComponentTreeNode; |
|||
filter: string; |
|||
}; |
|||
[Hooks.WALK_COMPONENT_PARENTS]: { |
|||
componentInstance: ComponentInstance; |
|||
parentInstances: ComponentInstance[]; |
|||
}; |
|||
[Hooks.INSPECT_COMPONENT]: { |
|||
app: App; |
|||
componentInstance: ComponentInstance; |
|||
instanceData: InspectedComponentData; |
|||
}; |
|||
[Hooks.GET_COMPONENT_BOUNDS]: { |
|||
componentInstance: ComponentInstance; |
|||
bounds: ComponentBounds; |
|||
}; |
|||
[Hooks.GET_COMPONENT_NAME]: { |
|||
componentInstance: ComponentInstance; |
|||
name: string; |
|||
}; |
|||
[Hooks.GET_COMPONENT_INSTANCES]: { |
|||
app: App; |
|||
componentInstances: ComponentInstance[]; |
|||
}; |
|||
[Hooks.GET_ELEMENT_COMPONENT]: { |
|||
element: HTMLElement | any; |
|||
componentInstance: ComponentInstance; |
|||
}; |
|||
[Hooks.GET_COMPONENT_ROOT_ELEMENTS]: { |
|||
componentInstance: ComponentInstance; |
|||
rootElements: (HTMLElement | any)[]; |
|||
}; |
|||
[Hooks.EDIT_COMPONENT_STATE]: { |
|||
app: App; |
|||
componentInstance: ComponentInstance; |
|||
path: string[]; |
|||
type: string; |
|||
state: EditStatePayload; |
|||
set: (object: any, path?: string | (string[]), value?: any, cb?: (object: any, field: string, value: any) => void) => void; |
|||
}; |
|||
[Hooks.GET_COMPONENT_DEVTOOLS_OPTIONS]: { |
|||
componentInstance: ComponentInstance; |
|||
options: ComponentDevtoolsOptions; |
|||
}; |
|||
[Hooks.GET_COMPONENT_RENDER_CODE]: { |
|||
componentInstance: ComponentInstance; |
|||
code: string; |
|||
}; |
|||
[Hooks.INSPECT_TIMELINE_EVENT]: { |
|||
app: App; |
|||
layerId: string; |
|||
event: TimelineEvent; |
|||
all?: boolean; |
|||
data: any; |
|||
}; |
|||
[Hooks.TIMELINE_CLEARED]: Record<string, never>; |
|||
[Hooks.GET_INSPECTOR_TREE]: { |
|||
app: App; |
|||
inspectorId: string; |
|||
filter: string; |
|||
rootNodes: CustomInspectorNode[]; |
|||
}; |
|||
[Hooks.GET_INSPECTOR_STATE]: { |
|||
app: App; |
|||
inspectorId: string; |
|||
nodeId: string; |
|||
state: CustomInspectorState; |
|||
}; |
|||
[Hooks.EDIT_INSPECTOR_STATE]: { |
|||
app: App; |
|||
inspectorId: string; |
|||
nodeId: string; |
|||
path: string[]; |
|||
type: string; |
|||
state: EditStatePayload; |
|||
set: (object: any, path?: string | (string[]), value?: any, cb?: (object: any, field: string, value: any) => void) => void; |
|||
}; |
|||
[Hooks.SET_PLUGIN_SETTINGS]: { |
|||
app: App; |
|||
pluginId: string; |
|||
key: string; |
|||
newValue: any; |
|||
oldValue: any; |
|||
settings: any; |
|||
}; |
|||
} |
|||
export type EditStatePayload = { |
|||
value: any; |
|||
newKey?: string | null; |
|||
remove?: undefined | false; |
|||
} | { |
|||
value?: undefined; |
|||
newKey?: undefined; |
|||
remove: true; |
|||
}; |
|||
export type HookHandler<TPayload, TContext> = (payload: TPayload, ctx: TContext) => void | Promise<void>; |
|||
export interface Hookable<TContext> { |
|||
transformCall: (handler: HookHandler<HookPayloads[Hooks.TRANSFORM_CALL], TContext>) => any; |
|||
getAppRecordName: (handler: HookHandler<HookPayloads[Hooks.GET_APP_RECORD_NAME], TContext>) => any; |
|||
getAppRootInstance: (handler: HookHandler<HookPayloads[Hooks.GET_APP_ROOT_INSTANCE], TContext>) => any; |
|||
registerApplication: (handler: HookHandler<HookPayloads[Hooks.REGISTER_APPLICATION], TContext>) => any; |
|||
walkComponentTree: (handler: HookHandler<HookPayloads[Hooks.WALK_COMPONENT_TREE], TContext>) => any; |
|||
visitComponentTree: (handler: HookHandler<HookPayloads[Hooks.VISIT_COMPONENT_TREE], TContext>) => any; |
|||
walkComponentParents: (handler: HookHandler<HookPayloads[Hooks.WALK_COMPONENT_PARENTS], TContext>) => any; |
|||
inspectComponent: (handler: HookHandler<HookPayloads[Hooks.INSPECT_COMPONENT], TContext>) => any; |
|||
getComponentBounds: (handler: HookHandler<HookPayloads[Hooks.GET_COMPONENT_BOUNDS], TContext>) => any; |
|||
getComponentName: (handler: HookHandler<HookPayloads[Hooks.GET_COMPONENT_NAME], TContext>) => any; |
|||
getComponentInstances: (handler: HookHandler<HookPayloads[Hooks.GET_COMPONENT_INSTANCES], TContext>) => any; |
|||
getElementComponent: (handler: HookHandler<HookPayloads[Hooks.GET_ELEMENT_COMPONENT], TContext>) => any; |
|||
getComponentRootElements: (handler: HookHandler<HookPayloads[Hooks.GET_COMPONENT_ROOT_ELEMENTS], TContext>) => any; |
|||
editComponentState: (handler: HookHandler<HookPayloads[Hooks.EDIT_COMPONENT_STATE], TContext>) => any; |
|||
getComponentDevtoolsOptions: (handler: HookHandler<HookPayloads[Hooks.GET_COMPONENT_DEVTOOLS_OPTIONS], TContext>) => any; |
|||
getComponentRenderCode: (handler: HookHandler<HookPayloads[Hooks.GET_COMPONENT_RENDER_CODE], TContext>) => any; |
|||
inspectTimelineEvent: (handler: HookHandler<HookPayloads[Hooks.INSPECT_TIMELINE_EVENT], TContext>) => any; |
|||
timelineCleared: (handler: HookHandler<HookPayloads[Hooks.TIMELINE_CLEARED], TContext>) => any; |
|||
getInspectorTree: (handler: HookHandler<HookPayloads[Hooks.GET_INSPECTOR_TREE], TContext>) => any; |
|||
getInspectorState: (handler: HookHandler<HookPayloads[Hooks.GET_INSPECTOR_STATE], TContext>) => any; |
|||
editInspectorState: (handler: HookHandler<HookPayloads[Hooks.EDIT_INSPECTOR_STATE], TContext>) => any; |
|||
setPluginSettings: (handler: HookHandler<HookPayloads[Hooks.SET_PLUGIN_SETTINGS], TContext>) => any; |
|||
} |
@ -0,0 +1 @@ |
|||
export {}; |
@ -0,0 +1,6 @@ |
|||
export * from './api.js'; |
|||
export * from './app.js'; |
|||
export * from './component.js'; |
|||
export * from './context.js'; |
|||
export * from './hooks.js'; |
|||
export * from './util.js'; |
@ -0,0 +1,6 @@ |
|||
export * from './api.js'; |
|||
export * from './app.js'; |
|||
export * from './component.js'; |
|||
export * from './context.js'; |
|||
export * from './hooks.js'; |
|||
export * from './util.js'; |
@ -0,0 +1,4 @@ |
|||
export type ID = number | string; |
|||
export interface WithId { |
|||
id: ID; |
|||
} |
@ -0,0 +1 @@ |
|||
export {}; |
@ -0,0 +1,2 @@ |
|||
export declare const HOOK_SETUP = "devtools-plugin:setup"; |
|||
export declare const HOOK_PLUGIN_SETTINGS_SET = "plugin:settings:set"; |
@ -0,0 +1,2 @@ |
|||
export const HOOK_SETUP = 'devtools-plugin:setup'; |
|||
export const HOOK_PLUGIN_SETTINGS_SET = 'plugin:settings:set'; |
@ -0,0 +1,15 @@ |
|||
import type { ApiProxy } from './proxy.js'; |
|||
import type { PluginDescriptor, SetupFunction } from './index.js'; |
|||
export interface PluginQueueItem { |
|||
pluginDescriptor: PluginDescriptor; |
|||
setupFn: SetupFunction; |
|||
proxy?: ApiProxy; |
|||
} |
|||
interface GlobalTarget { |
|||
__VUE_DEVTOOLS_PLUGINS__?: PluginQueueItem[]; |
|||
__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__?: boolean; |
|||
} |
|||
export declare function getDevtoolsGlobalHook(): any; |
|||
export declare function getTarget(): GlobalTarget; |
|||
export declare const isProxyAvailable: boolean; |
|||
export {}; |
@ -0,0 +1,12 @@ |
|||
export function getDevtoolsGlobalHook() { |
|||
return getTarget().__VUE_DEVTOOLS_GLOBAL_HOOK__; |
|||
} |
|||
export function getTarget() { |
|||
// @ts-expect-error navigator and windows are not available in all environments
|
|||
return (typeof navigator !== 'undefined' && typeof window !== 'undefined') |
|||
? window |
|||
: typeof globalThis !== 'undefined' |
|||
? globalThis |
|||
: {}; |
|||
} |
|||
export const isProxyAvailable = typeof Proxy === 'function'; |
@ -0,0 +1,18 @@ |
|||
import type { DevtoolsPluginApi } from './api/index.js'; |
|||
import type { ExtractSettingsTypes, PluginDescriptor, PluginSettingsItem } from './plugin.js'; |
|||
export * from './api/index.js'; |
|||
export * from './plugin.js'; |
|||
export * from './time.js'; |
|||
export { PluginQueueItem } from './env.js'; |
|||
type Cast<A, B> = A extends B ? A : B; |
|||
type Narrowable = string | number | bigint | boolean; |
|||
type Narrow<A> = Cast<A, [] | (A extends Narrowable ? A : never) | ({ |
|||
[K in keyof A]: Narrow<A[K]>; |
|||
})>; |
|||
type Exact<C, T> = { |
|||
[K in keyof C]: K extends keyof T ? T[K] : never; |
|||
}; |
|||
export type SetupFunction<TSettings = any> = (api: DevtoolsPluginApi<TSettings>) => void; |
|||
export declare function setupDevtoolsPlugin<TDescriptor extends Exact<TDescriptor, PluginDescriptor>, TSettings = ExtractSettingsTypes<TDescriptor extends { |
|||
settings: infer S; |
|||
} ? S extends Record<string, PluginSettingsItem> ? S : Record<string, PluginSettingsItem> : Record<string, PluginSettingsItem>>>(pluginDescriptor: Narrow<TDescriptor>, setupFn: SetupFunction<TSettings>): void; |
@ -0,0 +1,27 @@ |
|||
import { getDevtoolsGlobalHook, getTarget, isProxyAvailable } from './env.js'; |
|||
import { HOOK_SETUP } from './const.js'; |
|||
import { ApiProxy } from './proxy.js'; |
|||
export * from './api/index.js'; |
|||
export * from './plugin.js'; |
|||
export * from './time.js'; |
|||
export function setupDevtoolsPlugin(pluginDescriptor, setupFn) { |
|||
const descriptor = pluginDescriptor; |
|||
const target = getTarget(); |
|||
const hook = getDevtoolsGlobalHook(); |
|||
const enableProxy = isProxyAvailable && descriptor.enableEarlyProxy; |
|||
if (hook && (target.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__ || !enableProxy)) { |
|||
hook.emit(HOOK_SETUP, pluginDescriptor, setupFn); |
|||
} |
|||
else { |
|||
const proxy = enableProxy ? new ApiProxy(descriptor, hook) : null; |
|||
const list = target.__VUE_DEVTOOLS_PLUGINS__ = target.__VUE_DEVTOOLS_PLUGINS__ || []; |
|||
list.push({ |
|||
pluginDescriptor: descriptor, |
|||
setupFn, |
|||
proxy, |
|||
}); |
|||
if (proxy) { |
|||
setupFn(proxy.proxiedTarget); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
import type { App } from './api/index.js'; |
|||
export interface PluginDescriptor { |
|||
id: string; |
|||
label: string; |
|||
app: App; |
|||
packageName?: string; |
|||
homepage?: string; |
|||
componentStateTypes?: string[]; |
|||
logo?: string; |
|||
disableAppScope?: boolean; |
|||
disablePluginScope?: boolean; |
|||
/** |
|||
* Run the plugin setup and expose the api even if the devtools is not opened yet. |
|||
* Useful to record timeline events early. |
|||
*/ |
|||
enableEarlyProxy?: boolean; |
|||
settings?: Record<string, PluginSettingsItem>; |
|||
} |
|||
export type PluginSettingsItem = { |
|||
label: string; |
|||
description?: string; |
|||
} & ({ |
|||
type: 'boolean'; |
|||
defaultValue: boolean; |
|||
} | { |
|||
type: 'choice'; |
|||
defaultValue: string | number; |
|||
options: { |
|||
value: string | number; |
|||
label: string; |
|||
}[]; |
|||
component?: 'select' | 'button-group'; |
|||
} | { |
|||
type: 'text'; |
|||
defaultValue: string; |
|||
}); |
|||
type InferSettingsType<T extends PluginSettingsItem> = [T] extends [{ |
|||
type: 'boolean'; |
|||
}] ? boolean : [T] extends [{ |
|||
type: 'choice'; |
|||
}] ? T['options'][number]['value'] : [T] extends [{ |
|||
type: 'text'; |
|||
}] ? string : unknown; |
|||
export type ExtractSettingsTypes<O extends Record<string, PluginSettingsItem>> = { |
|||
[K in keyof O]: InferSettingsType<O[K]>; |
|||
}; |
|||
export {}; |
@ -0,0 +1 @@ |
|||
export {}; |
@ -0,0 +1,20 @@ |
|||
import type { Context, DevtoolsPluginApi, Hookable } from './api/index.js'; |
|||
import type { PluginDescriptor } from './plugin.js'; |
|||
interface QueueItem { |
|||
method: string; |
|||
args: any[]; |
|||
resolve?: (value?: any) => void; |
|||
} |
|||
export declare class ApiProxy<TTarget extends DevtoolsPluginApi<any> = DevtoolsPluginApi<any>> { |
|||
target: TTarget | null; |
|||
targetQueue: QueueItem[]; |
|||
proxiedTarget: TTarget; |
|||
onQueue: QueueItem[]; |
|||
proxiedOn: Hookable<Context>; |
|||
plugin: PluginDescriptor; |
|||
hook: any; |
|||
fallbacks: Record<string, any>; |
|||
constructor(plugin: PluginDescriptor, hook: any); |
|||
setRealTarget(target: TTarget): Promise<void>; |
|||
} |
|||
export {}; |
@ -0,0 +1,107 @@ |
|||
import { HOOK_PLUGIN_SETTINGS_SET } from './const.js'; |
|||
import { now } from './time.js'; |
|||
export class ApiProxy { |
|||
constructor(plugin, hook) { |
|||
this.target = null; |
|||
this.targetQueue = []; |
|||
this.onQueue = []; |
|||
this.plugin = plugin; |
|||
this.hook = hook; |
|||
const defaultSettings = {}; |
|||
if (plugin.settings) { |
|||
for (const id in plugin.settings) { |
|||
const item = plugin.settings[id]; |
|||
defaultSettings[id] = item.defaultValue; |
|||
} |
|||
} |
|||
const localSettingsSaveId = `__vue-devtools-plugin-settings__${plugin.id}`; |
|||
let currentSettings = Object.assign({}, defaultSettings); |
|||
try { |
|||
const raw = localStorage.getItem(localSettingsSaveId); |
|||
const data = JSON.parse(raw); |
|||
Object.assign(currentSettings, data); |
|||
} |
|||
catch (e) { |
|||
// noop
|
|||
} |
|||
this.fallbacks = { |
|||
getSettings() { |
|||
return currentSettings; |
|||
}, |
|||
setSettings(value) { |
|||
try { |
|||
localStorage.setItem(localSettingsSaveId, JSON.stringify(value)); |
|||
} |
|||
catch (e) { |
|||
// noop
|
|||
} |
|||
currentSettings = value; |
|||
}, |
|||
now() { |
|||
return now(); |
|||
}, |
|||
}; |
|||
if (hook) { |
|||
hook.on(HOOK_PLUGIN_SETTINGS_SET, (pluginId, value) => { |
|||
if (pluginId === this.plugin.id) { |
|||
this.fallbacks.setSettings(value); |
|||
} |
|||
}); |
|||
} |
|||
this.proxiedOn = new Proxy({}, { |
|||
get: (_target, prop) => { |
|||
if (this.target) { |
|||
return this.target.on[prop]; |
|||
} |
|||
else { |
|||
return (...args) => { |
|||
this.onQueue.push({ |
|||
method: prop, |
|||
args, |
|||
}); |
|||
}; |
|||
} |
|||
}, |
|||
}); |
|||
this.proxiedTarget = new Proxy({}, { |
|||
get: (_target, prop) => { |
|||
if (this.target) { |
|||
return this.target[prop]; |
|||
} |
|||
else if (prop === 'on') { |
|||
return this.proxiedOn; |
|||
} |
|||
else if (Object.keys(this.fallbacks).includes(prop)) { |
|||
return (...args) => { |
|||
this.targetQueue.push({ |
|||
method: prop, |
|||
args, |
|||
resolve: () => { }, |
|||
}); |
|||
return this.fallbacks[prop](...args); |
|||
}; |
|||
} |
|||
else { |
|||
return (...args) => { |
|||
return new Promise((resolve) => { |
|||
this.targetQueue.push({ |
|||
method: prop, |
|||
args, |
|||
resolve, |
|||
}); |
|||
}); |
|||
}; |
|||
} |
|||
}, |
|||
}); |
|||
} |
|||
async setRealTarget(target) { |
|||
this.target = target; |
|||
for (const item of this.onQueue) { |
|||
this.target.on[item.method](...item.args); |
|||
} |
|||
for (const item of this.targetQueue) { |
|||
item.resolve(await this.target[item.method](...item.args)); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,2 @@ |
|||
export declare function isPerformanceSupported(): boolean; |
|||
export declare function now(): number; |
@ -0,0 +1,23 @@ |
|||
let supported; |
|||
let perf; |
|||
export function isPerformanceSupported() { |
|||
var _a; |
|||
if (supported !== undefined) { |
|||
return supported; |
|||
} |
|||
if (typeof window !== 'undefined' && window.performance) { |
|||
supported = true; |
|||
perf = window.performance; |
|||
} |
|||
else if (typeof globalThis !== 'undefined' && ((_a = globalThis.perf_hooks) === null || _a === void 0 ? void 0 : _a.performance)) { |
|||
supported = true; |
|||
perf = globalThis.perf_hooks.performance; |
|||
} |
|||
else { |
|||
supported = false; |
|||
} |
|||
return supported; |
|||
} |
|||
export function now() { |
|||
return isPerformanceSupported() ? perf.now() : Date.now(); |
|||
} |
@ -0,0 +1,67 @@ |
|||
{ |
|||
"_from": "@vue/devtools-api@^6.6.3", |
|||
"_id": "@vue/devtools-api@6.6.4", |
|||
"_inBundle": false, |
|||
"_integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", |
|||
"_location": "/@vue/devtools-api", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "range", |
|||
"registry": true, |
|||
"raw": "@vue/devtools-api@^6.6.3", |
|||
"name": "@vue/devtools-api", |
|||
"escapedName": "@vue%2fdevtools-api", |
|||
"scope": "@vue", |
|||
"rawSpec": "^6.6.3", |
|||
"saveSpec": null, |
|||
"fetchSpec": "^6.6.3" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/pinia" |
|||
], |
|||
"_resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", |
|||
"_shasum": "cbe97fe0162b365edc1dba80e173f90492535343", |
|||
"_spec": "@vue/devtools-api@^6.6.3", |
|||
"_where": "D:\\work\\questionbankvue3\\node_modules\\pinia", |
|||
"author": { |
|||
"name": "Guillaume Chau" |
|||
}, |
|||
"browser": "lib/esm/index.js", |
|||
"bugs": { |
|||
"url": "https://github.com/vuejs/vue-devtools/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"deprecated": false, |
|||
"description": "Interact with the Vue devtools from the page", |
|||
"devDependencies": { |
|||
"@types/node": "^20.11.16", |
|||
"@types/webpack-env": "^1.15.1", |
|||
"typescript": "^5.3.3" |
|||
}, |
|||
"files": [ |
|||
"lib/cjs", |
|||
"lib/esm" |
|||
], |
|||
"homepage": "https://github.com/vuejs/vue-devtools#readme", |
|||
"license": "MIT", |
|||
"main": "lib/cjs/index.js", |
|||
"module": "lib/esm/index.js", |
|||
"name": "@vue/devtools-api", |
|||
"publishConfig": { |
|||
"access": "public" |
|||
}, |
|||
"repository": { |
|||
"url": "git+https://github.com/vuejs/vue-devtools.git", |
|||
"type": "git", |
|||
"directory": "packages/api" |
|||
}, |
|||
"scripts": { |
|||
"build": "rimraf lib && yarn build:esm && yarn build:cjs", |
|||
"build:cjs": "tsc --module commonjs --outDir lib/cjs", |
|||
"build:esm": "tsc --module es2015 --outDir lib/esm -d", |
|||
"build:watch": "yarn tsc --module es2015 --outDir lib/esm -d -w --sourceMap" |
|||
}, |
|||
"sideEffects": false, |
|||
"types": "lib/esm/index.d.ts", |
|||
"version": "6.6.4" |
|||
} |
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2019-present Eduardo San Martin Morote |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
@ -0,0 +1,24 @@ |
|||
<p align="center"> |
|||
<a href="https://pinia.vuejs.org" target="_blank" rel="noopener noreferrer"> |
|||
<img width="180" src="https://pinia.vuejs.org/logo.svg" alt="Pinia logo"> |
|||
</a> |
|||
</p> |
|||
|
|||
# Pinia |
|||
|
|||
> Intuitive, type safe and flexible Store for Vue |
|||
|
|||
## 👉 [Demo with Vue 3 on StackBlitz](https://stackblitz.com/github/piniajs/example-vue-3-vite) |
|||
|
|||
## Help me keep working on this project 💚 |
|||
|
|||
- [Become a Sponsor on GitHub](https://github.com/sponsors/posva) |
|||
- [One-time donation via PayPal](https://paypal.me/posva) |
|||
|
|||
## Documentation |
|||
|
|||
To learn more about Pinia, check [its documentation](https://pinia.vuejs.org). |
|||
|
|||
## License |
|||
|
|||
[MIT](http://opensource.org/licenses/MIT) |
2059
node_modules/pinia/dist/pinia.cjs
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1064
node_modules/pinia/dist/pinia.d.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2035
node_modules/pinia/dist/pinia.esm-browser.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2221
node_modules/pinia/dist/pinia.iife.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
6
node_modules/pinia/dist/pinia.iife.prod.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2043
node_modules/pinia/dist/pinia.mjs
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,844 @@ |
|||
/*! |
|||
* pinia v2.2.4 |
|||
* (c) 2024 Eduardo San Martin Morote |
|||
* @license MIT |
|||
*/ |
|||
'use strict'; |
|||
|
|||
var vueDemi = require('vue-demi'); |
|||
|
|||
/** |
|||
* setActivePinia must be called to handle SSR at the top of functions like |
|||
* `fetch`, `setup`, `serverPrefetch` and others |
|||
*/ |
|||
let activePinia; |
|||
/** |
|||
* Sets or unsets the active pinia. Used in SSR and internally when calling |
|||
* actions and getters |
|||
* |
|||
* @param pinia - Pinia instance |
|||
*/ |
|||
// @ts-expect-error: cannot constrain the type of the return |
|||
const setActivePinia = (pinia) => (activePinia = pinia); |
|||
/** |
|||
* Get the currently active pinia if there is any. |
|||
*/ |
|||
const getActivePinia = () => (vueDemi.hasInjectionContext() && vueDemi.inject(piniaSymbol)) || activePinia; |
|||
const piniaSymbol = (/* istanbul ignore next */ Symbol()); |
|||
|
|||
function isPlainObject( |
|||
// eslint-disable-next-line @typescript-eslint/no-explicit-any |
|||
o) { |
|||
return (o && |
|||
typeof o === 'object' && |
|||
Object.prototype.toString.call(o) === '[object Object]' && |
|||
typeof o.toJSON !== 'function'); |
|||
} |
|||
// type DeepReadonly<T> = { readonly [P in keyof T]: DeepReadonly<T[P]> } |
|||
// TODO: can we change these to numbers? |
|||
/** |
|||
* Possible types for SubscriptionCallback |
|||
*/ |
|||
exports.MutationType = void 0; |
|||
(function (MutationType) { |
|||
/** |
|||
* Direct mutation of the state: |
|||
* |
|||
* - `store.name = 'new name'` |
|||
* - `store.$state.name = 'new name'` |
|||
* - `store.list.push('new item')` |
|||
*/ |
|||
MutationType["direct"] = "direct"; |
|||
/** |
|||
* Mutated the state with `$patch` and an object |
|||
* |
|||
* - `store.$patch({ name: 'newName' })` |
|||
*/ |
|||
MutationType["patchObject"] = "patch object"; |
|||
/** |
|||
* Mutated the state with `$patch` and a function |
|||
* |
|||
* - `store.$patch(state => state.name = 'newName')` |
|||
*/ |
|||
MutationType["patchFunction"] = "patch function"; |
|||
// maybe reset? for $state = {} and $reset |
|||
})(exports.MutationType || (exports.MutationType = {})); |
|||
|
|||
const IS_CLIENT = typeof window !== 'undefined'; |
|||
|
|||
/** |
|||
* Creates a Pinia instance to be used by the application |
|||
*/ |
|||
function createPinia() { |
|||
const scope = vueDemi.effectScope(true); |
|||
// NOTE: here we could check the window object for a state and directly set it |
|||
// if there is anything like it with Vue 3 SSR |
|||
const state = scope.run(() => vueDemi.ref({})); |
|||
let _p = []; |
|||
// plugins added before calling app.use(pinia) |
|||
let toBeInstalled = []; |
|||
const pinia = vueDemi.markRaw({ |
|||
install(app) { |
|||
// this allows calling useStore() outside of a component setup after |
|||
// installing pinia's plugin |
|||
setActivePinia(pinia); |
|||
if (!vueDemi.isVue2) { |
|||
pinia._a = app; |
|||
app.provide(piniaSymbol, pinia); |
|||
app.config.globalProperties.$pinia = pinia; |
|||
toBeInstalled.forEach((plugin) => _p.push(plugin)); |
|||
toBeInstalled = []; |
|||
} |
|||
}, |
|||
use(plugin) { |
|||
if (!this._a && !vueDemi.isVue2) { |
|||
toBeInstalled.push(plugin); |
|||
} |
|||
else { |
|||
_p.push(plugin); |
|||
} |
|||
return this; |
|||
}, |
|||
_p, |
|||
// it's actually undefined here |
|||
// @ts-expect-error |
|||
_a: null, |
|||
_e: scope, |
|||
_s: new Map(), |
|||
state, |
|||
}); |
|||
return pinia; |
|||
} |
|||
/** |
|||
* Dispose a Pinia instance by stopping its effectScope and removing the state, plugins and stores. This is mostly |
|||
* useful in tests, with both a testing pinia or a regular pinia and in applications that use multiple pinia instances. |
|||
* Once disposed, the pinia instance cannot be used anymore. |
|||
* |
|||
* @param pinia - pinia instance |
|||
*/ |
|||
function disposePinia(pinia) { |
|||
pinia._e.stop(); |
|||
pinia._s.clear(); |
|||
pinia._p.splice(0); |
|||
pinia.state.value = {}; |
|||
// @ts-expect-error: non valid |
|||
pinia._a = null; |
|||
} |
|||
|
|||
/** |
|||
* Creates an _accept_ function to pass to `import.meta.hot` in Vite applications. |
|||
* |
|||
* @example |
|||
* ```js |
|||
* const useUser = defineStore(...) |
|||
* if (import.meta.hot) { |
|||
* import.meta.hot.accept(acceptHMRUpdate(useUser, import.meta.hot)) |
|||
* } |
|||
* ``` |
|||
* |
|||
* @param initialUseStore - return of the defineStore to hot update |
|||
* @param hot - `import.meta.hot` |
|||
*/ |
|||
function acceptHMRUpdate(initialUseStore, hot) { |
|||
// strip as much as possible from iife.prod |
|||
{ |
|||
return () => { }; |
|||
} |
|||
} |
|||
|
|||
const noop = () => { }; |
|||
function addSubscription(subscriptions, callback, detached, onCleanup = noop) { |
|||
subscriptions.push(callback); |
|||
const removeSubscription = () => { |
|||
const idx = subscriptions.indexOf(callback); |
|||
if (idx > -1) { |
|||
subscriptions.splice(idx, 1); |
|||
onCleanup(); |
|||
} |
|||
}; |
|||
if (!detached && vueDemi.getCurrentScope()) { |
|||
vueDemi.onScopeDispose(removeSubscription); |
|||
} |
|||
return removeSubscription; |
|||
} |
|||
function triggerSubscriptions(subscriptions, ...args) { |
|||
subscriptions.slice().forEach((callback) => { |
|||
callback(...args); |
|||
}); |
|||
} |
|||
|
|||
const fallbackRunWithContext = (fn) => fn(); |
|||
/** |
|||
* Marks a function as an action for `$onAction` |
|||
* @internal |
|||
*/ |
|||
const ACTION_MARKER = Symbol(); |
|||
/** |
|||
* Action name symbol. Allows to add a name to an action after defining it |
|||
* @internal |
|||
*/ |
|||
const ACTION_NAME = Symbol(); |
|||
function mergeReactiveObjects(target, patchToApply) { |
|||
// Handle Map instances |
|||
if (target instanceof Map && patchToApply instanceof Map) { |
|||
patchToApply.forEach((value, key) => target.set(key, value)); |
|||
} |
|||
else if (target instanceof Set && patchToApply instanceof Set) { |
|||
// Handle Set instances |
|||
patchToApply.forEach(target.add, target); |
|||
} |
|||
// no need to go through symbols because they cannot be serialized anyway |
|||
for (const key in patchToApply) { |
|||
if (!patchToApply.hasOwnProperty(key)) |
|||
continue; |
|||
const subPatch = patchToApply[key]; |
|||
const targetValue = target[key]; |
|||
if (isPlainObject(targetValue) && |
|||
isPlainObject(subPatch) && |
|||
target.hasOwnProperty(key) && |
|||
!vueDemi.isRef(subPatch) && |
|||
!vueDemi.isReactive(subPatch)) { |
|||
// NOTE: here I wanted to warn about inconsistent types but it's not possible because in setup stores one might |
|||
// start the value of a property as a certain type e.g. a Map, and then for some reason, during SSR, change that |
|||
// to `undefined`. When trying to hydrate, we want to override the Map with `undefined`. |
|||
target[key] = mergeReactiveObjects(targetValue, subPatch); |
|||
} |
|||
else { |
|||
// @ts-expect-error: subPatch is a valid value |
|||
target[key] = subPatch; |
|||
} |
|||
} |
|||
return target; |
|||
} |
|||
const skipHydrateSymbol = /* istanbul ignore next */ Symbol(); |
|||
const skipHydrateMap = /*#__PURE__*/ new WeakMap(); |
|||
/** |
|||
* Tells Pinia to skip the hydration process of a given object. This is useful in setup stores (only) when you return a |
|||
* stateful object in the store but it isn't really state. e.g. returning a router instance in a setup store. |
|||
* |
|||
* @param obj - target object |
|||
* @returns obj |
|||
*/ |
|||
function skipHydrate(obj) { |
|||
return vueDemi.isVue2 |
|||
? // in @vue/composition-api, the refs are sealed so defineProperty doesn't work... |
|||
/* istanbul ignore next */ skipHydrateMap.set(obj, 1) && obj |
|||
: Object.defineProperty(obj, skipHydrateSymbol, {}); |
|||
} |
|||
/** |
|||
* Returns whether a value should be hydrated |
|||
* |
|||
* @param obj - target variable |
|||
* @returns true if `obj` should be hydrated |
|||
*/ |
|||
function shouldHydrate(obj) { |
|||
return vueDemi.isVue2 |
|||
? /* istanbul ignore next */ !skipHydrateMap.has(obj) |
|||
: !isPlainObject(obj) || !obj.hasOwnProperty(skipHydrateSymbol); |
|||
} |
|||
const { assign } = Object; |
|||
function isComputed(o) { |
|||
return !!(vueDemi.isRef(o) && o.effect); |
|||
} |
|||
function createOptionsStore(id, options, pinia, hot) { |
|||
const { state, actions, getters } = options; |
|||
const initialState = pinia.state.value[id]; |
|||
let store; |
|||
function setup() { |
|||
if (!initialState && (!false)) { |
|||
/* istanbul ignore if */ |
|||
if (vueDemi.isVue2) { |
|||
vueDemi.set(pinia.state.value, id, state ? state() : {}); |
|||
} |
|||
else { |
|||
pinia.state.value[id] = state ? state() : {}; |
|||
} |
|||
} |
|||
// avoid creating a state in pinia.state.value |
|||
const localState = vueDemi.toRefs(pinia.state.value[id]); |
|||
return assign(localState, actions, Object.keys(getters || {}).reduce((computedGetters, name) => { |
|||
computedGetters[name] = vueDemi.markRaw(vueDemi.computed(() => { |
|||
setActivePinia(pinia); |
|||
// it was created just before |
|||
const store = pinia._s.get(id); |
|||
// allow cross using stores |
|||
/* istanbul ignore if */ |
|||
if (vueDemi.isVue2 && !store._r) |
|||
return; |
|||
// @ts-expect-error |
|||
// return getters![name].call(context, context) |
|||
// TODO: avoid reading the getter while assigning with a global variable |
|||
return getters[name].call(store, store); |
|||
})); |
|||
return computedGetters; |
|||
}, {})); |
|||
} |
|||
store = createSetupStore(id, setup, options, pinia, hot, true); |
|||
return store; |
|||
} |
|||
function createSetupStore($id, setup, options = {}, pinia, hot, isOptionsStore) { |
|||
let scope; |
|||
const optionsForPlugin = assign({ actions: {} }, options); |
|||
// watcher options for $subscribe |
|||
const $subscribeOptions = { deep: true }; |
|||
// internal state |
|||
let isListening; // set to true at the end |
|||
let isSyncListening; // set to true at the end |
|||
let subscriptions = []; |
|||
let actionSubscriptions = []; |
|||
let debuggerEvents; |
|||
const initialState = pinia.state.value[$id]; |
|||
// avoid setting the state for option stores if it is set |
|||
// by the setup |
|||
if (!isOptionsStore && !initialState && (!false)) { |
|||
/* istanbul ignore if */ |
|||
if (vueDemi.isVue2) { |
|||
vueDemi.set(pinia.state.value, $id, {}); |
|||
} |
|||
else { |
|||
pinia.state.value[$id] = {}; |
|||
} |
|||
} |
|||
vueDemi.ref({}); |
|||
// avoid triggering too many listeners |
|||
// https://github.com/vuejs/pinia/issues/1129 |
|||
let activeListener; |
|||
function $patch(partialStateOrMutator) { |
|||
let subscriptionMutation; |
|||
isListening = isSyncListening = false; |
|||
if (typeof partialStateOrMutator === 'function') { |
|||
partialStateOrMutator(pinia.state.value[$id]); |
|||
subscriptionMutation = { |
|||
type: exports.MutationType.patchFunction, |
|||
storeId: $id, |
|||
events: debuggerEvents, |
|||
}; |
|||
} |
|||
else { |
|||
mergeReactiveObjects(pinia.state.value[$id], partialStateOrMutator); |
|||
subscriptionMutation = { |
|||
type: exports.MutationType.patchObject, |
|||
payload: partialStateOrMutator, |
|||
storeId: $id, |
|||
events: debuggerEvents, |
|||
}; |
|||
} |
|||
const myListenerId = (activeListener = Symbol()); |
|||
vueDemi.nextTick().then(() => { |
|||
if (activeListener === myListenerId) { |
|||
isListening = true; |
|||
} |
|||
}); |
|||
isSyncListening = true; |
|||
// because we paused the watcher, we need to manually call the subscriptions |
|||
triggerSubscriptions(subscriptions, subscriptionMutation, pinia.state.value[$id]); |
|||
} |
|||
const $reset = isOptionsStore |
|||
? function $reset() { |
|||
const { state } = options; |
|||
const newState = state ? state() : {}; |
|||
// we use a patch to group all changes into one single subscription |
|||
this.$patch(($state) => { |
|||
// @ts-expect-error: FIXME: shouldn't error? |
|||
assign($state, newState); |
|||
}); |
|||
} |
|||
: /* istanbul ignore next */ |
|||
noop; |
|||
function $dispose() { |
|||
scope.stop(); |
|||
subscriptions = []; |
|||
actionSubscriptions = []; |
|||
pinia._s.delete($id); |
|||
} |
|||
/** |
|||
* Helper that wraps function so it can be tracked with $onAction |
|||
* @param fn - action to wrap |
|||
* @param name - name of the action |
|||
*/ |
|||
const action = (fn, name = '') => { |
|||
if (ACTION_MARKER in fn) { |
|||
fn[ACTION_NAME] = name; |
|||
return fn; |
|||
} |
|||
const wrappedAction = function () { |
|||
setActivePinia(pinia); |
|||
const args = Array.from(arguments); |
|||
const afterCallbackList = []; |
|||
const onErrorCallbackList = []; |
|||
function after(callback) { |
|||
afterCallbackList.push(callback); |
|||
} |
|||
function onError(callback) { |
|||
onErrorCallbackList.push(callback); |
|||
} |
|||
// @ts-expect-error |
|||
triggerSubscriptions(actionSubscriptions, { |
|||
args, |
|||
name: wrappedAction[ACTION_NAME], |
|||
store, |
|||
after, |
|||
onError, |
|||
}); |
|||
let ret; |
|||
try { |
|||
ret = fn.apply(this && this.$id === $id ? this : store, args); |
|||
// handle sync errors |
|||
} |
|||
catch (error) { |
|||
triggerSubscriptions(onErrorCallbackList, error); |
|||
throw error; |
|||
} |
|||
if (ret instanceof Promise) { |
|||
return ret |
|||
.then((value) => { |
|||
triggerSubscriptions(afterCallbackList, value); |
|||
return value; |
|||
}) |
|||
.catch((error) => { |
|||
triggerSubscriptions(onErrorCallbackList, error); |
|||
return Promise.reject(error); |
|||
}); |
|||
} |
|||
// trigger after callbacks |
|||
triggerSubscriptions(afterCallbackList, ret); |
|||
return ret; |
|||
}; |
|||
wrappedAction[ACTION_MARKER] = true; |
|||
wrappedAction[ACTION_NAME] = name; // will be set later |
|||
// @ts-expect-error: we are intentionally limiting the returned type to just Fn |
|||
// because all the added properties are internals that are exposed through `$onAction()` only |
|||
return wrappedAction; |
|||
}; |
|||
const partialStore = { |
|||
_p: pinia, |
|||
// _s: scope, |
|||
$id, |
|||
$onAction: addSubscription.bind(null, actionSubscriptions), |
|||
$patch, |
|||
$reset, |
|||
$subscribe(callback, options = {}) { |
|||
const removeSubscription = addSubscription(subscriptions, callback, options.detached, () => stopWatcher()); |
|||
const stopWatcher = scope.run(() => vueDemi.watch(() => pinia.state.value[$id], (state) => { |
|||
if (options.flush === 'sync' ? isSyncListening : isListening) { |
|||
callback({ |
|||
storeId: $id, |
|||
type: exports.MutationType.direct, |
|||
events: debuggerEvents, |
|||
}, state); |
|||
} |
|||
}, assign({}, $subscribeOptions, options))); |
|||
return removeSubscription; |
|||
}, |
|||
$dispose, |
|||
}; |
|||
/* istanbul ignore if */ |
|||
if (vueDemi.isVue2) { |
|||
// start as non ready |
|||
partialStore._r = false; |
|||
} |
|||
const store = vueDemi.reactive(partialStore); |
|||
// store the partial store now so the setup of stores can instantiate each other before they are finished without |
|||
// creating infinite loops. |
|||
pinia._s.set($id, store); |
|||
const runWithContext = (pinia._a && pinia._a.runWithContext) || fallbackRunWithContext; |
|||
// TODO: idea create skipSerialize that marks properties as non serializable and they are skipped |
|||
const setupStore = runWithContext(() => pinia._e.run(() => (scope = vueDemi.effectScope()).run(() => setup({ action })))); |
|||
// overwrite existing actions to support $onAction |
|||
for (const key in setupStore) { |
|||
const prop = setupStore[key]; |
|||
if ((vueDemi.isRef(prop) && !isComputed(prop)) || vueDemi.isReactive(prop)) { |
|||
// mark it as a piece of state to be serialized |
|||
if (!isOptionsStore) { |
|||
// in setup stores we must hydrate the state and sync pinia state tree with the refs the user just created |
|||
if (initialState && shouldHydrate(prop)) { |
|||
if (vueDemi.isRef(prop)) { |
|||
prop.value = initialState[key]; |
|||
} |
|||
else { |
|||
// probably a reactive object, lets recursively assign |
|||
// @ts-expect-error: prop is unknown |
|||
mergeReactiveObjects(prop, initialState[key]); |
|||
} |
|||
} |
|||
// transfer the ref to the pinia state to keep everything in sync |
|||
/* istanbul ignore if */ |
|||
if (vueDemi.isVue2) { |
|||
vueDemi.set(pinia.state.value[$id], key, prop); |
|||
} |
|||
else { |
|||
pinia.state.value[$id][key] = prop; |
|||
} |
|||
} |
|||
// action |
|||
} |
|||
else if (typeof prop === 'function') { |
|||
const actionValue = action(prop, key); |
|||
// this a hot module replacement store because the hotUpdate method needs |
|||
// to do it with the right context |
|||
/* istanbul ignore if */ |
|||
if (vueDemi.isVue2) { |
|||
vueDemi.set(setupStore, key, actionValue); |
|||
} |
|||
else { |
|||
// @ts-expect-error |
|||
setupStore[key] = actionValue; |
|||
} |
|||
// list actions so they can be used in plugins |
|||
// @ts-expect-error |
|||
optionsForPlugin.actions[key] = prop; |
|||
} |
|||
else ; |
|||
} |
|||
// add the state, getters, and action properties |
|||
/* istanbul ignore if */ |
|||
if (vueDemi.isVue2) { |
|||
Object.keys(setupStore).forEach((key) => { |
|||
vueDemi.set(store, key, setupStore[key]); |
|||
}); |
|||
} |
|||
else { |
|||
assign(store, setupStore); |
|||
// allows retrieving reactive objects with `storeToRefs()`. Must be called after assigning to the reactive object. |
|||
// Make `storeToRefs()` work with `reactive()` #799 |
|||
assign(vueDemi.toRaw(store), setupStore); |
|||
} |
|||
// use this instead of a computed with setter to be able to create it anywhere |
|||
// without linking the computed lifespan to wherever the store is first |
|||
// created. |
|||
Object.defineProperty(store, '$state', { |
|||
get: () => (pinia.state.value[$id]), |
|||
set: (state) => { |
|||
$patch(($state) => { |
|||
// @ts-expect-error: FIXME: shouldn't error? |
|||
assign($state, state); |
|||
}); |
|||
}, |
|||
}); |
|||
/* istanbul ignore if */ |
|||
if (vueDemi.isVue2) { |
|||
// mark the store as ready before plugins |
|||
store._r = true; |
|||
} |
|||
// apply all plugins |
|||
pinia._p.forEach((extender) => { |
|||
/* istanbul ignore else */ |
|||
{ |
|||
assign(store, scope.run(() => extender({ |
|||
store: store, |
|||
app: pinia._a, |
|||
pinia, |
|||
options: optionsForPlugin, |
|||
}))); |
|||
} |
|||
}); |
|||
// only apply hydrate to option stores with an initial state in pinia |
|||
if (initialState && |
|||
isOptionsStore && |
|||
options.hydrate) { |
|||
options.hydrate(store.$state, initialState); |
|||
} |
|||
isListening = true; |
|||
isSyncListening = true; |
|||
return store; |
|||
} |
|||
// improves tree shaking |
|||
/*#__NO_SIDE_EFFECTS__*/ |
|||
function defineStore( |
|||
// TODO: add proper types from above |
|||
idOrOptions, setup, setupOptions) { |
|||
let id; |
|||
let options; |
|||
const isSetupStore = typeof setup === 'function'; |
|||
if (typeof idOrOptions === 'string') { |
|||
id = idOrOptions; |
|||
// the option store setup will contain the actual options in this case |
|||
options = isSetupStore ? setupOptions : setup; |
|||
} |
|||
else { |
|||
options = idOrOptions; |
|||
id = idOrOptions.id; |
|||
} |
|||
function useStore(pinia, hot) { |
|||
const hasContext = vueDemi.hasInjectionContext(); |
|||
pinia = |
|||
// in test mode, ignore the argument provided as we can always retrieve a |
|||
// pinia instance with getActivePinia() |
|||
((process.env.NODE_ENV === 'test') && activePinia && activePinia._testing ? null : pinia) || |
|||
(hasContext ? vueDemi.inject(piniaSymbol, null) : null); |
|||
if (pinia) |
|||
setActivePinia(pinia); |
|||
pinia = activePinia; |
|||
if (!pinia._s.has(id)) { |
|||
// creating the store registers it in `pinia._s` |
|||
if (isSetupStore) { |
|||
createSetupStore(id, setup, options, pinia); |
|||
} |
|||
else { |
|||
createOptionsStore(id, options, pinia); |
|||
} |
|||
} |
|||
const store = pinia._s.get(id); |
|||
// StoreGeneric cannot be casted towards Store |
|||
return store; |
|||
} |
|||
useStore.$id = id; |
|||
return useStore; |
|||
} |
|||
|
|||
let mapStoreSuffix = 'Store'; |
|||
/** |
|||
* Changes the suffix added by `mapStores()`. Can be set to an empty string. |
|||
* Defaults to `"Store"`. Make sure to extend the MapStoresCustomization |
|||
* interface if you are using TypeScript. |
|||
* |
|||
* @param suffix - new suffix |
|||
*/ |
|||
function setMapStoreSuffix(suffix // could be 'Store' but that would be annoying for JS |
|||
) { |
|||
mapStoreSuffix = suffix; |
|||
} |
|||
/** |
|||
* Allows using stores without the composition API (`setup()`) by generating an |
|||
* object to be spread in the `computed` field of a component. It accepts a list |
|||
* of store definitions. |
|||
* |
|||
* @example |
|||
* ```js |
|||
* export default { |
|||
* computed: { |
|||
* // other computed properties |
|||
* ...mapStores(useUserStore, useCartStore) |
|||
* }, |
|||
* |
|||
* created() { |
|||
* this.userStore // store with id "user" |
|||
* this.cartStore // store with id "cart" |
|||
* } |
|||
* } |
|||
* ``` |
|||
* |
|||
* @param stores - list of stores to map to an object |
|||
*/ |
|||
function mapStores(...stores) { |
|||
return stores.reduce((reduced, useStore) => { |
|||
// @ts-expect-error: $id is added by defineStore |
|||
reduced[useStore.$id + mapStoreSuffix] = function () { |
|||
return useStore(this.$pinia); |
|||
}; |
|||
return reduced; |
|||
}, {}); |
|||
} |
|||
/** |
|||
* Allows using state and getters from one store without using the composition |
|||
* API (`setup()`) by generating an object to be spread in the `computed` field |
|||
* of a component. |
|||
* |
|||
* @param useStore - store to map from |
|||
* @param keysOrMapper - array or object |
|||
*/ |
|||
function mapState(useStore, keysOrMapper) { |
|||
return Array.isArray(keysOrMapper) |
|||
? keysOrMapper.reduce((reduced, key) => { |
|||
reduced[key] = function () { |
|||
// @ts-expect-error: FIXME: should work? |
|||
return useStore(this.$pinia)[key]; |
|||
}; |
|||
return reduced; |
|||
}, {}) |
|||
: Object.keys(keysOrMapper).reduce((reduced, key) => { |
|||
// @ts-expect-error |
|||
reduced[key] = function () { |
|||
const store = useStore(this.$pinia); |
|||
const storeKey = keysOrMapper[key]; |
|||
// for some reason TS is unable to infer the type of storeKey to be a |
|||
// function |
|||
return typeof storeKey === 'function' |
|||
? storeKey.call(this, store) |
|||
: // @ts-expect-error: FIXME: should work? |
|||
store[storeKey]; |
|||
}; |
|||
return reduced; |
|||
}, {}); |
|||
} |
|||
/** |
|||
* Alias for `mapState()`. You should use `mapState()` instead. |
|||
* @deprecated use `mapState()` instead. |
|||
*/ |
|||
const mapGetters = mapState; |
|||
/** |
|||
* Allows directly using actions from your store without using the composition |
|||
* API (`setup()`) by generating an object to be spread in the `methods` field |
|||
* of a component. |
|||
* |
|||
* @param useStore - store to map from |
|||
* @param keysOrMapper - array or object |
|||
*/ |
|||
function mapActions(useStore, keysOrMapper) { |
|||
return Array.isArray(keysOrMapper) |
|||
? keysOrMapper.reduce((reduced, key) => { |
|||
// @ts-expect-error |
|||
reduced[key] = function (...args) { |
|||
// @ts-expect-error: FIXME: should work? |
|||
return useStore(this.$pinia)[key](...args); |
|||
}; |
|||
return reduced; |
|||
}, {}) |
|||
: Object.keys(keysOrMapper).reduce((reduced, key) => { |
|||
// @ts-expect-error |
|||
reduced[key] = function (...args) { |
|||
// @ts-expect-error: FIXME: should work? |
|||
return useStore(this.$pinia)[keysOrMapper[key]](...args); |
|||
}; |
|||
return reduced; |
|||
}, {}); |
|||
} |
|||
/** |
|||
* Allows using state and getters from one store without using the composition |
|||
* API (`setup()`) by generating an object to be spread in the `computed` field |
|||
* of a component. |
|||
* |
|||
* @param useStore - store to map from |
|||
* @param keysOrMapper - array or object |
|||
*/ |
|||
function mapWritableState(useStore, keysOrMapper) { |
|||
return Array.isArray(keysOrMapper) |
|||
? keysOrMapper.reduce((reduced, key) => { |
|||
// @ts-ignore |
|||
reduced[key] = { |
|||
get() { |
|||
// @ts-expect-error: FIXME: should work? |
|||
return useStore(this.$pinia)[key]; |
|||
}, |
|||
set(value) { |
|||
// @ts-expect-error: FIXME: should work? |
|||
return (useStore(this.$pinia)[key] = value); |
|||
}, |
|||
}; |
|||
return reduced; |
|||
}, {}) |
|||
: Object.keys(keysOrMapper).reduce((reduced, key) => { |
|||
// @ts-ignore |
|||
reduced[key] = { |
|||
get() { |
|||
// @ts-expect-error: FIXME: should work? |
|||
return useStore(this.$pinia)[keysOrMapper[key]]; |
|||
}, |
|||
set(value) { |
|||
// @ts-expect-error: FIXME: should work? |
|||
return (useStore(this.$pinia)[keysOrMapper[key]] = value); |
|||
}, |
|||
}; |
|||
return reduced; |
|||
}, {}); |
|||
} |
|||
|
|||
/** |
|||
* Creates an object of references with all the state, getters, and plugin-added |
|||
* state properties of the store. Similar to `toRefs()` but specifically |
|||
* designed for Pinia stores so methods and non reactive properties are |
|||
* completely ignored. |
|||
* |
|||
* @param store - store to extract the refs from |
|||
*/ |
|||
function storeToRefs(store) { |
|||
// See https://github.com/vuejs/pinia/issues/852 |
|||
// It's easier to just use toRefs() even if it includes more stuff |
|||
if (vueDemi.isVue2) { |
|||
// @ts-expect-error: toRefs include methods and others |
|||
return vueDemi.toRefs(store); |
|||
} |
|||
else { |
|||
store = vueDemi.toRaw(store); |
|||
const refs = {}; |
|||
for (const key in store) { |
|||
const value = store[key]; |
|||
if (vueDemi.isRef(value) || vueDemi.isReactive(value)) { |
|||
// @ts-expect-error: the key is state or getter |
|||
refs[key] = |
|||
// --- |
|||
vueDemi.toRef(store, key); |
|||
} |
|||
} |
|||
return refs; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Vue 2 Plugin that must be installed for pinia to work. Note **you don't need |
|||
* this plugin if you are using Nuxt.js**. Use the `buildModule` instead: |
|||
* https://pinia.vuejs.org/ssr/nuxt.html. |
|||
* |
|||
* @example |
|||
* ```js |
|||
* import Vue from 'vue' |
|||
* import { PiniaVuePlugin, createPinia } from 'pinia' |
|||
* |
|||
* Vue.use(PiniaVuePlugin) |
|||
* const pinia = createPinia() |
|||
* |
|||
* new Vue({ |
|||
* el: '#app', |
|||
* // ... |
|||
* pinia, |
|||
* }) |
|||
* ``` |
|||
* |
|||
* @param _Vue - `Vue` imported from 'vue'. |
|||
*/ |
|||
const PiniaVuePlugin = function (_Vue) { |
|||
// Equivalent of |
|||
// app.config.globalProperties.$pinia = pinia |
|||
_Vue.mixin({ |
|||
beforeCreate() { |
|||
const options = this.$options; |
|||
if (options.pinia) { |
|||
const pinia = options.pinia; |
|||
// HACK: taken from provide(): https://github.com/vuejs/composition-api/blob/main/src/apis/inject.ts#L31 |
|||
/* istanbul ignore else */ |
|||
if (!this._provided) { |
|||
const provideCache = {}; |
|||
Object.defineProperty(this, '_provided', { |
|||
get: () => provideCache, |
|||
set: (v) => Object.assign(provideCache, v), |
|||
}); |
|||
} |
|||
this._provided[piniaSymbol] = pinia; |
|||
// propagate the pinia instance in an SSR friendly way |
|||
// avoid adding it to nuxt twice |
|||
/* istanbul ignore else */ |
|||
if (!this.$pinia) { |
|||
this.$pinia = pinia; |
|||
} |
|||
pinia._a = this; |
|||
if (IS_CLIENT) { |
|||
// this allows calling useStore() outside of a component setup after |
|||
// installing pinia's plugin |
|||
setActivePinia(pinia); |
|||
} |
|||
} |
|||
else if (!this.$pinia && options.parent && options.parent.$pinia) { |
|||
this.$pinia = options.parent.$pinia; |
|||
} |
|||
}, |
|||
destroyed() { |
|||
delete this._pStores; |
|||
}, |
|||
}); |
|||
}; |
|||
|
|||
exports.PiniaVuePlugin = PiniaVuePlugin; |
|||
exports.acceptHMRUpdate = acceptHMRUpdate; |
|||
exports.createPinia = createPinia; |
|||
exports.defineStore = defineStore; |
|||
exports.disposePinia = disposePinia; |
|||
exports.getActivePinia = getActivePinia; |
|||
exports.mapActions = mapActions; |
|||
exports.mapGetters = mapGetters; |
|||
exports.mapState = mapState; |
|||
exports.mapStores = mapStores; |
|||
exports.mapWritableState = mapWritableState; |
|||
exports.setActivePinia = setActivePinia; |
|||
exports.setMapStoreSuffix = setMapStoreSuffix; |
|||
exports.skipHydrate = skipHydrate; |
|||
exports.storeToRefs = storeToRefs; |
@ -0,0 +1,7 @@ |
|||
'use strict' |
|||
|
|||
if (process.env.NODE_ENV === 'production') { |
|||
module.exports = require('./dist/pinia.prod.cjs') |
|||
} else { |
|||
module.exports = require('./dist/pinia.cjs') |
|||
} |
@ -0,0 +1,7 @@ |
|||
'use strict' |
|||
|
|||
if (process.env.NODE_ENV === 'production') { |
|||
module.exports = require('./dist/pinia.prod.cjs') |
|||
} else { |
|||
module.exports = require('./dist/pinia.cjs') |
|||
} |
@ -0,0 +1,126 @@ |
|||
{ |
|||
"_from": "pinia", |
|||
"_id": "pinia@2.2.4", |
|||
"_inBundle": false, |
|||
"_integrity": "sha512-K7ZhpMY9iJ9ShTC0cR2+PnxdQRuwVIsXDO/WIEV/RnMC/vmSoKDTKW/exNQYPI+4ij10UjXqdNiEHwn47McANQ==", |
|||
"_location": "/pinia", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "tag", |
|||
"registry": true, |
|||
"raw": "pinia", |
|||
"name": "pinia", |
|||
"escapedName": "pinia", |
|||
"rawSpec": "", |
|||
"saveSpec": null, |
|||
"fetchSpec": "latest" |
|||
}, |
|||
"_requiredBy": [ |
|||
"#USER", |
|||
"/" |
|||
], |
|||
"_resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.2.4.tgz", |
|||
"_shasum": "79b63b231a3da80968ab58f7721f575fe2c509ac", |
|||
"_spec": "pinia", |
|||
"_where": "D:\\work\\questionbankvue3", |
|||
"author": { |
|||
"name": "Eduardo San Martin Morote", |
|||
"email": "posva13@gmail.com" |
|||
}, |
|||
"bugs": { |
|||
"url": "https://github.com/vuejs/pinia/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"dependencies": { |
|||
"@vue/devtools-api": "^6.6.3", |
|||
"vue-demi": "^0.14.10" |
|||
}, |
|||
"deprecated": false, |
|||
"description": "Intuitive, type safe and flexible Store for Vue", |
|||
"devDependencies": { |
|||
"@microsoft/api-extractor": "7.47.9", |
|||
"@vue/test-utils": "^2.4.6" |
|||
}, |
|||
"exports": { |
|||
".": { |
|||
"types": "./dist/pinia.d.ts", |
|||
"node": { |
|||
"import": { |
|||
"production": "./dist/pinia.prod.cjs", |
|||
"development": "./dist/pinia.mjs", |
|||
"default": "./dist/pinia.mjs" |
|||
}, |
|||
"require": { |
|||
"production": "./dist/pinia.prod.cjs", |
|||
"development": "./dist/pinia.cjs", |
|||
"default": "./index.js" |
|||
} |
|||
}, |
|||
"import": "./dist/pinia.mjs", |
|||
"require": "./index.js" |
|||
}, |
|||
"./package.json": "./package.json", |
|||
"./dist/*": "./dist/*" |
|||
}, |
|||
"files": [ |
|||
"dist/*.js", |
|||
"dist/*.mjs", |
|||
"dist/*.cjs", |
|||
"dist/pinia.d.ts", |
|||
"index.js", |
|||
"index.cjs", |
|||
"LICENSE", |
|||
"README.md" |
|||
], |
|||
"funding": "https://github.com/sponsors/posva", |
|||
"homepage": "https://github.com/vuejs/pinia#readme", |
|||
"jsdelivr": "dist/pinia.iife.js", |
|||
"keywords": [ |
|||
"vue", |
|||
"vuex", |
|||
"store", |
|||
"pinia", |
|||
"piña", |
|||
"pigna", |
|||
"composition", |
|||
"api", |
|||
"setup", |
|||
"typed", |
|||
"typescript", |
|||
"ts", |
|||
"type", |
|||
"safe" |
|||
], |
|||
"license": "MIT", |
|||
"main": "index.js", |
|||
"module": "dist/pinia.mjs", |
|||
"name": "pinia", |
|||
"peerDependencies": { |
|||
"@vue/composition-api": "^1.4.0", |
|||
"typescript": ">=4.4.4", |
|||
"vue": "^2.6.14 || ^3.3.0" |
|||
}, |
|||
"peerDependenciesMeta": { |
|||
"typescript": { |
|||
"optional": true |
|||
}, |
|||
"@vue/composition-api": { |
|||
"optional": true |
|||
} |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vuejs/pinia.git" |
|||
}, |
|||
"scripts": { |
|||
"build": "rimraf dist && rollup -c ../../rollup.config.mjs --environment TARGET:pinia", |
|||
"build:dts": "api-extractor run --local --verbose && tail -n +3 ./src/globalExtensions.ts >> dist/pinia.d.ts", |
|||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --commit-path . -l pinia -r 1", |
|||
"test": "pnpm run build && pnpm run build:dts && pnpm test:dts", |
|||
"test:dts": "tsc -p ./test-dts/tsconfig.json" |
|||
}, |
|||
"sideEffects": false, |
|||
"types": "dist/pinia.d.ts", |
|||
"unpkg": "dist/pinia.iife.js", |
|||
"version": "2.2.4" |
|||
} |
@ -0,0 +1,21 @@ |
|||
MIT License |
|||
|
|||
Copyright (c) 2020-present, Anthony Fu |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
@ -0,0 +1,229 @@ |
|||
<p align="center"> |
|||
<img src="https://github.com/vueuse/vue-demi/blob/main/assets/banner.png?raw=true" width="600"/> |
|||
<br> |
|||
<a href='https://www.npmjs.com/package/vue-demi'><img src='https://img.shields.io/npm/v/vue-demi?color=42b883' alt='npm'></a> |
|||
</p> |
|||
|
|||
<p align="center"> |
|||
<b>Vue Demi</b> (<i>half</i> in French) is a developing utility<br> allows you to write <b>Universal Vue Libraries</b> for Vue 2 & 3<br> |
|||
<i>See more details in <a href='https://antfu.me/posts/make-libraries-working-with-vue-2-and-3'>this blog post</a></i> |
|||
</p> |
|||
|
|||
<br> |
|||
|
|||
<br> |
|||
|
|||
## Strategies |
|||
|
|||
- `<=2.6`: exports from `vue` + `@vue/composition-api` with plugin auto installing. |
|||
- `2.7`: exports from `vue` (Composition API is built-in in Vue 2.7). |
|||
- `>=3.0`: exports from `vue`, with polyfill of Vue 2's `set` and `del` API. |
|||
|
|||
## Usage |
|||
|
|||
Install this as your plugin's dependency: |
|||
|
|||
```bash |
|||
npm i vue-demi |
|||
# or |
|||
yarn add vue-demi |
|||
# or |
|||
pnpm i vue-demi |
|||
``` |
|||
|
|||
Add `vue` and `@vue/composition-api` to your plugin's peer dependencies to specify what versions you support. |
|||
|
|||
```jsonc |
|||
{ |
|||
"dependencies": { |
|||
"vue-demi": "latest" |
|||
}, |
|||
"peerDependencies": { |
|||
"@vue/composition-api": "^1.0.0-rc.1", |
|||
"vue": "^2.0.0 || >=3.0.0" |
|||
}, |
|||
"peerDependenciesMeta": { |
|||
"@vue/composition-api": { |
|||
"optional": true |
|||
} |
|||
}, |
|||
"devDependencies": { |
|||
"vue": "^3.0.0" // or "^2.6.0" base on your preferred working environment |
|||
}, |
|||
} |
|||
``` |
|||
|
|||
Import everything related to Vue from it, it will redirect to `vue@2` + `@vue/composition-api` or `vue@3` based on users' environments. |
|||
|
|||
```ts |
|||
import { ref, reactive, defineComponent } from 'vue-demi' |
|||
``` |
|||
|
|||
Publish your plugin and all is done! |
|||
|
|||
> When using with [Vite](https://vitejs.dev), you will need to opt-out the pre-bundling to get `vue-demi` work properly by |
|||
> ```js |
|||
> // vite.config.js |
|||
> export default defineConfig({ |
|||
> optimizeDeps: { |
|||
> exclude: ['vue-demi'] |
|||
> } |
|||
> }) |
|||
> ``` |
|||
|
|||
### Extra APIs |
|||
|
|||
`Vue Demi` provides extra APIs to help distinguish users' environments and to do some version-specific logic. |
|||
|
|||
### `isVue2` `isVue3` |
|||
|
|||
```ts |
|||
import { isVue2, isVue3 } from 'vue-demi' |
|||
|
|||
if (isVue2) { |
|||
// Vue 2 only |
|||
} else { |
|||
// Vue 3 only |
|||
} |
|||
``` |
|||
|
|||
### `Vue2` |
|||
|
|||
To avoid bringing in all the tree-shakable modules, we provide a `Vue2` export to support access to Vue 2's global API. (See [#41](https://github.com/vueuse/vue-demi/issues/41).) |
|||
|
|||
```ts |
|||
import { Vue2 } from 'vue-demi' |
|||
|
|||
if (Vue2) { |
|||
Vue2.config.ignoredElements.push('x-foo') |
|||
} |
|||
``` |
|||
|
|||
### `install()` |
|||
|
|||
Composition API in Vue 2 is provided as a plugin and needs to be installed on the Vue instance before using. Normally, `vue-demi` will try to install it automatically. For some usages where you might need to ensure the plugin gets installed correctly, the `install()` API is exposed to as a safe version of `Vue.use(CompositionAPI)`. `install()` in the Vue 3 environment will be an empty function (no-op). |
|||
|
|||
```ts |
|||
import { install } from 'vue-demi' |
|||
|
|||
install() |
|||
``` |
|||
|
|||
## CLI |
|||
|
|||
### Manually Switch Versions |
|||
|
|||
To explicitly switch the redirecting version, you can use these commands in your project's root. |
|||
|
|||
```bash |
|||
npx vue-demi-switch 2 |
|||
# or |
|||
npx vue-demi-switch 3 |
|||
``` |
|||
|
|||
### Package Aliasing |
|||
|
|||
If you would like to import `vue` under an alias, you can use the following command |
|||
|
|||
```bash |
|||
npx vue-demi-switch 2 vue2 |
|||
# or |
|||
npx vue-demi-switch 3 vue3 |
|||
``` |
|||
|
|||
Then `vue-demi` will redirect APIs from the alias name you specified, for example: |
|||
|
|||
```ts |
|||
import * as Vue from 'vue3' |
|||
|
|||
var isVue2 = false |
|||
var isVue3 = true |
|||
var Vue2 = undefined |
|||
|
|||
export * from 'vue3' |
|||
export { |
|||
Vue, |
|||
Vue2, |
|||
isVue2, |
|||
isVue3, |
|||
} |
|||
``` |
|||
|
|||
### Auto Fix |
|||
|
|||
If the `postinstall` hook doesn't get triggered or you have updated the Vue version, try to run the following command to resolve the redirecting. |
|||
|
|||
```bash |
|||
npx vue-demi-fix |
|||
``` |
|||
|
|||
### Isomorphic Testings |
|||
|
|||
You can support testing for both versions by adding npm alias in your dev dependencies. For example: |
|||
|
|||
```json |
|||
{ |
|||
"scripts": { |
|||
"test:2": "vue-demi-switch 2 vue2 && jest", |
|||
"test:3": "vue-demi-switch 3 && jest", |
|||
}, |
|||
"devDependencies": { |
|||
"vue": "^3.0.0", |
|||
"vue2": "npm:vue@2" |
|||
}, |
|||
} |
|||
``` |
|||
|
|||
or |
|||
|
|||
```json |
|||
{ |
|||
"scripts": { |
|||
"test:2": "vue-demi-switch 2 && jest", |
|||
"test:3": "vue-demi-switch 3 vue3 && jest", |
|||
}, |
|||
"devDependencies": { |
|||
"vue": "^2.6.0", |
|||
"vue3": "npm:vue@3" |
|||
}, |
|||
} |
|||
``` |
|||
|
|||
## Examples |
|||
|
|||
See [examples](./examples). |
|||
|
|||
## Who is using this? |
|||
|
|||
- [VueUse](https://github.com/vueuse/vueuse) - Collection of Composition API utils |
|||
- [@vue/apollo-composable](https://github.com/vuejs/vue-apollo/tree/v4/packages/vue-apollo-composable) - Apollo GraphQL functions for Vue Composition API |
|||
- [vuelidate](https://github.com/vuelidate/vuelidate) - Simple, lightweight model-based validation |
|||
- [vue-composition-test-utils](https://github.com/ariesjia/vue-composition-test-utils) - Simple vue composition api unit test utilities |
|||
- [vue-use-stripe](https://github.com/frandiox/vue-use-stripe) - Stripe Elements wrapper for Vue.js |
|||
- [@opd/g2plot-vue](https://github.com/open-data-plan/g2plot-vue) - G2plot for vue |
|||
- [vue-echarts](https://github.com/ecomfe/vue-echarts) - Vue.js component for Apache ECharts. |
|||
- [fluent-vue](https://github.com/Demivan/fluent-vue) - Vue.js integration for [Fluent.js](https://github.com/projectfluent/fluent.js) - JavaScript implementation of [Project Fluent](https://projectfluent.org) |
|||
- [vue-datatable-url-sync](https://github.com/socotecio/vue-datatable-url-sync) - Synchronize datatable options and filters with the url to keep user preference even after refresh or navigation |
|||
- [vue-insta-stories](https://github.com/UnevenSoftware/vue-insta-stories) - Instagram stories in your vue projects. |
|||
- [vue-tiny-validate](https://github.com/FrontLabsOfficial/vue-tiny-validate) - Tiny Vue Validate Composition |
|||
- [v-perfect-signature](https://github.com/wobsoriano/v-perfect-signature) - Pressure-sensitive signature drawing for Vue 2 and 3 |
|||
- [vue-winbox](https://github.com/wobsoriano/vue-winbox) - A wrapper component for WinBox.js that adds the ability to mount Vue components. |
|||
- [vue-word-highlighter](https://github.com/kawamataryo/vue-word-highlighter) - The word highlighter library for Vue 2 and Vue 3 |
|||
- [vue-chart-3](https://github.com/victorgarciaesgi/vue-chart-3) - Vue.js component for Chart.js |
|||
- [json-editor-vue](https://github.com/cloydlau/json-editor-vue) - JSON editor & viewer for Vue 2 and 3. |
|||
- [kidar-echarts](https://github.com/kidarjs/kidar-echarts) - A simpler echarts component for Vue 2 and 3. |
|||
- [vue3-sketch-ruler](https://github.com/kakajun/vue3-sketch-ruler) - The zoom operation used for page presentation for Vue 2 and 3( Replace render function with template ) |
|||
- [vue-rough-notation](https://github.com/Leecason/vue-rough-notation) - RoughNotation wrapper component for Vue 2 and 3. |
|||
- [vue-request](https://github.com/AttoJS/vue-request) - Vue composition API for data fetching, supports SWR, polling, error retry, cache request, pagination, etc. |
|||
- [vue3-lazyload](https://github.com/murongg/vue3-lazyload) - A vue3.x image lazyload plugin. |
|||
- [vue-codemirror6](https://github.com/logue/vue-codemirror6) - CodeMirror6 component for Vue2 and 3. |
|||
- [@tanstack/vue-query](https://github.com/TanStack/query) - TanStack Query for Vue. |
|||
> open a PR to add your library ;) |
|||
|
|||
## Underhood |
|||
|
|||
See [the blog post](https://antfu.me/posts/make-libraries-working-with-vue-2-and-3/#-introducing-vue-demi). |
|||
|
|||
## License |
|||
|
|||
MIT License © 2020 [Anthony Fu](https://github.com/antfu) |
@ -0,0 +1,3 @@ |
|||
#!/usr/bin/env node
|
|||
'use strict' |
|||
require('../scripts/postinstall') |
@ -0,0 +1,3 @@ |
|||
#!/usr/bin/env node
|
|||
'use strict' |
|||
require('../scripts/switch-cli') |
@ -0,0 +1,29 @@ |
|||
var Vue = require('vue') |
|||
|
|||
Object.keys(Vue).forEach(function(key) { |
|||
exports[key] = Vue[key] |
|||
}) |
|||
|
|||
exports.set = function(target, key, val) { |
|||
if (Array.isArray(target)) { |
|||
target.length = Math.max(target.length, key) |
|||
target.splice(key, 1, val) |
|||
return val |
|||
} |
|||
target[key] = val |
|||
return val |
|||
} |
|||
|
|||
exports.del = function(target, key) { |
|||
if (Array.isArray(target)) { |
|||
target.splice(key, 1) |
|||
return |
|||
} |
|||
delete target[key] |
|||
} |
|||
|
|||
exports.Vue = Vue |
|||
exports.Vue2 = undefined |
|||
exports.isVue2 = false |
|||
exports.isVue3 = true |
|||
exports.install = function(){} |
@ -0,0 +1,22 @@ |
|||
import * as Vue from 'vue' |
|||
declare const isVue2: boolean |
|||
declare const isVue3: boolean |
|||
declare const Vue2: any |
|||
declare const install: (vue?: any) => void |
|||
/** |
|||
* @deprecated To avoid bringing in all the tree-shakable modules, this API has been deprecated. Use `Vue2` or named exports instead. |
|||
* Refer to https://github.com/vueuse/vue-demi/issues/41
|
|||
*/ |
|||
declare const V: typeof Vue |
|||
|
|||
export function set<T>(target: any, key: any, val: T): T |
|||
export function del(target: any, key: any): void |
|||
|
|||
export * from 'vue' |
|||
export { |
|||
V as Vue, |
|||
Vue2, |
|||
isVue2, |
|||
isVue3, |
|||
install, |
|||
} |
@ -0,0 +1,126 @@ |
|||
var _VueDemiGlobal = typeof globalThis !== 'undefined' |
|||
? globalThis |
|||
: typeof global !== 'undefined' |
|||
? global |
|||
: typeof self !== 'undefined' |
|||
? self |
|||
: this |
|||
var VueDemi = (function (VueDemi, Vue, VueCompositionAPI) { |
|||
if (VueDemi.install) { |
|||
return VueDemi |
|||
} |
|||
if (!Vue) { |
|||
console.error('[vue-demi] no Vue instance found, please be sure to import `vue` before `vue-demi`.') |
|||
return VueDemi |
|||
} |
|||
|
|||
// Vue 2.7
|
|||
if (Vue.version.slice(0, 4) === '2.7.') { |
|||
for (var key in Vue) { |
|||
VueDemi[key] = Vue[key] |
|||
} |
|||
VueDemi.isVue2 = true |
|||
VueDemi.isVue3 = false |
|||
VueDemi.install = function () {} |
|||
VueDemi.Vue = Vue |
|||
VueDemi.Vue2 = Vue |
|||
VueDemi.version = Vue.version |
|||
VueDemi.warn = Vue.util.warn |
|||
VueDemi.hasInjectionContext = function() { |
|||
return !!VueDemi.getCurrentInstance() |
|||
} |
|||
function createApp(rootComponent, rootProps) { |
|||
var vm |
|||
var provide = {} |
|||
var app = { |
|||
config: Vue.config, |
|||
use: Vue.use.bind(Vue), |
|||
mixin: Vue.mixin.bind(Vue), |
|||
component: Vue.component.bind(Vue), |
|||
provide: function (key, value) { |
|||
provide[key] = value |
|||
return this |
|||
}, |
|||
directive: function (name, dir) { |
|||
if (dir) { |
|||
Vue.directive(name, dir) |
|||
return app |
|||
} else { |
|||
return Vue.directive(name) |
|||
} |
|||
}, |
|||
mount: function (el, hydrating) { |
|||
if (!vm) { |
|||
vm = new Vue(Object.assign({ propsData: rootProps }, rootComponent, { provide: Object.assign(provide, rootComponent.provide) })) |
|||
vm.$mount(el, hydrating) |
|||
return vm |
|||
} else { |
|||
return vm |
|||
} |
|||
}, |
|||
unmount: function () { |
|||
if (vm) { |
|||
vm.$destroy() |
|||
vm = undefined |
|||
} |
|||
}, |
|||
} |
|||
return app |
|||
} |
|||
VueDemi.createApp = createApp |
|||
} |
|||
// Vue 2.6.x
|
|||
else if (Vue.version.slice(0, 2) === '2.') { |
|||
if (VueCompositionAPI) { |
|||
for (var key in VueCompositionAPI) { |
|||
VueDemi[key] = VueCompositionAPI[key] |
|||
} |
|||
VueDemi.isVue2 = true |
|||
VueDemi.isVue3 = false |
|||
VueDemi.install = function () {} |
|||
VueDemi.Vue = Vue |
|||
VueDemi.Vue2 = Vue |
|||
VueDemi.version = Vue.version |
|||
VueDemi.hasInjectionContext = function() { |
|||
return !!VueDemi.getCurrentInstance() |
|||
} |
|||
} else { |
|||
console.error('[vue-demi] no VueCompositionAPI instance found, please be sure to import `@vue/composition-api` before `vue-demi`.') |
|||
} |
|||
} |
|||
// Vue 3
|
|||
else if (Vue.version.slice(0, 2) === '3.') { |
|||
for (var key in Vue) { |
|||
VueDemi[key] = Vue[key] |
|||
} |
|||
VueDemi.isVue2 = false |
|||
VueDemi.isVue3 = true |
|||
VueDemi.install = function () {} |
|||
VueDemi.Vue = Vue |
|||
VueDemi.Vue2 = undefined |
|||
VueDemi.version = Vue.version |
|||
VueDemi.set = function (target, key, val) { |
|||
if (Array.isArray(target)) { |
|||
target.length = Math.max(target.length, key) |
|||
target.splice(key, 1, val) |
|||
return val |
|||
} |
|||
target[key] = val |
|||
return val |
|||
} |
|||
VueDemi.del = function (target, key) { |
|||
if (Array.isArray(target)) { |
|||
target.splice(key, 1) |
|||
return |
|||
} |
|||
delete target[key] |
|||
} |
|||
} else { |
|||
console.error('[vue-demi] Vue version ' + Vue.version + ' is unsupported.') |
|||
} |
|||
return VueDemi |
|||
})( |
|||
(_VueDemiGlobal.VueDemi = _VueDemiGlobal.VueDemi || (typeof VueDemi !== 'undefined' ? VueDemi : {})), |
|||
_VueDemiGlobal.Vue || (typeof Vue !== 'undefined' ? Vue : undefined), |
|||
_VueDemiGlobal.VueCompositionAPI || (typeof VueCompositionAPI !== 'undefined' ? VueCompositionAPI : undefined) |
|||
); |
@ -0,0 +1,34 @@ |
|||
import * as Vue from 'vue' |
|||
|
|||
var isVue2 = false |
|||
var isVue3 = true |
|||
var Vue2 = undefined |
|||
|
|||
function install() {} |
|||
|
|||
export function set(target, key, val) { |
|||
if (Array.isArray(target)) { |
|||
target.length = Math.max(target.length, key) |
|||
target.splice(key, 1, val) |
|||
return val |
|||
} |
|||
target[key] = val |
|||
return val |
|||
} |
|||
|
|||
export function del(target, key) { |
|||
if (Array.isArray(target)) { |
|||
target.splice(key, 1) |
|||
return |
|||
} |
|||
delete target[key] |
|||
} |
|||
|
|||
export * from 'vue' |
|||
export { |
|||
Vue, |
|||
Vue2, |
|||
isVue2, |
|||
isVue3, |
|||
install, |
|||
} |
@ -0,0 +1,60 @@ |
|||
var VueModule = require('vue') |
|||
|
|||
// get the real Vue https://github.com/vueuse/vue-demi/issues/192 |
|||
var Vue = VueModule.default || VueModule |
|||
|
|||
exports.Vue = Vue |
|||
exports.Vue2 = Vue |
|||
exports.isVue2 = true |
|||
exports.isVue3 = false |
|||
exports.install = function () {} |
|||
exports.warn = Vue.util.warn |
|||
|
|||
// createApp polyfill |
|||
exports.createApp = function (rootComponent, rootProps) { |
|||
var vm |
|||
var provide = {} |
|||
var app = { |
|||
config: Vue.config, |
|||
use: Vue.use.bind(Vue), |
|||
mixin: Vue.mixin.bind(Vue), |
|||
component: Vue.component.bind(Vue), |
|||
provide: function (key, value) { |
|||
provide[key] = value |
|||
return this |
|||
}, |
|||
directive: function (name, dir) { |
|||
if (dir) { |
|||
Vue.directive(name, dir) |
|||
return app |
|||
} else { |
|||
return Vue.directive(name) |
|||
} |
|||
}, |
|||
mount: function (el, hydrating) { |
|||
if (!vm) { |
|||
vm = new Vue(Object.assign({ propsData: rootProps }, rootComponent, { provide: Object.assign(provide, rootComponent.provide) })) |
|||
vm.$mount(el, hydrating) |
|||
return vm |
|||
} else { |
|||
return vm |
|||
} |
|||
}, |
|||
unmount: function () { |
|||
if (vm) { |
|||
vm.$destroy() |
|||
vm = undefined |
|||
} |
|||
}, |
|||
} |
|||
return app |
|||
} |
|||
|
|||
Object.keys(VueModule).forEach(function (key) { |
|||
exports[key] = VueModule[key] |
|||
}) |
|||
|
|||
// Not implemented https://github.com/vuejs/core/pull/8111, falls back to getCurrentInstance() |
|||
exports.hasInjectionContext = function() { |
|||
return !!VueModule.getCurrentInstance() |
|||
} |
@ -0,0 +1,38 @@ |
|||
import Vue from 'vue' |
|||
import type { PluginFunction, PluginObject, VueConstructor, Directive, InjectionKey, Component } from 'vue' |
|||
|
|||
declare const isVue2: boolean |
|||
declare const isVue3: boolean |
|||
declare const Vue2: typeof Vue | undefined |
|||
declare const version: string |
|||
declare const install: (vue?: typeof Vue) => void |
|||
export declare function warn(msg: string, vm?: Component | null): void |
|||
/** |
|||
* @deprecated To avoid bringing in all the tree-shakable modules, this API has been deprecated. Use `Vue2` or named exports instead. |
|||
* Refer to https://github.com/vueuse/vue-demi/issues/41
|
|||
*/ |
|||
declare const V: typeof Vue |
|||
|
|||
// accept no generic because Vue 3 doesn't accept any
|
|||
// https://github.com/vuejs/vue-next/pull/2758/
|
|||
export declare type Plugin = PluginObject<any> | PluginFunction<any> |
|||
export type { VNode } from 'vue' |
|||
export * from 'vue' |
|||
export { V as Vue, Vue2, isVue2, isVue3, version, install } |
|||
|
|||
// #region createApp polyfill
|
|||
export interface App<T = any> { |
|||
config: VueConstructor['config'] |
|||
use: VueConstructor['use'] |
|||
mixin: VueConstructor['mixin'] |
|||
component: VueConstructor['component'] |
|||
directive(name: string): Directive | undefined |
|||
directive(name: string, directive: Directive): this |
|||
provide<T>(key: InjectionKey<T> | string, value: T): this |
|||
mount: Vue['$mount'] |
|||
unmount: Vue['$destroy'] |
|||
} |
|||
export declare function createApp(rootComponent: any, rootProps?: any): App |
|||
// #endregion
|
|||
|
|||
export declare function hasInjectionContext(): boolean |
@ -0,0 +1,80 @@ |
|||
import Vue from 'vue' |
|||
import { getCurrentInstance } from 'vue' |
|||
|
|||
var isVue2 = true |
|||
var isVue3 = false |
|||
var Vue2 = Vue |
|||
var warn = Vue.util.warn |
|||
|
|||
function install() {} |
|||
|
|||
// createApp polyfill |
|||
export function createApp(rootComponent, rootProps) { |
|||
var vm |
|||
var provide = {} |
|||
var app = { |
|||
config: Vue.config, |
|||
use: Vue.use.bind(Vue), |
|||
mixin: Vue.mixin.bind(Vue), |
|||
component: Vue.component.bind(Vue), |
|||
provide: function (key, value) { |
|||
provide[key] = value |
|||
return this |
|||
}, |
|||
directive: function (name, dir) { |
|||
if (dir) { |
|||
Vue.directive(name, dir) |
|||
return app |
|||
} else { |
|||
return Vue.directive(name) |
|||
} |
|||
}, |
|||
mount: function (el, hydrating) { |
|||
if (!vm) { |
|||
vm = new Vue(Object.assign({ propsData: rootProps }, rootComponent, { provide: Object.assign(provide, rootComponent.provide) })) |
|||
vm.$mount(el, hydrating) |
|||
return vm |
|||
} else { |
|||
return vm |
|||
} |
|||
}, |
|||
unmount: function () { |
|||
if (vm) { |
|||
vm.$destroy() |
|||
vm = undefined |
|||
} |
|||
}, |
|||
} |
|||
return app |
|||
} |
|||
|
|||
export { |
|||
Vue, |
|||
Vue2, |
|||
isVue2, |
|||
isVue3, |
|||
install, |
|||
warn |
|||
} |
|||
|
|||
// Vue 3 components mock |
|||
function createMockComponent(name) { |
|||
return { |
|||
setup() { |
|||
throw new Error('[vue-demi] ' + name + ' is not supported in Vue 2. It\'s provided to avoid compiler errors.') |
|||
} |
|||
} |
|||
} |
|||
export var Fragment = /*#__PURE__*/ createMockComponent('Fragment') |
|||
export var Transition = /*#__PURE__*/ createMockComponent('Transition') |
|||
export var TransitionGroup = /*#__PURE__*/ createMockComponent('TransitionGroup') |
|||
export var Teleport = /*#__PURE__*/ createMockComponent('Teleport') |
|||
export var Suspense = /*#__PURE__*/ createMockComponent('Suspense') |
|||
export var KeepAlive = /*#__PURE__*/ createMockComponent('KeepAlive') |
|||
|
|||
export * from 'vue' |
|||
|
|||
// Not implemented https://github.com/vuejs/core/pull/8111, falls back to getCurrentInstance() |
|||
export function hasInjectionContext() { |
|||
return !!getCurrentInstance() |
|||
} |
@ -0,0 +1,34 @@ |
|||
var Vue = require('vue') |
|||
var VueCompositionAPI = require('@vue/composition-api') |
|||
|
|||
function install(_vue) { |
|||
var vueLib = _vue || Vue |
|||
if (vueLib && 'default' in vueLib) { |
|||
vueLib = vueLib.default |
|||
} |
|||
|
|||
if (vueLib && !vueLib['__composition_api_installed__']) { |
|||
if (VueCompositionAPI && 'default' in VueCompositionAPI) |
|||
vueLib.use(VueCompositionAPI.default) |
|||
else if (VueCompositionAPI) |
|||
vueLib.use(VueCompositionAPI) |
|||
} |
|||
} |
|||
|
|||
install(Vue) |
|||
|
|||
Object.keys(VueCompositionAPI).forEach(function(key) { |
|||
exports[key] = VueCompositionAPI[key] |
|||
}) |
|||
|
|||
exports.Vue = Vue |
|||
exports.Vue2 = Vue |
|||
exports.isVue2 = true |
|||
exports.isVue3 = false |
|||
exports.install = install |
|||
exports.version = Vue.version |
|||
|
|||
// Not implemented https://github.com/vuejs/core/pull/8111, falls back to getCurrentInstance() |
|||
exports.hasInjectionContext = function () { |
|||
return !!VueCompositionAPI.getCurrentInstance() |
|||
} |
@ -0,0 +1,33 @@ |
|||
import Vue from 'vue' |
|||
import type { PluginFunction, PluginObject } from 'vue' |
|||
declare const isVue2: boolean |
|||
declare const isVue3: boolean |
|||
declare const Vue2: typeof Vue | undefined |
|||
declare const version: string |
|||
declare const install: (vue?: typeof Vue) => void |
|||
/** |
|||
* @deprecated To avoid bringing in all the tree-shakable modules, this API has been deprecated. Use `Vue2` or named exports instead. |
|||
* Refer to https://github.com/vueuse/vue-demi/issues/41
|
|||
*/ |
|||
declare const V: typeof Vue |
|||
|
|||
/** |
|||
* DebuggerEvent is a Vue 3 development only feature. This type cannot exist in Vue 2. |
|||
*/ |
|||
export declare type DebuggerEvent = never |
|||
|
|||
// accept no generic because Vue 3 doesn't accept any
|
|||
// https://github.com/vuejs/vue-next/pull/2758/
|
|||
export declare type Plugin = PluginObject<any> | PluginFunction<any> |
|||
export type { VNode } from 'vue' |
|||
export * from '@vue/composition-api' |
|||
export { |
|||
V as Vue, |
|||
Vue2, |
|||
isVue2, |
|||
isVue3, |
|||
version, |
|||
install, |
|||
} |
|||
|
|||
export declare function hasInjectionContext(): boolean |
@ -0,0 +1,49 @@ |
|||
import Vue from 'vue' |
|||
import VueCompositionAPI, { getCurrentInstance } from '@vue/composition-api/dist/vue-composition-api.mjs' |
|||
|
|||
function install(_vue) { |
|||
_vue = _vue || Vue |
|||
if (_vue && !_vue['__composition_api_installed__']) |
|||
_vue.use(VueCompositionAPI) |
|||
} |
|||
|
|||
install(Vue) |
|||
|
|||
var isVue2 = true |
|||
var isVue3 = false |
|||
var Vue2 = Vue |
|||
var version = Vue.version |
|||
|
|||
/**VCA-EXPORTS**/ |
|||
export * from '@vue/composition-api/dist/vue-composition-api.mjs' |
|||
/**VCA-EXPORTS**/ |
|||
|
|||
export { |
|||
Vue, |
|||
Vue2, |
|||
isVue2, |
|||
isVue3, |
|||
version, |
|||
install, |
|||
} |
|||
|
|||
|
|||
// Vue 3 components mock |
|||
function createMockComponent(name) { |
|||
return { |
|||
setup() { |
|||
throw new Error('[vue-demi] ' + name + ' is not supported in Vue 2. It\'s provided to avoid compiler errors.') |
|||
} |
|||
} |
|||
} |
|||
export var Fragment = /*#__PURE__*/ createMockComponent('Fragment') |
|||
export var Transition = /*#__PURE__*/ createMockComponent('Transition') |
|||
export var TransitionGroup = /*#__PURE__*/ createMockComponent('TransitionGroup') |
|||
export var Teleport = /*#__PURE__*/ createMockComponent('Teleport') |
|||
export var Suspense = /*#__PURE__*/ createMockComponent('Suspense') |
|||
export var KeepAlive = /*#__PURE__*/ createMockComponent('KeepAlive') |
|||
|
|||
// Not implemented https://github.com/vuejs/core/pull/8111, falls back to getCurrentInstance() |
|||
export function hasInjectionContext() { |
|||
return !!getCurrentInstance() |
|||
} |
@ -0,0 +1,29 @@ |
|||
var Vue = require('vue') |
|||
|
|||
Object.keys(Vue).forEach(function(key) { |
|||
exports[key] = Vue[key] |
|||
}) |
|||
|
|||
exports.set = function(target, key, val) { |
|||
if (Array.isArray(target)) { |
|||
target.length = Math.max(target.length, key) |
|||
target.splice(key, 1, val) |
|||
return val |
|||
} |
|||
target[key] = val |
|||
return val |
|||
} |
|||
|
|||
exports.del = function(target, key) { |
|||
if (Array.isArray(target)) { |
|||
target.splice(key, 1) |
|||
return |
|||
} |
|||
delete target[key] |
|||
} |
|||
|
|||
exports.Vue = Vue |
|||
exports.Vue2 = undefined |
|||
exports.isVue2 = false |
|||
exports.isVue3 = true |
|||
exports.install = function(){} |
@ -0,0 +1,22 @@ |
|||
import * as Vue from 'vue' |
|||
declare const isVue2: boolean |
|||
declare const isVue3: boolean |
|||
declare const Vue2: any |
|||
declare const install: (vue?: any) => void |
|||
/** |
|||
* @deprecated To avoid bringing in all the tree-shakable modules, this API has been deprecated. Use `Vue2` or named exports instead. |
|||
* Refer to https://github.com/vueuse/vue-demi/issues/41
|
|||
*/ |
|||
declare const V: typeof Vue |
|||
|
|||
export function set<T>(target: any, key: any, val: T): T |
|||
export function del(target: any, key: any): void |
|||
|
|||
export * from 'vue' |
|||
export { |
|||
V as Vue, |
|||
Vue2, |
|||
isVue2, |
|||
isVue3, |
|||
install, |
|||
} |
@ -0,0 +1,34 @@ |
|||
import * as Vue from 'vue' |
|||
|
|||
var isVue2 = false |
|||
var isVue3 = true |
|||
var Vue2 = undefined |
|||
|
|||
function install() {} |
|||
|
|||
export function set(target, key, val) { |
|||
if (Array.isArray(target)) { |
|||
target.length = Math.max(target.length, key) |
|||
target.splice(key, 1, val) |
|||
return val |
|||
} |
|||
target[key] = val |
|||
return val |
|||
} |
|||
|
|||
export function del(target, key) { |
|||
if (Array.isArray(target)) { |
|||
target.splice(key, 1) |
|||
return |
|||
} |
|||
delete target[key] |
|||
} |
|||
|
|||
export * from 'vue' |
|||
export { |
|||
Vue, |
|||
Vue2, |
|||
isVue2, |
|||
isVue3, |
|||
install, |
|||
} |
@ -0,0 +1,83 @@ |
|||
{ |
|||
"_from": "vue-demi@^0.14.10", |
|||
"_id": "vue-demi@0.14.10", |
|||
"_inBundle": false, |
|||
"_integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", |
|||
"_location": "/vue-demi", |
|||
"_phantomChildren": {}, |
|||
"_requested": { |
|||
"type": "range", |
|||
"registry": true, |
|||
"raw": "vue-demi@^0.14.10", |
|||
"name": "vue-demi", |
|||
"escapedName": "vue-demi", |
|||
"rawSpec": "^0.14.10", |
|||
"saveSpec": null, |
|||
"fetchSpec": "^0.14.10" |
|||
}, |
|||
"_requiredBy": [ |
|||
"/pinia" |
|||
], |
|||
"_resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", |
|||
"_shasum": "afc78de3d6f9e11bf78c55e8510ee12814522f04", |
|||
"_spec": "vue-demi@^0.14.10", |
|||
"_where": "D:\\work\\questionbankvue3\\node_modules\\pinia", |
|||
"author": { |
|||
"name": "Anthony Fu", |
|||
"email": "anthonyfu117@hotmail.com" |
|||
}, |
|||
"bin": { |
|||
"vue-demi-fix": "bin/vue-demi-fix.js", |
|||
"vue-demi-switch": "bin/vue-demi-switch.js" |
|||
}, |
|||
"bugs": { |
|||
"url": "https://github.com/antfu/vue-demi/issues" |
|||
}, |
|||
"bundleDependencies": false, |
|||
"deprecated": false, |
|||
"description": "<p align=\"center\"> <img src=\"https://github.com/vueuse/vue-demi/blob/main/assets/banner.png?raw=true\" width=\"600\"/> <br> <a href='https://www.npmjs.com/package/vue-demi'><img src='https://img.shields.io/npm/v/vue-demi?color=42b883' alt='npm'></a> </p>", |
|||
"engines": { |
|||
"node": ">=12" |
|||
}, |
|||
"exports": { |
|||
".": { |
|||
"types": "./lib/index.d.ts", |
|||
"require": "./lib/index.cjs", |
|||
"import": "./lib/index.mjs", |
|||
"browser": "./lib/index.mjs" |
|||
}, |
|||
"./*": "./*" |
|||
}, |
|||
"files": [ |
|||
"lib", |
|||
"bin", |
|||
"scripts" |
|||
], |
|||
"funding": "https://github.com/sponsors/antfu", |
|||
"homepage": "https://github.com/antfu/vue-demi#readme", |
|||
"jsdelivr": "lib/index.iife.js", |
|||
"license": "MIT", |
|||
"main": "lib/index.cjs", |
|||
"module": "lib/index.mjs", |
|||
"name": "vue-demi", |
|||
"peerDependencies": { |
|||
"@vue/composition-api": "^1.0.0-rc.1", |
|||
"vue": "^3.0.0-0 || ^2.6.0" |
|||
}, |
|||
"peerDependenciesMeta": { |
|||
"@vue/composition-api": { |
|||
"optional": true |
|||
} |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/antfu/vue-demi.git" |
|||
}, |
|||
"scripts": { |
|||
"postinstall": "node -e \"try{require('./scripts/postinstall.js')}catch(e){}\"", |
|||
"release": "npx bumpp --tag --commit --push && npm publish" |
|||
}, |
|||
"types": "lib/index.d.ts", |
|||
"unpkg": "lib/index.iife.js", |
|||
"version": "0.14.10" |
|||
} |
@ -0,0 +1,19 @@ |
|||
const { switchVersion, loadModule } = require('./utils') |
|||
|
|||
const Vue = loadModule('vue') |
|||
|
|||
if (!Vue || typeof Vue.version !== 'string') { |
|||
console.warn('[vue-demi] Vue is not found. Please run "npm install vue" to install.') |
|||
} |
|||
else if (Vue.version.startsWith('2.7.')) { |
|||
switchVersion(2.7) |
|||
} |
|||
else if (Vue.version.startsWith('2.')) { |
|||
switchVersion(2) |
|||
} |
|||
else if (Vue.version.startsWith('3.')) { |
|||
switchVersion(3) |
|||
} |
|||
else { |
|||
console.warn(`[vue-demi] Vue version v${Vue.version} is not supported.`) |
|||
} |
@ -0,0 +1,18 @@ |
|||
const { switchVersion } = require('./utils') |
|||
|
|||
const version = process.argv[2] |
|||
const vueEntry = process.argv[3] || 'vue' |
|||
|
|||
if (version === '2.7') { |
|||
switchVersion(2.7, vueEntry) |
|||
console.log(`[vue-demi] Switched for Vue 2.7 (entry: "${vueEntry}")`) |
|||
} else if (version === '2') { |
|||
switchVersion(2, vueEntry) |
|||
console.log(`[vue-demi] Switched for Vue 2 (entry: "${vueEntry}")`) |
|||
} else if (version === '3') { |
|||
switchVersion(3, vueEntry) |
|||
console.log(`[vue-demi] Switched for Vue 3 (entry: "${vueEntry}")`) |
|||
} else { |
|||
console.warn(`[vue-demi] expecting version "2" or "2.7" or "3" but got "${version}"`) |
|||
process.exit(1) |
|||
} |
@ -0,0 +1,62 @@ |
|||
const fs = require('fs') |
|||
const path = require('path') |
|||
|
|||
const dir = path.resolve(__dirname, '..', 'lib') |
|||
|
|||
function loadModule(name) { |
|||
try { |
|||
return require(name) |
|||
} catch (e) { |
|||
return undefined |
|||
} |
|||
} |
|||
|
|||
function copy(name, version, vue) { |
|||
vue = vue || 'vue' |
|||
const src = path.join(dir, `v${version}`, name) |
|||
const dest = path.join(dir, name) |
|||
let content = fs.readFileSync(src, 'utf-8') |
|||
content = content.replace(/'vue'/g, `'${vue}'`) |
|||
// unlink for pnpm, #92
|
|||
try { |
|||
fs.unlinkSync(dest) |
|||
} catch (error) { } |
|||
fs.writeFileSync(dest, content, 'utf-8') |
|||
} |
|||
|
|||
function updateVue2API() { |
|||
const ignoreList = ['version', 'default'] |
|||
const VCA = loadModule('@vue/composition-api') |
|||
if (!VCA) { |
|||
console.warn('[vue-demi] Composition API plugin is not found. Please run "npm install @vue/composition-api" to install.') |
|||
return |
|||
} |
|||
|
|||
const exports = Object.keys(VCA).filter(i => !ignoreList.includes(i)) |
|||
|
|||
const esmPath = path.join(dir, 'index.mjs') |
|||
let content = fs.readFileSync(esmPath, 'utf-8') |
|||
|
|||
content = content.replace( |
|||
/\/\*\*VCA-EXPORTS\*\*\/[\s\S]+\/\*\*VCA-EXPORTS\*\*\//m, |
|||
`/**VCA-EXPORTS**/
|
|||
export { ${exports.join(', ')} } from '@vue/composition-api/dist/vue-composition-api.mjs' |
|||
/**VCA-EXPORTS**/`
|
|||
) |
|||
|
|||
fs.writeFileSync(esmPath, content, 'utf-8') |
|||
|
|||
} |
|||
|
|||
function switchVersion(version, vue) { |
|||
copy('index.cjs', version, vue) |
|||
copy('index.mjs', version, vue) |
|||
copy('index.d.ts', version, vue) |
|||
|
|||
if (version === 2) |
|||
updateVue2API() |
|||
} |
|||
|
|||
|
|||
module.exports.loadModule = loadModule |
|||
module.exports.switchVersion = switchVersion |
@ -1,21 +1,30 @@ |
|||
{ |
|||
"name": "questionbankvue3", |
|||
"version": "1.0.0", |
|||
"lockfileVersion": 3, |
|||
"lockfileVersion": 1, |
|||
"requires": true, |
|||
"packages": { |
|||
"": { |
|||
"name": "questionbankvue3", |
|||
"version": "1.0.0", |
|||
"license": "ISC", |
|||
"dependencies": { |
|||
"js-md5": "^0.8.3" |
|||
"dependencies": { |
|||
"@vue/devtools-api": { |
|||
"version": "6.6.4", |
|||
"resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", |
|||
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==" |
|||
}, |
|||
"js-md5": { |
|||
"version": "0.8.3" |
|||
}, |
|||
"pinia": { |
|||
"version": "2.2.4", |
|||
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.2.4.tgz", |
|||
"integrity": "sha512-K7ZhpMY9iJ9ShTC0cR2+PnxdQRuwVIsXDO/WIEV/RnMC/vmSoKDTKW/exNQYPI+4ij10UjXqdNiEHwn47McANQ==", |
|||
"requires": { |
|||
"@vue/devtools-api": "^6.6.3", |
|||
"vue-demi": "^0.14.10" |
|||
} |
|||
}, |
|||
"node_modules/js-md5": { |
|||
"version": "0.8.3", |
|||
"resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz", |
|||
"integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==" |
|||
"vue-demi": { |
|||
"version": "0.14.10", |
|||
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", |
|||
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==" |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,9 @@ |
|||
|
|||
import {createPinia} from 'pinia'; |
|||
|
|||
export const store = createPinia(); |
|||
|
|||
// 全局挂载store
|
|||
export function setupStore(app) { |
|||
app.use(store); |
|||
} |
@ -0,0 +1,18 @@ |
|||
import {defineStore} from 'pinia'; |
|||
|
|||
const carStore = defineStore( |
|||
'car', |
|||
{ |
|||
state: () => ({ |
|||
carInfo: { |
|||
name: 'joe' |
|||
} |
|||
}), |
|||
actions: { |
|||
setCar(key, value) { |
|||
this.carInfo[key] = value |
|||
}, |
|||
} |
|||
}) |
|||
|
|||
export default carStore |
Write
Preview
Loading…
Cancel
Save
Reference in new issue