532 lines
17 KiB
JavaScript
532 lines
17 KiB
JavaScript
import { isBrowser, target } from "@vue/devtools-shared";
|
|
import { DevToolsContextHookKeys, DevToolsMessagingHookKeys, createRpcClient, createRpcServer, devtools, devtoolsRouter, devtoolsRouterInfo, getActiveInspectors, getInspector, getInspectorActions, getInspectorInfo, getInspectorNodeActions, getRpcClient, getRpcServer, getViteRpcClient, stringify, toggleClientConnected, updateDevToolsClientDetected, updateTimelineLayersState } from "@vue/devtools-kit";
|
|
import { computed, inject, onUnmounted, ref, watch } from "vue";
|
|
|
|
//#region src/client.ts
|
|
function setDevToolsClientUrl(url) {
|
|
target.__VUE_DEVTOOLS_CLIENT_URL__ = url;
|
|
}
|
|
function getDevToolsClientUrl() {
|
|
return target.__VUE_DEVTOOLS_CLIENT_URL__ ?? (() => {
|
|
if (isBrowser) {
|
|
const devtoolsMeta = document.querySelector("meta[name=__VUE_DEVTOOLS_CLIENT_URL__]");
|
|
if (devtoolsMeta) return devtoolsMeta.getAttribute("content");
|
|
}
|
|
return "";
|
|
})();
|
|
}
|
|
|
|
//#endregion
|
|
//#region ../../node_modules/.pnpm/hookable@5.5.3/node_modules/hookable/dist/index.mjs
|
|
function flatHooks(configHooks, hooks$2 = {}, parentName) {
|
|
for (const key in configHooks) {
|
|
const subHook = configHooks[key];
|
|
const name = parentName ? `${parentName}:${key}` : key;
|
|
if (typeof subHook === "object" && subHook !== null) flatHooks(subHook, hooks$2, name);
|
|
else if (typeof subHook === "function") hooks$2[name] = subHook;
|
|
}
|
|
return hooks$2;
|
|
}
|
|
const defaultTask = { run: (function_) => function_() };
|
|
const _createTask = () => defaultTask;
|
|
const createTask = typeof console.createTask !== "undefined" ? console.createTask : _createTask;
|
|
function serialTaskCaller(hooks$2, args) {
|
|
const task = createTask(args.shift());
|
|
return hooks$2.reduce((promise, hookFunction) => promise.then(() => task.run(() => hookFunction(...args))), Promise.resolve());
|
|
}
|
|
function parallelTaskCaller(hooks$2, args) {
|
|
const task = createTask(args.shift());
|
|
return Promise.all(hooks$2.map((hook) => task.run(() => hook(...args))));
|
|
}
|
|
function callEachWith(callbacks, arg0) {
|
|
for (const callback of [...callbacks]) callback(arg0);
|
|
}
|
|
var Hookable = class {
|
|
constructor() {
|
|
this._hooks = {};
|
|
this._before = void 0;
|
|
this._after = void 0;
|
|
this._deprecatedMessages = void 0;
|
|
this._deprecatedHooks = {};
|
|
this.hook = this.hook.bind(this);
|
|
this.callHook = this.callHook.bind(this);
|
|
this.callHookWith = this.callHookWith.bind(this);
|
|
}
|
|
hook(name, function_, options = {}) {
|
|
if (!name || typeof function_ !== "function") return () => {};
|
|
const originalName = name;
|
|
let dep;
|
|
while (this._deprecatedHooks[name]) {
|
|
dep = this._deprecatedHooks[name];
|
|
name = dep.to;
|
|
}
|
|
if (dep && !options.allowDeprecated) {
|
|
let message = dep.message;
|
|
if (!message) message = `${originalName} hook has been deprecated` + (dep.to ? `, please use ${dep.to}` : "");
|
|
if (!this._deprecatedMessages) this._deprecatedMessages = /* @__PURE__ */ new Set();
|
|
if (!this._deprecatedMessages.has(message)) {
|
|
console.warn(message);
|
|
this._deprecatedMessages.add(message);
|
|
}
|
|
}
|
|
if (!function_.name) try {
|
|
Object.defineProperty(function_, "name", {
|
|
get: () => "_" + name.replace(/\W+/g, "_") + "_hook_cb",
|
|
configurable: true
|
|
});
|
|
} catch {}
|
|
this._hooks[name] = this._hooks[name] || [];
|
|
this._hooks[name].push(function_);
|
|
return () => {
|
|
if (function_) {
|
|
this.removeHook(name, function_);
|
|
function_ = void 0;
|
|
}
|
|
};
|
|
}
|
|
hookOnce(name, function_) {
|
|
let _unreg;
|
|
let _function = (...arguments_) => {
|
|
if (typeof _unreg === "function") _unreg();
|
|
_unreg = void 0;
|
|
_function = void 0;
|
|
return function_(...arguments_);
|
|
};
|
|
_unreg = this.hook(name, _function);
|
|
return _unreg;
|
|
}
|
|
removeHook(name, function_) {
|
|
if (this._hooks[name]) {
|
|
const index = this._hooks[name].indexOf(function_);
|
|
if (index !== -1) this._hooks[name].splice(index, 1);
|
|
if (this._hooks[name].length === 0) delete this._hooks[name];
|
|
}
|
|
}
|
|
deprecateHook(name, deprecated) {
|
|
this._deprecatedHooks[name] = typeof deprecated === "string" ? { to: deprecated } : deprecated;
|
|
const _hooks = this._hooks[name] || [];
|
|
delete this._hooks[name];
|
|
for (const hook of _hooks) this.hook(name, hook);
|
|
}
|
|
deprecateHooks(deprecatedHooks) {
|
|
Object.assign(this._deprecatedHooks, deprecatedHooks);
|
|
for (const name in deprecatedHooks) this.deprecateHook(name, deprecatedHooks[name]);
|
|
}
|
|
addHooks(configHooks) {
|
|
const hooks$2 = flatHooks(configHooks);
|
|
const removeFns = Object.keys(hooks$2).map((key) => this.hook(key, hooks$2[key]));
|
|
return () => {
|
|
for (const unreg of removeFns.splice(0, removeFns.length)) unreg();
|
|
};
|
|
}
|
|
removeHooks(configHooks) {
|
|
const hooks$2 = flatHooks(configHooks);
|
|
for (const key in hooks$2) this.removeHook(key, hooks$2[key]);
|
|
}
|
|
removeAllHooks() {
|
|
for (const key in this._hooks) delete this._hooks[key];
|
|
}
|
|
callHook(name, ...arguments_) {
|
|
arguments_.unshift(name);
|
|
return this.callHookWith(serialTaskCaller, name, ...arguments_);
|
|
}
|
|
callHookParallel(name, ...arguments_) {
|
|
arguments_.unshift(name);
|
|
return this.callHookWith(parallelTaskCaller, name, ...arguments_);
|
|
}
|
|
callHookWith(caller, name, ...arguments_) {
|
|
const event = this._before || this._after ? {
|
|
name,
|
|
args: arguments_,
|
|
context: {}
|
|
} : void 0;
|
|
if (this._before) callEachWith(this._before, event);
|
|
const result = caller(name in this._hooks ? [...this._hooks[name]] : [], arguments_);
|
|
if (result instanceof Promise) return result.finally(() => {
|
|
if (this._after && event) callEachWith(this._after, event);
|
|
});
|
|
if (this._after && event) callEachWith(this._after, event);
|
|
return result;
|
|
}
|
|
beforeEach(function_) {
|
|
this._before = this._before || [];
|
|
this._before.push(function_);
|
|
return () => {
|
|
if (this._before !== void 0) {
|
|
const index = this._before.indexOf(function_);
|
|
if (index !== -1) this._before.splice(index, 1);
|
|
}
|
|
};
|
|
}
|
|
afterEach(function_) {
|
|
this._after = this._after || [];
|
|
this._after.push(function_);
|
|
return () => {
|
|
if (this._after !== void 0) {
|
|
const index = this._after.indexOf(function_);
|
|
if (index !== -1) this._after.splice(index, 1);
|
|
}
|
|
};
|
|
}
|
|
};
|
|
function createHooks() {
|
|
return new Hookable();
|
|
}
|
|
|
|
//#endregion
|
|
//#region src/rpc/global.ts
|
|
const hooks$1 = createHooks();
|
|
let DevToolsMessagingEvents = /* @__PURE__ */ function(DevToolsMessagingEvents$1) {
|
|
DevToolsMessagingEvents$1["INSPECTOR_TREE_UPDATED"] = "inspector-tree-updated";
|
|
DevToolsMessagingEvents$1["INSPECTOR_STATE_UPDATED"] = "inspector-state-updated";
|
|
DevToolsMessagingEvents$1["DEVTOOLS_STATE_UPDATED"] = "devtools-state-updated";
|
|
DevToolsMessagingEvents$1["ROUTER_INFO_UPDATED"] = "router-info-updated";
|
|
DevToolsMessagingEvents$1["TIMELINE_EVENT_UPDATED"] = "timeline-event-updated";
|
|
DevToolsMessagingEvents$1["INSPECTOR_UPDATED"] = "inspector-updated";
|
|
DevToolsMessagingEvents$1["ACTIVE_APP_UNMOUNTED"] = "active-app-updated";
|
|
DevToolsMessagingEvents$1["DESTROY_DEVTOOLS_CLIENT"] = "destroy-devtools-client";
|
|
DevToolsMessagingEvents$1["RELOAD_DEVTOOLS_CLIENT"] = "reload-devtools-client";
|
|
return DevToolsMessagingEvents$1;
|
|
}({});
|
|
function getDevToolsState() {
|
|
const state = devtools.ctx.state;
|
|
return {
|
|
connected: state.connected,
|
|
clientConnected: true,
|
|
vueVersion: state?.activeAppRecord?.version || "",
|
|
tabs: state.tabs,
|
|
commands: state.commands,
|
|
vitePluginDetected: state.vitePluginDetected,
|
|
appRecords: state.appRecords.map((item) => ({
|
|
id: item.id,
|
|
name: item.name,
|
|
version: item.version,
|
|
routerId: item.routerId,
|
|
iframe: item.iframe
|
|
})),
|
|
activeAppRecordId: state.activeAppRecordId,
|
|
timelineLayersState: state.timelineLayersState
|
|
};
|
|
}
|
|
const functions = {
|
|
on: (event, handler) => {
|
|
hooks$1.hook(event, handler);
|
|
},
|
|
off: (event, handler) => {
|
|
hooks$1.removeHook(event, handler);
|
|
},
|
|
once: (event, handler) => {
|
|
hooks$1.hookOnce(event, handler);
|
|
},
|
|
emit: (event, ...args) => {
|
|
hooks$1.callHook(event, ...args);
|
|
},
|
|
heartbeat: () => {
|
|
return true;
|
|
},
|
|
devtoolsState: () => {
|
|
return getDevToolsState();
|
|
},
|
|
async getInspectorTree(payload) {
|
|
return stringify(await devtools.ctx.api.getInspectorTree(payload));
|
|
},
|
|
async getInspectorState(payload) {
|
|
const inspector = getInspector(payload.inspectorId);
|
|
if (inspector) inspector.selectedNodeId = payload.nodeId;
|
|
return stringify(await devtools.ctx.api.getInspectorState(payload));
|
|
},
|
|
async editInspectorState(payload) {
|
|
return await devtools.ctx.api.editInspectorState(payload);
|
|
},
|
|
sendInspectorState(id) {
|
|
return devtools.ctx.api.sendInspectorState(id);
|
|
},
|
|
inspectComponentInspector() {
|
|
return devtools.ctx.api.inspectComponentInspector();
|
|
},
|
|
cancelInspectComponentInspector() {
|
|
return devtools.ctx.api.cancelInspectComponentInspector();
|
|
},
|
|
getComponentRenderCode(id) {
|
|
return devtools.ctx.api.getComponentRenderCode(id);
|
|
},
|
|
scrollToComponent(id) {
|
|
return devtools.ctx.api.scrollToComponent(id);
|
|
},
|
|
inspectDOM(id) {
|
|
return devtools.ctx.api.inspectDOM(id);
|
|
},
|
|
getInspectorNodeActions(id) {
|
|
return getInspectorNodeActions(id);
|
|
},
|
|
getInspectorActions(id) {
|
|
return getInspectorActions(id);
|
|
},
|
|
updateTimelineLayersState(state) {
|
|
return updateTimelineLayersState(state);
|
|
},
|
|
callInspectorNodeAction(inspectorId, actionIndex, nodeId) {
|
|
const nodeActions = getInspectorNodeActions(inspectorId);
|
|
if (nodeActions?.length) nodeActions[actionIndex].action?.(nodeId);
|
|
},
|
|
callInspectorAction(inspectorId, actionIndex) {
|
|
const actions = getInspectorActions(inspectorId);
|
|
if (actions?.length) actions[actionIndex].action?.();
|
|
},
|
|
openInEditor(options) {
|
|
return devtools.ctx.api.openInEditor(options);
|
|
},
|
|
async checkVueInspectorDetected() {
|
|
return !!await devtools.ctx.api.getVueInspector();
|
|
},
|
|
async enableVueInspector() {
|
|
const inspector = await devtools?.api?.getVueInspector?.();
|
|
if (inspector) await inspector.enable();
|
|
},
|
|
async toggleApp(id, options) {
|
|
return devtools.ctx.api.toggleApp(id, options);
|
|
},
|
|
updatePluginSettings(pluginId, key, value) {
|
|
return devtools.ctx.api.updatePluginSettings(pluginId, key, value);
|
|
},
|
|
getPluginSettings(pluginId) {
|
|
return devtools.ctx.api.getPluginSettings(pluginId);
|
|
},
|
|
getRouterInfo() {
|
|
return devtoolsRouterInfo;
|
|
},
|
|
navigate(path) {
|
|
return devtoolsRouter.value?.push(path).catch(() => ({}));
|
|
},
|
|
getMatchedRoutes(path) {
|
|
const c = console.warn;
|
|
console.warn = () => {};
|
|
const matched = devtoolsRouter.value?.resolve?.({ path: path || "/" }).matched ?? [];
|
|
console.warn = c;
|
|
return matched;
|
|
},
|
|
toggleClientConnected(state) {
|
|
toggleClientConnected(state);
|
|
},
|
|
getCustomInspector() {
|
|
return getActiveInspectors();
|
|
},
|
|
getInspectorInfo(id) {
|
|
return getInspectorInfo(id);
|
|
},
|
|
highlighComponent(uid) {
|
|
return devtools.ctx.hooks.callHook(DevToolsContextHookKeys.COMPONENT_HIGHLIGHT, { uid });
|
|
},
|
|
unhighlight() {
|
|
return devtools.ctx.hooks.callHook(DevToolsContextHookKeys.COMPONENT_UNHIGHLIGHT);
|
|
},
|
|
updateDevToolsClientDetected(params) {
|
|
updateDevToolsClientDetected(params);
|
|
},
|
|
initDevToolsServerListener() {
|
|
const broadcast = getRpcServer().broadcast;
|
|
devtools.ctx.hooks.hook(DevToolsMessagingHookKeys.SEND_INSPECTOR_TREE_TO_CLIENT, (payload) => {
|
|
broadcast.emit(DevToolsMessagingEvents.INSPECTOR_TREE_UPDATED, stringify(payload));
|
|
});
|
|
devtools.ctx.hooks.hook(DevToolsMessagingHookKeys.SEND_INSPECTOR_STATE_TO_CLIENT, (payload) => {
|
|
broadcast.emit(DevToolsMessagingEvents.INSPECTOR_STATE_UPDATED, stringify(payload));
|
|
});
|
|
devtools.ctx.hooks.hook(DevToolsMessagingHookKeys.DEVTOOLS_STATE_UPDATED, () => {
|
|
broadcast.emit(DevToolsMessagingEvents.DEVTOOLS_STATE_UPDATED, getDevToolsState());
|
|
});
|
|
devtools.ctx.hooks.hook(DevToolsMessagingHookKeys.ROUTER_INFO_UPDATED, ({ state }) => {
|
|
broadcast.emit(DevToolsMessagingEvents.ROUTER_INFO_UPDATED, state);
|
|
});
|
|
devtools.ctx.hooks.hook(DevToolsMessagingHookKeys.SEND_TIMELINE_EVENT_TO_CLIENT, (payload) => {
|
|
broadcast.emit(DevToolsMessagingEvents.TIMELINE_EVENT_UPDATED, stringify(payload));
|
|
});
|
|
devtools.ctx.hooks.hook(DevToolsMessagingHookKeys.SEND_INSPECTOR_TO_CLIENT, (payload) => {
|
|
broadcast.emit(DevToolsMessagingEvents.INSPECTOR_UPDATED, payload);
|
|
});
|
|
devtools.ctx.hooks.hook(DevToolsMessagingHookKeys.SEND_ACTIVE_APP_UNMOUNTED_TO_CLIENT, () => {
|
|
broadcast.emit(DevToolsMessagingEvents.ACTIVE_APP_UNMOUNTED);
|
|
});
|
|
}
|
|
};
|
|
const rpc = new Proxy({
|
|
value: {},
|
|
functions: {}
|
|
}, { get(target$1, property) {
|
|
const _rpc = getRpcClient();
|
|
if (property === "value") return _rpc;
|
|
else if (property === "functions") return _rpc.$functions;
|
|
} });
|
|
const rpcServer = new Proxy({
|
|
value: {},
|
|
functions: {}
|
|
}, { get(target$1, property) {
|
|
const _rpc = getRpcServer();
|
|
if (property === "value") return _rpc;
|
|
else if (property === "functions") return _rpc.functions;
|
|
} });
|
|
function onRpcConnected(callback) {
|
|
let timer = null;
|
|
let retryCount = 0;
|
|
function heartbeat() {
|
|
rpc.value?.heartbeat?.().then(() => {
|
|
callback();
|
|
clearTimeout(timer);
|
|
}).catch(() => {});
|
|
}
|
|
timer = setInterval(() => {
|
|
if (retryCount >= 30) clearTimeout(timer);
|
|
retryCount++;
|
|
heartbeat();
|
|
}, retryCount * 200 + 200);
|
|
heartbeat();
|
|
}
|
|
function onRpcSeverReady(callback) {
|
|
let timer = null;
|
|
const timeout = 120;
|
|
function heartbeat() {
|
|
if (rpcServer.value.clients.length > 0) {
|
|
callback();
|
|
clearTimeout(timer);
|
|
}
|
|
}
|
|
timer = setInterval(() => {
|
|
heartbeat();
|
|
}, timeout);
|
|
}
|
|
|
|
//#endregion
|
|
//#region src/rpc/vite.ts
|
|
const hooks = createHooks();
|
|
const viteRpcFunctions = {
|
|
on: (event, handler) => {
|
|
hooks.hook(event, handler);
|
|
},
|
|
off: (event, handler) => {
|
|
hooks.removeHook(event, handler);
|
|
},
|
|
once: (event, handler) => {
|
|
hooks.hookOnce(event, handler);
|
|
},
|
|
emit: (event, ...args) => {
|
|
hooks.callHook(event, ...args);
|
|
},
|
|
heartbeat: () => {
|
|
return true;
|
|
}
|
|
};
|
|
const viteRpc = new Proxy({
|
|
value: {},
|
|
functions: {}
|
|
}, { get(target$1, property) {
|
|
const _rpc = getViteRpcClient();
|
|
if (property === "value") return _rpc;
|
|
else if (property === "functions") return _rpc?.$functions;
|
|
} });
|
|
function onViteRpcConnected(callback) {
|
|
let timer = null;
|
|
function heartbeat() {
|
|
viteRpc.value?.heartbeat?.().then(() => {
|
|
clearTimeout(timer);
|
|
callback();
|
|
}).catch(() => ({}));
|
|
timer = setTimeout(() => {
|
|
heartbeat();
|
|
}, 80);
|
|
}
|
|
heartbeat();
|
|
}
|
|
function createViteClientRpc() {
|
|
createRpcClient(viteRpcFunctions, { preset: "vite" });
|
|
}
|
|
function createViteServerRpc(functions$1) {
|
|
createRpcServer(functions$1, { preset: "vite" });
|
|
}
|
|
|
|
//#endregion
|
|
//#region src/vue-plugin/devtools-state.ts
|
|
const VueDevToolsStateSymbol = Symbol.for("__VueDevToolsStateSymbol__");
|
|
function VueDevToolsVuePlugin() {
|
|
return { install(app) {
|
|
const state = createDevToolsStateContext();
|
|
state.getDevToolsState();
|
|
app.provide(VueDevToolsStateSymbol, state);
|
|
app.config.globalProperties.$getDevToolsState = state.getDevToolsState;
|
|
app.config.globalProperties.$disconnectDevToolsClient = () => {
|
|
state.clientConnected.value = false;
|
|
state.connected.value = false;
|
|
};
|
|
} };
|
|
}
|
|
function createDevToolsStateContext() {
|
|
const connected = ref(false);
|
|
const clientConnected = ref(false);
|
|
const vueVersion = ref("");
|
|
const tabs = ref([]);
|
|
const commands = ref([]);
|
|
const vitePluginDetected = ref(false);
|
|
const appRecords = ref([]);
|
|
const activeAppRecordId = ref("");
|
|
const timelineLayersState = ref({});
|
|
function updateState(data) {
|
|
connected.value = data.connected;
|
|
clientConnected.value = data.clientConnected;
|
|
vueVersion.value = data.vueVersion || "";
|
|
tabs.value = data.tabs;
|
|
commands.value = data.commands;
|
|
vitePluginDetected.value = data.vitePluginDetected;
|
|
appRecords.value = data.appRecords;
|
|
activeAppRecordId.value = data.activeAppRecordId;
|
|
timelineLayersState.value = data.timelineLayersState;
|
|
}
|
|
function getDevToolsState$1() {
|
|
onRpcConnected(() => {
|
|
rpc.value.devtoolsState().then((data) => {
|
|
updateState(data);
|
|
});
|
|
rpc.functions.off(DevToolsMessagingEvents.DEVTOOLS_STATE_UPDATED, updateState);
|
|
rpc.functions.on(DevToolsMessagingEvents.DEVTOOLS_STATE_UPDATED, updateState);
|
|
});
|
|
}
|
|
return {
|
|
getDevToolsState: getDevToolsState$1,
|
|
connected,
|
|
clientConnected,
|
|
vueVersion,
|
|
tabs,
|
|
commands,
|
|
vitePluginDetected,
|
|
appRecords,
|
|
activeAppRecordId,
|
|
timelineLayersState
|
|
};
|
|
}
|
|
function useDevToolsState() {
|
|
return inject(VueDevToolsStateSymbol);
|
|
}
|
|
const fns = [];
|
|
function onDevToolsConnected(fn) {
|
|
const { connected, clientConnected } = useDevToolsState();
|
|
fns.push(fn);
|
|
onUnmounted(() => {
|
|
fns.splice(fns.indexOf(fn), 1);
|
|
});
|
|
const devtoolsReady = computed(() => clientConnected.value && connected.value);
|
|
if (devtoolsReady.value) fn();
|
|
else {
|
|
const stop = watch(devtoolsReady, (v) => {
|
|
if (v) {
|
|
fn();
|
|
stop();
|
|
}
|
|
});
|
|
}
|
|
return () => {
|
|
fns.splice(fns.indexOf(fn), 1);
|
|
};
|
|
}
|
|
function refreshCurrentPageData() {
|
|
fns.forEach((fn) => fn());
|
|
}
|
|
|
|
//#endregion
|
|
export { DevToolsMessagingEvents, VueDevToolsVuePlugin, createDevToolsStateContext, createViteClientRpc, createViteServerRpc, functions, getDevToolsClientUrl, onDevToolsConnected, onRpcConnected, onRpcSeverReady, onViteRpcConnected, refreshCurrentPageData, rpc, rpcServer, setDevToolsClientUrl, useDevToolsState, viteRpc, viteRpcFunctions }; |