UNPKG

vite-uni-dev-tool

Version:

vite-uni-dev-tool, debug, uni-app, 一处编写,到处调试

695 lines (694 loc) 21.5 kB
import { console as p, backup as w } from "../core.js"; import { DEV_APP_MESSAGE as M, DEV_WINDOW_VISIBLE as _, DEV_BUTTON_VISIBLE as f, DEV_OPTION_SEND as R, DEV_WINDOW_MESSAGE as I, DEV_CONSOLE_CLEAR as O, DEV_NETWORK_CLEAR as A, DEV_WEBSOCKET_CLEAR as N, DEV_WEBSOCKET_CLEAR_MESSAGE as U, DEV_UPLOAD_CLEAR as b, DEV_STORAGE_CLEAR as V, DEV_STORAGE_REFRESH as x, DEV_STORAGE_REMOVE as k, DEV_STORAGE_ADD as P, DEV_STORAGE_UPDATE as B, DEV_BUTTON_SHOW_OR_HIDE as W, DEV_RESTART_DEBUGGER as G, DEV_RESTART_APP as F, DEV_EXPORT_LOG as H, DEV_VUEX_CHANGE as j, DEV_PINIA_CHANGE as J, DEV_LOG_CACHE_CLEAR as z, DEV_DESTROY as q, DEV_WINDOW_OPEN as K, DEV_WINDOW_CLOSE as X, DEV_ROUTE_REFRESH as $, DEV_OPTION_GET as Y, DEV_EL_EVENT_CLEAR as Q, DEV_UNI_EVENT_CLEAR as Z, DEV_RUN_JS as tt, DEV_CAPTURE_SCREEN_CLEAR as et, DEV_INTERCEPT_NETWORK_UPDATE as st, DEV_INTERCEPT_NETWORK_REMOVE as ot, DEV_CHANGE_CACHE_INTERCEPT_CONFIG as it, DEV_BOTTOM_TAB_CHANGE as rt, DEV_SCAN_CODE_CLEAR as nt, DEV_NFC_CLEAR as at, DEV_CAPTURE_TAP_EVENT as m, DEV_CAPTURE_TOUCH_START as L, DEV_CAPTURE_TOUCH_MOVE as S, DEV_CAPTURE_TOUCH_END as C } from "../const.js"; import "../utils/index.js"; import { transformValueToView as ht, transformValueToShortString as lt } from "../utils/language.js"; import { throttle as d } from "../utils/function.js"; import { calculateObjectSize as pt, formatStorageSize as ct, parseValue as ut } from "../utils/object.js"; import { saveTextFileMicro as Et, saveTextFileH5 as vt, saveTxtFileApp as dt } from "../utils/file.js"; import { getCurrentDate as y } from "../utils/date.js"; import { getCurrentPagePath as c } from "../utils/page.js"; class wt { constructor({ store: t, eventBus: e }) { this.abnormalUploadCount = 0, this.abnormalUploadTimer = null, this.isAbnormalUploadActive = !1, this.postMessage = d(this.postMessageFn, 1e3), this.throttleAddElEvent = d(this.addElEvent, 1e3), this.throttleTouchStartEvent = d(this.touchStartEvent, 1e3), this.throttleTouchMoveEvent = d(this.touchMoveEvent, 1e3), this.throttleTouchEndEvent = d(this.touchEndEvent, 1e3), this.store = t, this.eventBus = e, this.acceptMessage(); } setIntercept(t) { this.intercept = t; } /** * 发送数据 * * @param {DevTool.WindowData} data * @memberof DevEvent */ async postMessageFn() { var i; if (this.getDevToolDestroy()) return; const t = await this.store.getDevData(), e = pt(t), s = ct(e); t.size = e, t.sizeFormat = s, this.eventBus.emit(M, t), e > this.store.cacheMaxSize && ((i = this.store) == null || i.clearDevCache()); } /** * 创建调试器 * * @return {*} * @memberof DevEvent */ createDevTool(t) { var s; if (!this.getDevToolDestroy()) { p.warn("[DevTool] 调试器已创建,不再创建"); return; } const e = this.store.getDevToolOptions(); (s = this.intercept) == null || s.init({ enableCaptureScreen: e == null ? void 0 : e.enableCaptureScreen, enableInterceptPromiseReject: e == null ? void 0 : e.enableInterceptPromiseReject }), this.addEventListener(), this.store.setDevToolDestroy(!1), this.updateRouteList(), this.showDevToolButton(), this.postMessage(), setTimeout(() => { p.warn( `[DevTool] 创建成功 当前版本:${t == null ? void 0 : t.devToolVersion} 构建时间:${t == null ? void 0 : t.devToolBuildTime} 一处编写,到处调试 😂 有问题前往反馈:https://gitee.com/cloud_l/vite-uni-dev-tool` ); }, 500); } /** * 销毁调试器 * * @return {*} * @memberof DevEvent */ destroyDevTool() { var t; if (this.getDevToolDestroy()) { p.warn("[DevTool] 调试器已经销毁了,不再重新销毁"); return; } this.hideDevToolButton(), this.closeDevToolWindow(), this.removeEventListener(), this.store.setRequestIndex(-1), this.store.setUploadIndex(-1), this.store.setDevToolDestroy(!0), this.store.clearAll(), (t = this.intercept) == null || t.reset(), this.stopAbnormalUpload(), p.warn("[DevTool] 调试器已销毁"); } /** * 重启调试器 * * @memberof DevEvent */ restartDevTool() { this.destroyDevTool(), this.createDevTool({ devToolBuildTime: this.store.devToolBuildTime, devToolVersion: this.store.devToolVersion }), this.openDevToolWindow(), this.restartAbnormalUpload(); } /** * 打开调试器窗口 * * @memberof DevEvent */ openDevToolWindow() { if (this.getDevToolDestroy()) { p.warn("[DevTool] 调试器已销毁"); return; } setTimeout(async () => { this.postMessage(); }, 100), this.eventBus.emit(_, !0); } /** * 关闭调试器窗口 * * @memberof DevEvent */ closeDevToolWindow() { if (this.getDevToolDestroy()) { p.warn("[DevTool] 调试器已销毁"); return; } this.eventBus.emit(_, !1); } /** * 显示调试按钮 * * @export */ showDevToolButton() { this.getDevToolDestroy() || (this.eventBus.emit(f, !0), this.store.setDevToolVisible(!0)); } /** * 隐藏调试按钮 * * @return {*} */ hideDevToolButton() { this.getDevToolDestroy() || (this.eventBus.emit(f, !1), this.store.setDevToolVisible(!1)); } exportLog(t) { const e = this.store.getExportData(t); switch (uni.__dev_tool_platform__) { case "app": dt(JSON.stringify(e, null, 2), "dev-tool-log"); break; case "web": vt(JSON.stringify(e, null, 2), "dev-tool-log"); break; case "mp-weixin": case "mp-alipay": case "mp-toutiao": Et(JSON.stringify(e, null, 2), "dev-tool-log"); break; } } /** * 重启app * * @memberof DevEvent */ restartApp() { var t; switch (uni.__dev_tool_platform__) { case "app": plus.runtime.restart(); break; case "web": window.location.reload(); break; case "mp-weixin": if (wx != null && wx.restartMiniProgram) { const e = "/" + this.store.getCurrentPagePath(); (t = wx.restartMiniProgram) == null || t.call(wx, { path: e }); } break; } } refreshRouteList() { this.store.getRouteList(), this.postMessage(); } sendDevToolOption() { const t = this.store.getDevToolOptions(); this.eventBus.emit(R, t); } /** * 接受消息 * * @memberof DevEvent */ acceptMessage() { this.eventBus.on( I, (t) => { t.type === O ? this.store.clearConsoleList() : t.type === A ? (this.store.clearNetworkList(), this.postMessage()) : t.type === N ? (this.store.clearWsList(), this.postMessage()) : t.type === U ? (p.log("data: ", t), this.store.clearWsMessage(t.data.url), this.postMessage()) : t.type === b ? (this.store.clearUploadList(), this.postMessage()) : t.type === V ? (this.store.clearStorageList(!0), this.postMessage()) : t.type === x ? (this.store.refreshStore(), this.postMessage()) : t.type === k ? (this.store.removeStorage(t.data.key + "", !0), this.postMessage()) : t.type === P ? (this.store.addStorage(t.data, !0), this.postMessage()) : t.type === B ? (this.store.updateStore(t.data), this.postMessage()) : t.type === W ? (t.data.show ? this.showDevToolButton() : this.hideDevToolButton(), this.postMessage()) : t.type === G ? this.restartDevTool() : t.type === F ? this.restartApp() : t.type === H ? this.exportLog(t.data) : t.type === j ? (this.store.updateVuexStore(t.data), this.postMessage()) : t.type === J ? (this.store.updatePiniaStore(t.data), this.postMessage()) : t.type === z ? this.store.clearDevCache() : t.type === q ? this.destroyDevTool() : t.type === K ? this.openDevToolWindow() : t.type === X ? this.closeDevToolWindow() : t.type === $ ? this.refreshRouteList() : t.type === Y ? this.sendDevToolOption() : t.type === Q ? this.clearElEventList() : t.type === Z ? this.clearUniEvent() : t.type === tt ? this.devRunJS(t.data.code) : t.type === et ? this.store.clearCaptureScreenList() : t.type === st ? this.updateInterceptNetworkList(t.data) : t.type === ot ? this.removeInterceptNetwork(t.data) : t.type === it ? this.changeCacheInterceptConfig(t.data) : t.type === rt ? (this.closeDevToolWindow(), this.updateRouteList(t.data.path)) : t.type === nt ? this.store.clearScanCodeList() : t.type === at && this.store.clearNfcList(); } ); } /** * 更新路由信息 * * @param {string} path * @memberof DevEvent */ updateRouteList(t) { this.store.updateRouteList(t), this.postMessage(); } /** * 清除console日志 * * @memberof DevEvent */ clearConsoleList() { this.store.clearConsoleList(), this.postMessage(); } /** * 更新控制台日志 * * @param {DevTool.ConsoleItem[]} addItems * @param {number} [index] * @memberof DevEvent */ updateConsoleList(t, e) { this.store.updateConsoleList(t, e), this.postMessage(); } /** * 更新网络日志 * * @param {DevTool.NetworkItem[]} addItems * @param {number} [index] * @memberof DevEvent */ updateNetworkList(t, e) { this.store.updateNetworkList(t, e), this.postMessage(); } /** * 更新websocket日志 * * @param {DevTool.WS} item * @memberof DevEvent */ updateWsList(t) { this.store.updateWsList(t), this.postMessage(); } /** * 重置websocket * * @memberof DevEvent */ resetWebSocket() { uni.connectSocket = w.connectSocket; } /** * 更新状态存储 * * @param {DevTool.StorageItem[]} addItems * @memberof DevEvent */ updateStoreList(t) { this.store.updateStoreList(t), this.postMessage(); } /** * 移除状态 * * @param {string} key * @memberof DevEvent */ removeStorage(t, e) { this.store.removeStorage(t, e), this.postMessage(); } /** * 清除缓存 * * @memberof DevEvent */ clearStorage(t) { this.store.clearStorageList(t), this.postMessage(); } /** * 更新上传日志 * * @param {DevTool.UploadItem[]} addItems * @param {number} [index] * @memberof DevEvent */ updateUploadList(t, e) { this.store.updateUploadList(t, e), this.postMessage(); } /** * 移除上传任务 * * @param {(number | string)} index * @memberof DevEvent */ removeUploadTask(t) { this.store.removeUploadTask(t), this.postMessage(); } /** * 新增上传任务 * * @param {(number | string)} index * @param {UniApp.UploadTask} task * @memberof DevEvent */ addUploadTask(t, e) { this.store.addUploadTask(t, e), this.postMessage(); } setRequestIndex(t) { return this.store.setRequestIndex(t); } getRequestIndex() { return this.store.getRequestIndex(); } setUploadIndex(t) { return this.store.setUploadIndex(t); } getUploadIndex() { return this.store.getUploadIndex(); } setScreenIndex(t) { return this.store.setScreenIndex(t); } getScreenIndex() { return this.store.getScreenIndex(); } setVuexList(t) { this.store.setVuexList(t); } setPiniaList(t) { this.store.setPiniaList(t); } setPiniaStore(t) { this.store.setPiniaStore(t); } getDevToolDestroy() { return this.store.getDevToolDestroy(); } updateUniEventCount(t) { this.store.updateUniEventCount(t), this.postMessage(); } updateUniEventList(t) { this.store.updateUniEventList(t), this.postMessage(); } clearUniEvent() { this.store.clearUniEvent(), this.postMessage(); } execute(t) { const e = "_e_v_a_l_".replace( /_/g, "" ), s = "_e_v_a_l_F_n_".replace( /_/g, "" ); if (globalThis != null && globalThis[s]) return Promise.resolve(globalThis == null ? void 0 : globalThis[s](t)); if (globalThis != null && globalThis[e]) return Promise.resolve(globalThis == null ? void 0 : globalThis[e](t)); throw new Error("[DevTool] DevRunJS 当前环境不支持执行js"); } /** * 运行js * * @param {string} code * @memberof DevEvent */ devRunJS(t) { var n, h; const e = (h = (n = new Error()) == null ? void 0 : n.stack) == null ? void 0 : h.split(` `), s = e == null ? void 0 : e[1], i = Date.now(), o = { type: "log", args: [ { type: "string", value: t } ], position: c(), time: y(), stack: s, mode: "input" }; this.updateConsoleList([{ ...o }]), this.execute(t).then((a) => { const l = ht(a), u = ut(a), D = l === "object" || l === "array" ? lt(u, l) : ""; o.args = [ { type: l, value: u, shortValue: D } ], o.time = y(), o.mode = "output", o.executionTime = Date.now() - i, this.updateConsoleList([{ ...o }]); }); } /** * 更新截屏列表 * * @param {DevTool.ScreenItem[]} list * @memberof DevEvent */ updateScreenList(t, e) { this.store.updateScreenList(t, e), this.postMessage(); } /** * 清空截屏列表 * * @memberof DevEvent */ clearCaptureScreenList() { this.store.clearCaptureScreenList(); } /** * 更新拦截的网络请求列表 * * @param {DevTool.NetworkItem[]} list * @memberof DevEvent */ updateInterceptNetworkList(t) { this.store.updateInterceptNetworkList(t), this.postMessage(); } /** * 清空拦截的网络请求列表 * * @memberof DevEvent */ clearInterceptNetworkList() { this.store.clearInterceptNetworkList(), this.postMessage(); } /** * 移除拦截的网络请求 * * @param {DevTool.NetworkItem} item * @memberof DevEvent */ removeInterceptNetwork(t) { this.store.removeInterceptNetwork(t), this.postMessage(); } /** * 缓存网络请求到本地 * * @param {{ * cacheInterceptConfig: boolean; * }} { * cacheInterceptConfig, * } * @memberof DevEvent */ changeCacheInterceptConfig({ cacheInterceptConfig: t }) { this.store.changeCacheInterceptConfig(t); } getInterceptNetworkMap() { return this.store.getInterceptNetworkMap(); } updateScanCodeList(t) { this.store.updateScanCodeList(t), this.postMessage(); } /** * 外界扫描传入的code * @param code */ devToolScanCode(t, e) { var h, a; if (this.getDevToolDestroy()) return; let s = {}; try { s = JSON.parse(t); } catch { } const i = (a = (h = new Error()) == null ? void 0 : h.stack) == null ? void 0 : a.split(` `), o = i == null ? void 0 : i[2], n = { timer: Date.now(), charSet: "utf-8", rawData: t, result: t, scanType: e, errMsg: "ok", resultObject: s, path: c(), stack: o }; this.updateScanCodeList([n]); } updateNfcList(t) { this.store.updateNfcList(t), this.postMessage(); } /** 外界 nfc 读取传入 */ devToolNFC(t) { var o, n; const e = (n = (o = new Error()) == null ? void 0 : o.stack) == null ? void 0 : n.split(` `), s = e == null ? void 0 : e[1], i = { ...t, stack: s, timer: Date.now(), path: c() }; this.updateNfcList([i]); } addElEvent(t) { this.store.addElEvent(t), this.postMessage(); } clearElEventList() { this.store.clearElEventList(), this.postMessage(); } hasCaptureEvent(t) { const { includeCaptureElDataSet: e = [], excludeCaptureElDataSet: s = [] } = this.store.getDevToolOptions() ?? { includeCaptureElDataSet: [], excludeCaptureElDataSet: [] }; return e.length ? e.some((i) => { var o; return Object.keys(((o = t == null ? void 0 : t.target) == null ? void 0 : o.dataset) ?? {}).includes(i); }) : s.length ? !s.some((i) => { var o; return Object.keys(((o = t == null ? void 0 : t.target) == null ? void 0 : o.dataset) ?? {}).includes(i); }) : !0; } tapEvent(t) { if (!this.hasCaptureEvent(t)) return; const e = { type: t.type, timer: Date.now(), target: t.target, touches: t.touches, path: c() }; this.addElEvent(e); } touchStartEvent(t) { if (!this.hasCaptureEvent(t)) return; const e = { type: t.type, timer: Date.now(), target: t.target, touches: t.touches, path: c() }; this.addElEvent(e); } touchMoveEvent(t) { if (!this.hasCaptureEvent(t)) return; const e = { type: t.type, timer: Date.now(), target: t.target, touches: t.touches, path: c() }; this.addElEvent(e); } touchEndEvent(t) { if (!this.hasCaptureEvent(t)) return; const e = { type: t.type, timer: Date.now(), target: t.target, touches: t.touches, path: c() }; this.addElEvent(e); } /** * 添加事件监听 */ addEventListener() { const t = this.store.getCaptureList(); t.includes("tap") && this.eventBus.on(m, this.tapEvent.bind(this)), t.includes("touchstart") && this.eventBus.on( L, this.throttleTouchStartEvent.bind(this) ), t.includes("touchmove") && this.eventBus.on( S, this.throttleTouchMoveEvent.bind(this) ), t.includes("touchend") && this.eventBus.on( C, this.throttleTouchEndEvent.bind(this) ); } /** * 移除事件监听 */ removeEventListener() { const t = this.store.getCaptureList(); t.includes("tap") && this.eventBus.off(m, this.tapEvent), t.includes("touchstart") && this.eventBus.off(L, this.throttleTouchStartEvent), t.includes("touchmove") && this.eventBus.off(S, this.throttleTouchMoveEvent), t.includes("touchend") && this.eventBus.off(C, this.throttleTouchEndEvent); } async getAbnormalData() { var a, l, u, T, D, g; const t = await this.store.getDevData(), e = ((a = t.consoleList) == null ? void 0 : a.filter( (r) => ["error", "warn"].includes(r.type) && !r.hasUpload )) ?? [], s = ((l = t.networkList) == null ? void 0 : l.filter( (r) => { var E, v; return r.sponsor === "user" && !((v = (E = r.status) == null ? void 0 : E.toString()) != null && v.startsWith("2")) && !r.hasUpload; } )) ?? [], i = ((u = t.uploadList) == null ? void 0 : u.filter( (r) => { var E, v; return !((v = (E = r.status) == null ? void 0 : E.toString()) != null && v.startsWith("2")) && !r.hasUpload; } )) ?? [], o = ((T = t.elEventList) == null ? void 0 : T.filter((r) => !r.hasUpload)) ?? [], n = ((D = t.uniEventList) == null ? void 0 : D.filter((r) => !r.hasUpload)) ?? [], h = ((g = t.screenList) == null ? void 0 : g.filter((r) => !r.hasUpload)) ?? []; return { consoleList: e, networkList: s, uploadList: i, elEventList: o, uniEventList: n, screenList: h, systemInfo: t.systemInfo, deviceInfo: t.deviceInfo }; } async performAbnormalUpload(t) { const { consoleList: e, networkList: s, uploadList: i, systemInfo: o, elEventList: n, uniEventList: h, screenList: a, deviceInfo: l } = await this.getAbnormalData(); (e.length || s.length || i.length || n.length || h.length || a.length) && uni.request({ method: "POST", url: t == null ? void 0 : t.url, header: { ...(t == null ? void 0 : t.header) ?? {}, "dev-tool-sponsor": Date.now() }, timeout: (t == null ? void 0 : t.timerOut) ?? 3 * 1e3, data: { ...(t == null ? void 0 : t.payload) ?? {}, consoleList: e, networkList: s, uploadList: i, elEventList: n, uniEventList: h, screenList: a, deviceInfo: l, systemInfo: o, platform: uni.__dev_tool_platform__ }, success: () => { this.store.updateHasUpload(), this.uploadAbnormal(), this.abnormalUploadCount = 0; }, fail: () => { this.uploadAbnormal(), this.abnormalUploadCount++; } }); } /** * 上报异常 * * @memberof DevEvent */ uploadAbnormal(t) { if (!this.isAbnormalUploadActive) return; const { uploadAbnormalUV: e } = this.store.getDevToolOptions() ?? { uploadAbnormalUV: { url: "", header: { "dev-tool-sponsor": Date.now() }, payload: {}, duration: 10 * 1e3, timerOut: 3 * 1e3 } }; if (!(e != null && e.url)) { p.log("[DevTool] 未配置异常上报地址,将不上报异常信息"); return; } const s = e.duration ?? 10 * 1e3, i = 5 * 60 * 1e3, o = Math.min( s * Math.pow(2, this.abnormalUploadCount), i ), n = Math.max(o, s); this.abnormalUploadTimer && clearTimeout(this.abnormalUploadTimer), t != null && t.immediately && this.performAbnormalUpload(e), this.abnormalUploadTimer = setTimeout(() => { this.performAbnormalUpload(e); }, n); } /** * 启动异常上报 */ startAbnormalUpload(t) { this.isAbnormalUploadActive = !0, this.abnormalUploadCount = 0, this.uploadAbnormal(t); } /** * 停止异常上报 */ stopAbnormalUpload() { this.isAbnormalUploadActive = !1, this.abnormalUploadTimer && (clearTimeout(this.abnormalUploadTimer), this.abnormalUploadTimer = null); } /** * 重启异常上报 */ restartAbnormalUpload() { this.stopAbnormalUpload(), this.startAbnormalUpload(); } } export { wt as DevEvent };