├── demo ├── app.wxss ├── t2 │ ├── index.wxml │ ├── index.json │ ├── index.wxss │ └── index.js ├── t1 │ ├── index.wxss │ ├── index.wxml │ ├── index.json │ └── index.js ├── pages │ └── index │ │ ├── index.wxss │ │ ├── index.js │ │ ├── index.wxml │ │ └── index.json ├── sitemap.json ├── app.js ├── app.json └── project.config.json ├── src ├── mp-console │ ├── tpl-all.xml │ ├── tpl-api.xml │ ├── tpl-console.xml │ ├── tpl-network.xml │ ├── tpl-storage.xml │ ├── tpl-system.xml │ ├── index.json │ ├── index.xml │ ├── tpl-view.xml │ ├── viewer.xml │ ├── index.ts │ └── index.scss ├── config.ts ├── global.d.ts ├── index.ts ├── vquery.ts ├── vars.ts ├── viewer.ts ├── util.ts ├── storage.ts └── rewrite.ts ├── packages ├── mp-console │ ├── console │ │ ├── index.wxml │ │ ├── index.json │ │ ├── index.ts │ │ └── index.scss │ └── index.ts ├── core │ ├── web │ │ └── rewrite.ts │ ├── debug.js │ ├── index.ts │ ├── package.json │ ├── storage.ts │ ├── data-parser.ts │ ├── miniprogram │ │ └── rewrite.ts │ └── package-lock.json ├── types │ ├── global.d.ts │ ├── index.ts │ ├── util.ts │ ├── parser.ts │ ├── package-lock.json │ ├── provider.ts │ ├── package.json │ ├── data-parser.ts │ └── storage.ts ├── provider │ ├── index.ts │ ├── package.json │ ├── producer.ts │ ├── package-lock.json │ ├── observer.ts │ └── storager.ts └── util │ ├── package.json │ ├── index.ts │ └── event-emitter.ts ├── .vscode ├── settings.json └── launch.json ├── 原型.mp ├── lerna.json ├── .babelrc ├── tsconfig.json ├── LICENSE ├── README.md ├── package.json └── .gitignore /demo/app.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mp-console/tpl-all.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mp-console/tpl-api.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mp-console/tpl-console.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mp-console/tpl-network.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mp-console/tpl-storage.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mp-console/tpl-system.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/mp-console/console/index.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/t2/index.wxml: -------------------------------------------------------------------------------- 1 | test-component2 -------------------------------------------------------------------------------- /demo/t2/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } -------------------------------------------------------------------------------- /demo/t1/index.wxss: -------------------------------------------------------------------------------- 1 | .abc { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /demo/t2/index.wxss: -------------------------------------------------------------------------------- 1 | .abc { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /src/mp-console/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } -------------------------------------------------------------------------------- /demo/t1/index.wxml: -------------------------------------------------------------------------------- 1 | test-component1 2 | -------------------------------------------------------------------------------- /packages/core/web/rewrite.ts: -------------------------------------------------------------------------------- 1 | export const test = () => {}; 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true 3 | } -------------------------------------------------------------------------------- /packages/types/global.d.ts: -------------------------------------------------------------------------------- 1 | export * from "@mpkit/types/global"; 2 | -------------------------------------------------------------------------------- /原型.mp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imingyu/fe-console/HEAD/原型.mp -------------------------------------------------------------------------------- /demo/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | page{ 2 | background-color: #ccc; 3 | color:#fff; 4 | } -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "0.0.0" 6 | } 7 | -------------------------------------------------------------------------------- /demo/pages/index/index.js: -------------------------------------------------------------------------------- 1 | 2 | Page({ 3 | onLoad() { 4 | global.p1 = this; 5 | } 6 | }) 7 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/env"], "@babel/preset-typescript"], 3 | "plugins": ["lodash"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./storage"; 2 | export * from "./provider"; 3 | export * from "./util"; 4 | -------------------------------------------------------------------------------- /demo/t1/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "t2": "../t2/index" 5 | } 6 | } -------------------------------------------------------------------------------- /packages/provider/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./producer"; 2 | export * from "./storager"; 3 | export * from "./observer"; 4 | -------------------------------------------------------------------------------- /demo/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 页面其他内容... 2 | 3 | -------------------------------------------------------------------------------- /packages/mp-console/console/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "data-parser": "../data-parser/index" 4 | } 5 | } -------------------------------------------------------------------------------- /demo/pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "mp-console": "../../mp-console/mpc-wechat/index", 4 | "t1": "../../t1/index" 5 | } 6 | } -------------------------------------------------------------------------------- /demo/t1/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | properties: { 3 | test: String, 4 | test2: Object, 5 | }, 6 | created() { 7 | global.t1 = this; 8 | } 9 | }) -------------------------------------------------------------------------------- /demo/t2/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | properties: { 3 | test: String, 4 | test2: Object, 5 | }, 6 | created() { 7 | global.t2 = this; 8 | } 9 | }) -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | rewrite: { 3 | console: true, 4 | app: true, 5 | page: true, 6 | component: true, 7 | api: true 8 | } 9 | } -------------------------------------------------------------------------------- /demo/sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [{ 4 | "action": "allow", 5 | "page": "*" 6 | }] 7 | } -------------------------------------------------------------------------------- /demo/app.js: -------------------------------------------------------------------------------- 1 | import './mp-console/index.js'; 2 | App({ 3 | data1: 'Tom', 4 | data2: 3, 5 | data3: [1, 2, 3], 6 | data4: { 7 | name: 'Tom', 8 | age: 3 9 | } 10 | }) -------------------------------------------------------------------------------- /packages/core/debug.js: -------------------------------------------------------------------------------- 1 | const { parseData } = require('./dist/index.cjs'); 2 | const res = parseData('chunk', '你好', [1, 2, 3, { name: 'Tom' }, () => 33], { name: 'Alice', address: { name: '上海' } }); 3 | console.log(res); -------------------------------------------------------------------------------- /packages/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./miniprogram/rewrite"; 2 | export * from "./web/rewrite"; 3 | import FecStorage from "./storage"; 4 | import parseData from "./data-parser"; 5 | export { FecStorage, parseData }; 6 | -------------------------------------------------------------------------------- /packages/util/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "util", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC" 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@fe-console/*": ["packages/*"] 6 | }, 7 | "declaration": true 8 | }, 9 | "include": ["packages/**/*.ts"], 10 | "exclude": ["node_modules", "dist"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/mp-console/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | rewriteMpApi, 3 | rewriteMpView, 4 | rewriteMpConsole, 5 | FecStorage, 6 | } from "@fe-console/core"; 7 | const mpcStorage = new FecStorage(); 8 | rewriteMpApi(mpcStorage); 9 | rewriteMpView(mpcStorage); 10 | rewriteMpConsole(mpcStorage); 11 | -------------------------------------------------------------------------------- /src/global.d.ts: -------------------------------------------------------------------------------- 1 | declare var getApp: Function; 2 | declare var getCurrentPages: Function; 3 | declare var wx: object; 4 | declare var my: object; 5 | declare var swan: object; 6 | declare var tt: object; 7 | declare var App: Function; 8 | declare var Page: Function; 9 | declare var Component: Function; 10 | declare var global: any; -------------------------------------------------------------------------------- /demo/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages":[ 3 | "pages/index/index" 4 | ], 5 | "window":{ 6 | "backgroundTextStyle":"light", 7 | "navigationBarBackgroundColor": "#fff", 8 | "navigationBarTitleText": "Weixin", 9 | "navigationBarTextStyle":"black" 10 | }, 11 | "style": "v2", 12 | "sitemapLocation": "sitemap.json" 13 | } 14 | -------------------------------------------------------------------------------- /packages/types/util.ts: -------------------------------------------------------------------------------- 1 | export interface FcEventHandler { 2 | (type: string, data?: T); 3 | } 4 | export interface IFcEventEmitter { 5 | on(type: string, handler: FcEventHandler); 6 | once(type: string, handler: FcEventHandler); 7 | off(type: string, handler?: FcEventHandler); 8 | emit(type: string, data?: T); 9 | destory(); 10 | } 11 | -------------------------------------------------------------------------------- /packages/util/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./event-emitter"; 2 | export const now = (() => { 3 | let p; 4 | return (): number => { 5 | if (!p) { 6 | p = 7 | typeof performance !== "undefined" && "now" in performance 8 | ? performance 9 | : Date; 10 | } 11 | return p.now(); 12 | }; 13 | })(); 14 | -------------------------------------------------------------------------------- /packages/provider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "provider", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@mpkit/ebus": "^1.0.15", 14 | "@mpkit/util": "^1.0.15", 15 | "squirrel-report": "^1.0.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/types/parser.ts: -------------------------------------------------------------------------------- 1 | export enum FecDataType { 2 | number = "number", 3 | string = "string", 4 | boolean = "boolean", 5 | function = "function", 6 | object = "object", 7 | ellipsisObject = "ellipsisObject", 8 | null = "null", 9 | array = "array", 10 | undefined = "undefined", 11 | key = "key", 12 | row = "row", 13 | getter = "getter", 14 | protectKey = "protectKey", 15 | br = "br", 16 | symbol = "symbol", 17 | } 18 | -------------------------------------------------------------------------------- /packages/types/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@fe-console/types", 3 | "version": "0.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@mpkit/types": { 8 | "version": "1.0.5", 9 | "resolved": "https://registry.npmjs.org/@mpkit/types/-/types-1.0.5.tgz", 10 | "integrity": "sha512-KOuhccGt8BkRMKxts/SdPHTLOYHjMoTv8g+cDydS2n5U/TOL4Mu+uOkwaDKtkx1FlgjBdA+prOZG8K58uh/bSg==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/provider/producer.ts: -------------------------------------------------------------------------------- 1 | import { 2 | FcProducerRunHandler, 3 | FcProduct, 4 | IFcProducer, 5 | } from "@fe-console/types"; 6 | import { FcEventEmitter, now } from "@fe-console/util"; 7 | import { uuid } from "@mpkit/util"; 8 | /** 9 | * 生产者,只负责生产数据,其他一概不管 10 | */ 11 | export abstract class FcProducerImpl 12 | extends FcEventEmitter> 13 | implements IFcProducer { 14 | constructor(run: FcProducerRunHandler) { 15 | super(); 16 | run(this); 17 | } 18 | create(data: T, time: number = now(), id: string = uuid()) { 19 | this.emit("data", { 20 | data, 21 | time, 22 | id, 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "debug build", 11 | "skipFiles": ["/**"], 12 | "program": "${workspaceFolder}/build/build.js", 13 | "outFiles": ["${workspaceFolder}/**/*.js"] 14 | }, 15 | { 16 | "type": "node", 17 | "request": "launch", 18 | "name": "debug core", 19 | "skipFiles": ["/**"], 20 | "program": "${workspaceFolder}/packages/core/debug.js", 21 | "outFiles": ["${workspaceFolder}/**/*.js"] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /packages/types/provider.ts: -------------------------------------------------------------------------------- 1 | import { IFcEventEmitter } from "./util"; 2 | 3 | export interface FcProduct { 4 | data?: T; 5 | time: number; 6 | id: string; 7 | } 8 | export interface FcProducerRunHandler { 9 | (producer: IFcProducer); 10 | } 11 | export interface IFcProducer extends IFcEventEmitter> { 12 | create(data: T, time?: number, id?: string); 13 | } 14 | export interface FcStoragerRequestHandler { 15 | (data: T | T[]); 16 | } 17 | export interface IFcStorager extends IFcEventEmitter> { 18 | push(data: FcProduct); 19 | destory(); 20 | } 21 | 22 | export interface IFcObserver extends IFcEventEmitter> { 23 | storager?: IFcStorager; 24 | connect(storager?: IFcStorager): Promise; 25 | close(); 26 | call(where: T, eid?: string, timeout?: number): Promise; 27 | } 28 | -------------------------------------------------------------------------------- /packages/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@fe-console/types", 3 | "version": "0.0.0", 4 | "description": "types", 5 | "author": "imingyu ", 6 | "homepage": "https://github.com/imingyu/fe-console/tree/master/packages/types", 7 | "license": "MIT", 8 | "main": "dist/index.cjs.js", 9 | "module": "dist/index.esm.js", 10 | "types": "spec/index.d.ts", 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/imingyu/fe-console.git" 14 | }, 15 | "scripts": {}, 16 | "bugs": { 17 | "url": "https://github.com/imingyu/fe-console/issues" 18 | }, 19 | "publishConfig": { 20 | "access": "public" 21 | }, 22 | "keywords": [ 23 | "fe-console", 24 | "小程序", 25 | "miniprogram", 26 | "小程序开发工具", 27 | "小程序辅助工具" 28 | ], 29 | "dependencies": { 30 | "@mpkit/types": "^1.0.5" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/types/data-parser.ts: -------------------------------------------------------------------------------- 1 | export interface DpItem { 2 | openable: boolean; 3 | opened?: boolean; 4 | value?: any; 5 | feature?: { 6 | [prop: string]: boolean; 7 | }; 8 | } 9 | export interface DpChunk extends DpItem { 10 | type: DpItemType; 11 | children?: DpChild[]; 12 | rows?: DpRow[]; 13 | } 14 | export interface DpChild { 15 | type: DpItemType; 16 | value?: any; 17 | feature?: { 18 | [prop: string]: boolean; 19 | }; 20 | } 21 | export enum DpItemType { 22 | number = "number", 23 | string = "string", 24 | boolean = "boolean", 25 | function = "function", 26 | object = "object", 27 | array = "array", 28 | undefined = "undefined", 29 | symbol = "symbol", 30 | length = "length", 31 | bracket = "bracket", 32 | ellipsisObject = "ellipsisObject", 33 | ellipsisFcuntion = "ellipsisFcuntion", 34 | ellipsisArray = "ellipsisArray", 35 | prop = "prop", 36 | br = "br", 37 | separator = "separator", 38 | } 39 | export interface DpRow extends DpChunk { 40 | prop: string; 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 imingyu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@fe-console/core", 3 | "version": "0.0.0", 4 | "description": "核心功能", 5 | "author": "imingyu ", 6 | "homepage": "https://github.com/imingyu/fe-console/tree/master/packages/core", 7 | "license": "MIT", 8 | "main": "dist/index.cjs.js", 9 | "module": "dist/index.esm.js", 10 | "types": "spec/index.d.ts", 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/imingyu/fe-console.git" 14 | }, 15 | "scripts": {}, 16 | "bugs": { 17 | "url": "https://github.com/imingyu/fe-console/issues" 18 | }, 19 | "publishConfig": { 20 | "access": "public" 21 | }, 22 | "keywords": [ 23 | "fe-console", 24 | "小程序", 25 | "miniprogram", 26 | "小程序开发工具", 27 | "小程序辅助工具" 28 | ], 29 | "dependencies": { 30 | "@mpkit/ebus": "^1.0.6", 31 | "@mpkit/mixin": "^1.0.6", 32 | "@mpkit/types": "^1.0.6", 33 | "@mpkit/util": "^1.0.6" 34 | }, 35 | "devDependencies": { 36 | "chai": "^4.2.0", 37 | "mocha": "^8.1.1" 38 | } 39 | } -------------------------------------------------------------------------------- /demo/project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": true, 9 | "postcss": true, 10 | "preloadBackgroundData": false, 11 | "minified": true, 12 | "newFeature": true, 13 | "coverView": true, 14 | "autoAudits": false, 15 | "showShadowRootInWxmlPanel": true, 16 | "scopeDataCheck": false, 17 | "checkInvalidKey": true, 18 | "checkSiteMap": true, 19 | "uploadWithSourceMap": true, 20 | "babelSetting": { 21 | "ignore": [], 22 | "disablePlugins": [], 23 | "outputPath": "" 24 | }, 25 | "useCompilerModule": true, 26 | "userConfirmedUseCompilerModuleSwitch": false 27 | }, 28 | "compileType": "miniprogram", 29 | "libVersion": "2.12.0", 30 | "appid": "wxdb0fced84d364af9", 31 | "projectname": "MpConsole%E7%A4%BA%E4%BE%8B", 32 | "debugOptions": { 33 | "hidedInDevtools": [] 34 | }, 35 | "isGameTourist": false, 36 | "simulatorType": "wechat", 37 | "simulatorPluginLibVersion": {}, 38 | "condition": { 39 | "search": { 40 | "current": -1, 41 | "list": [] 42 | }, 43 | "conversation": { 44 | "current": -1, 45 | "list": [] 46 | }, 47 | "game": { 48 | "currentL": -1, 49 | "list": [] 50 | }, 51 | "miniprogram": { 52 | "current": -1, 53 | "list": [] 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/mp-console/index.xml: -------------------------------------------------------------------------------- 1 | 2 | Mpc 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{tab.name}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fe-console 2 | 3 | 面向 h5、微信/支付宝/百度/字节跳动小程序的控制台辅助开发工具。 4 | 5 | ## 功能列表 6 | 7 | - [ ] 核心 8 | - [ ] 仅监控数据,不负责数据渲染 9 | - [ ] 可将监控数据实时发送到控制台 10 | - [ ] 控制台 11 | 12 | - [ ] 以 pc 端 web 形式存在 13 | - [ ] 实时以小程序端/h5 端的 UI 样式显示监控数据 14 | - [ ] 可以做日志查看器应用 15 | 16 | - [ ] CLI 17 | - [ ] 无需开发者手动安装 fe-console,仅通过 cli 工具进行安装和卸载 18 | - [ ] 可以将 UI 代码插入小程序端/h5 端 19 | - [ ] 可以将 UI 代码从小程序端/h5 端移除 20 | - [ ] 小程序端 21 | - [ ] `Api`:监控 api 执行记录,并友好化显示其执行结果、状态、子任务(如 WebSocketTask)状态及数据 22 | - [ ] `View`:树结构实时查看 App/Page/Component 实例对象及关系 23 | - [ ] `Method`:监控 App/Page/Component 内的方法执行记录,并友好化显示其执行结果、状态、所在载体等数据 24 | - [ ] `Event`:监控 Component 的事件触发与外部的 Page/Component 的监听记录,并友好化显示其数据及相关载体 25 | - [ ] `Console`:监控`console`对象的相关方法执行,并友好化显示其数据 26 | - [ ] `Storage`:查看及操作 Storage 数据 27 | - [ ] `System`:查看系统数据,如:窗口大小、手机型号、网络状态等 28 | - [ ] H5 端 29 | 30 | - [ ] `Network`:监控网络请求 31 | - [ ] `Elements`:树结构实时查看 html 结构 32 | - [ ] `Console`:监控`console`对象的相关方法执行,并友好化显示其数据 33 | - [ ] `Storage`:查看及操作 Storage 数据 34 | - [ ] `Local Storage` 35 | - [ ] `Session Storage` 36 | - [ ] `Cookies` 37 | - [ ] `IndexedDB` 38 | - [ ] `Web SQL` 39 | - [ ] `Application Cache` 40 | - [ ] `System`:查看系统数据,如:窗口大小、系统版本等 41 | 42 | - 生产者只负责生产数据,其他一概不管 43 | - 存储者负责保存数据,至于怎么保存,存在哪,存多久,看具体实现 44 | - 存储者需要提供接口将保存的数据向外导出 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mp-console", 3 | "version": "1.0.0", 4 | "description": "小程序控制台辅助工具", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "node build/ts.js", 8 | "dev": "node build/dev.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/imingyu/mp-console.git" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/imingyu/mp-console/issues" 18 | }, 19 | "homepage": "https://github.com/imingyu/mp-console#readme", 20 | "devDependencies": { 21 | "@types/node": "^14.0.24", 22 | "autoprefixer": "^9.8.5", 23 | "fs-extra": "^9.0.1", 24 | "lerna": "^3.22.1", 25 | "postcss": "^7.0.32", 26 | "rimraf": "^3.0.2", 27 | "typescript": "^3.9.7", 28 | "watch": "^1.0.2", 29 | "@babel/core": "^7.11.1", 30 | "@babel/preset-env": "^7.11.0", 31 | "@babel/preset-typescript": "^7.10.4", 32 | "@rollup/plugin-babel": "^5.1.0", 33 | "@rollup/plugin-commonjs": "^14.0.0", 34 | "@rollup/plugin-json": "^4.1.0", 35 | "@rollup/plugin-node-resolve": "^8.4.0", 36 | "@rollup/plugin-replace": "^2.3.3", 37 | "@rollup/plugin-typescript": "^5.0.2", 38 | "babel-plugin-lodash": "^3.3.4", 39 | "chai": "^4.2.0", 40 | "fast-xml-parser": "^3.17.4", 41 | "fse": "^4.0.1", 42 | "mocha": "^8.1.1", 43 | "rollup": "^2.23.0" 44 | }, 45 | "dependencies": { 46 | "node-sass": "^4.14.1" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/util/event-emitter.ts: -------------------------------------------------------------------------------- 1 | import { IFcEventEmitter, FcEventHandler } from "@fe-console/types"; 2 | export class FcEventEmitter implements IFcEventEmitter { 3 | private events: { 4 | [prop: string]: FcEventHandler[]; 5 | } = {}; 6 | constructor() { 7 | ["on", "off", "emit"].forEach((prop) => { 8 | this[prop] = this[prop].bind(this); 9 | }); 10 | } 11 | once(type: string, _handler: FcEventHandler) { 12 | const handler = (...args) => { 13 | _handler.apply(args); 14 | this.off(type, handler); 15 | }; 16 | this.on(type, handler); 17 | } 18 | destory() { 19 | this.emit("destory"); 20 | for (let prop in this.events) { 21 | delete this.events[prop]; 22 | } 23 | } 24 | on(type: string, handler: FcEventHandler) { 25 | if (!this.events[type]) { 26 | this.events[type] = []; 27 | } 28 | if (this.events[type].indexOf(handler) === -1) { 29 | this.events[type].push(handler); 30 | } 31 | } 32 | off(type: string, handler?: FcEventHandler) { 33 | if (this.events[type]) { 34 | if (handler) { 35 | const index = this.events[type].indexOf(handler); 36 | index !== -1 && this.events[type].splice(index, 1); 37 | } else { 38 | delete this.events[type]; 39 | } 40 | } 41 | } 42 | emit(type: string, data?: T) { 43 | this.events[type] && 44 | this.events[type].forEach((handler) => { 45 | handler(type, data); 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/mp-console/tpl-view.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import MpcConfig from "./config"; 2 | import { rewriteMP, rewriteConsole, rewriteView } from "./rewrite"; 3 | import { getDataView } from "./viewer"; 4 | import { Storage } from "./storage"; 5 | import { MpViewType, MpPlatfrom } from "./vars"; 6 | import { MP_PLATFORM, MP_API_VAR } from "./util"; 7 | global.getDataView = getDataView; 8 | export const native = { 9 | App, 10 | Page, 11 | Component, 12 | ApiVar: MP_API_VAR, 13 | console, 14 | }; 15 | export const storage = new Storage(); 16 | export const MpcConsole = rewriteConsole(console, storage); 17 | export const MpcApp = rewriteView(App, MpViewType.App, storage); 18 | export const MpcPage = rewriteView(Page, MpViewType.Page, storage); 19 | export const MpcComponent = rewriteView( 20 | Component, 21 | MpViewType.Component, 22 | storage 23 | ); 24 | export const MpcApiVar = rewriteMP(MP_API_VAR, storage); 25 | 26 | // 根据配置重写相关对象 27 | // 重写小程序顶级对象 28 | if (MpcConfig.rewrite) { 29 | if (MpcConfig.rewrite.console) { 30 | console = MpcConsole; 31 | } 32 | if (MpcConfig.rewrite.app) { 33 | App = MpcApp; 34 | } 35 | if (MpcConfig.rewrite.page) { 36 | Page = MpcPage; 37 | } 38 | if (MpcConfig.rewrite.component) { 39 | Component = MpcComponent; 40 | } 41 | if (MpcConfig.rewrite.api) { 42 | if (MP_PLATFORM === MpPlatfrom.wechat) { 43 | wx = MpcApiVar; 44 | } else if (MP_PLATFORM === MpPlatfrom.alipay) { 45 | my = MpcApiVar; 46 | } else if (MP_PLATFORM === MpPlatfrom.smart) { 47 | swan = MpcApiVar; 48 | } else if (MP_PLATFORM === MpPlatfrom.tiktok) { 49 | tt = MpcApiVar; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/provider/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "provider", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@mpkit/ebus": { 8 | "version": "1.0.15", 9 | "resolved": "https://registry.npmjs.org/@mpkit/ebus/-/ebus-1.0.15.tgz", 10 | "integrity": "sha512-ZQTvRCHJoCuvA+ok3eApiO6I8lN+nK6AC06O675KWrNG4BrCzUIYChsTzXq6hF5hlLpFRmi85gwDv2StXVWNtA==", 11 | "requires": { 12 | "@mpkit/types": "^1.0.15", 13 | "@mpkit/util": "^1.0.15" 14 | } 15 | }, 16 | "@mpkit/types": { 17 | "version": "1.0.15", 18 | "resolved": "https://registry.npmjs.org/@mpkit/types/-/types-1.0.15.tgz", 19 | "integrity": "sha512-2d5E6cBRRygU3qrm9MXTCv10cttrUxhsdKdDYR2qLr9TEqts7/TRvgCGw8TcY5ZBs/kCDv3ysmLIzzqZaix8vw==", 20 | "requires": { 21 | "forgiving-xml-parser": "^1.3.0" 22 | } 23 | }, 24 | "@mpkit/util": { 25 | "version": "1.0.15", 26 | "resolved": "https://registry.npmjs.org/@mpkit/util/-/util-1.0.15.tgz", 27 | "integrity": "sha512-LeXZrNNs8y0JoS7FTWRVPWsTwhLodTYXW/pdd12iATY6yfq41NM+Efrpcj4t6n78fqSIaXSbRoa9Co/tEzemXA==", 28 | "requires": { 29 | "@mpkit/types": "^1.0.15" 30 | } 31 | }, 32 | "forgiving-xml-parser": { 33 | "version": "1.3.0", 34 | "resolved": "https://registry.npmjs.org/forgiving-xml-parser/-/forgiving-xml-parser-1.3.0.tgz", 35 | "integrity": "sha512-ozuv6mO2il2go1q5u8EZAWndCM37wRwtxnum/5sLAf0tzWL1GuHLz8Kb6IBEj92hwMSjTyOmRu97DXfF5uhRnA==" 36 | }, 37 | "squirrel-report": { 38 | "version": "1.0.2", 39 | "resolved": "https://registry.npmjs.org/squirrel-report/-/squirrel-report-1.0.2.tgz", 40 | "integrity": "sha512-/0uPJvJHKHJ4kkdlEFW7JgPILFKdHN/MiQbRLK5Lb5Hu3cbffSYpfuLVHbmk0sPaovwLZ9dQqfzKj7u3nzs7nA==" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | demo/mp-console -------------------------------------------------------------------------------- /packages/provider/observer.ts: -------------------------------------------------------------------------------- 1 | import { FcProduct, IFcStorager, IFcObserver } from "@fe-console/types"; 2 | import { FcEventEmitter, now } from "@fe-console/util"; 3 | import { uuid } from "@mpkit/util"; 4 | /** 5 | * 观察者 6 | */ 7 | export abstract class FcObserverImpl 8 | extends FcEventEmitter> 9 | implements IFcObserver { 10 | protected connected: boolean = false; 11 | constructor(public storager: IFcStorager) { 12 | super(); 13 | } 14 | call( 15 | where: T, 16 | eid: string = uuid(), 17 | timeout: number = 10 * 1000 18 | ): Promise { 19 | return (this.connected ? Promise.resolve() : this.connect()).then( 20 | () => { 21 | new Promise((resolve, reject) => { 22 | this.storager.emit(`Request.${eid}`, { 23 | data: where, 24 | time: now(), 25 | id: eid, 26 | }); 27 | let timer = setTimeout(() => { 28 | reject(new Error("Timeout")); 29 | }, timeout); 30 | this.storager.once(`Response.${eid}`, (type, data) => { 31 | timer && clearTimeout(timer); 32 | resolve(data); 33 | }); 34 | this.storager.once( 35 | `Response.Error.${eid}`, 36 | (type, data) => { 37 | timer && clearTimeout(timer); 38 | reject( 39 | data && data.data 40 | ? data.data 41 | : new Error( 42 | typeof data === "string" 43 | ? data 44 | : "未知错误" 45 | ) 46 | ); 47 | } 48 | ); 49 | }); 50 | } 51 | ) as Promise; 52 | } 53 | abstract connect(storager?: IFcStorager): Promise; 54 | abstract close(); 55 | } 56 | -------------------------------------------------------------------------------- /src/mp-console/viewer.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mp-console/index.ts: -------------------------------------------------------------------------------- 1 | import { native, storage } from "../index"; 2 | native.Component({ 3 | data: { 4 | visable: true, 5 | mounted: false, 6 | activeTabIndex: 3, 7 | tabs: [ 8 | { 9 | name: "全部", 10 | value: "all", 11 | }, 12 | { 13 | name: "Console", 14 | value: "console", 15 | }, 16 | { 17 | name: "网络", 18 | value: "network", 19 | }, 20 | { 21 | name: "View", 22 | value: "view", 23 | }, 24 | { 25 | name: "事件", 26 | value: "event", 27 | }, 28 | { 29 | name: "Storage", 30 | value: "storage", 31 | }, 32 | { 33 | name: "Api", 34 | value: "api", 35 | }, 36 | { 37 | name: "系统", 38 | value: "system", 39 | }, 40 | ], 41 | tabData: {}, 42 | }, 43 | methods: { 44 | noop() {}, 45 | toggleVisable() { 46 | this.setData({ 47 | visable: !this.data.visable, 48 | mounted: true, 49 | }); 50 | }, 51 | closeModal() { 52 | this.setData({ 53 | visable: false, 54 | }); 55 | }, 56 | setTab(e) { 57 | const activeTabIndex = parseInt(e.currentTarget.dataset.tab); 58 | this.setData({ 59 | activeTabIndex, 60 | }); 61 | if (this.data.tabs[activeTabIndex].value === "view") { 62 | this.setTabData(this.data.tabs[activeTabIndex].value, [ 63 | storage.getMpViewElementSpec("app"), 64 | ]); 65 | } 66 | }, 67 | setTabData(tabValue, data) { 68 | if (!this.data.tabData[tabValue]) { 69 | this.setData({ 70 | [`tabData.${tabValue}`]: data, 71 | }); 72 | } 73 | }, 74 | tapViewItem(e) { 75 | const mpcId = e.currentTarget.dataset.key; 76 | const view = storage.getMpViewDetail(mpcId); 77 | if(view){ 78 | 79 | } 80 | }, 81 | }, 82 | }); 83 | -------------------------------------------------------------------------------- /packages/mp-console/console/index.ts: -------------------------------------------------------------------------------- 1 | Component({ 2 | data: { 3 | visable: true, 4 | mounted: false, 5 | activeTabIndex: 3, 6 | tabs: [ 7 | { 8 | name: "全部", 9 | value: "all", 10 | }, 11 | { 12 | name: "Console", 13 | value: "console", 14 | }, 15 | { 16 | name: "Api", 17 | value: "api", 18 | }, 19 | { 20 | name: "View", 21 | value: "view", 22 | }, 23 | { 24 | name: "事件", 25 | value: "event", 26 | }, 27 | { 28 | name: "方法", 29 | value: "method", 30 | }, 31 | { 32 | name: "Storage", 33 | value: "storage", 34 | }, 35 | { 36 | name: "系统", 37 | value: "system", 38 | }, 39 | ], 40 | tabData: {}, 41 | }, 42 | methods: { 43 | noop() {}, 44 | toggleVisable() { 45 | this.setData({ 46 | visable: !this.data.visable, 47 | mounted: true, 48 | }); 49 | }, 50 | closeModal() { 51 | this.setData({ 52 | visable: false, 53 | }); 54 | }, 55 | // setTab(e) { 56 | // const activeTabIndex = parseInt(e.currentTarget.dataset.tab); 57 | // this.setData({ 58 | // activeTabIndex, 59 | // }); 60 | // if (this.data.tabs[activeTabIndex].value === "view") { 61 | // this.setTabData(this.data.tabs[activeTabIndex].value, [ 62 | // storage.getMpViewElementSpec("app"), 63 | // ]); 64 | // } 65 | // }, 66 | // setTabData(tabValue, data) { 67 | // if (!this.data.tabData[tabValue]) { 68 | // this.setData({ 69 | // [`tabData.${tabValue}`]: data, 70 | // }); 71 | // } 72 | // }, 73 | // tapViewItem(e) { 74 | // const mpcId = e.currentTarget.dataset.key; 75 | // const view = storage.getMpViewDetail(mpcId); 76 | // if (view) { 77 | // } 78 | // }, 79 | }, 80 | }); 81 | -------------------------------------------------------------------------------- /packages/provider/storager.ts: -------------------------------------------------------------------------------- 1 | import { 2 | FcProduct, 3 | FcStoragerRequestHandler, 4 | IFcStorager, 5 | } from "@fe-console/types"; 6 | import { 7 | Squirrel, 8 | SquirrelOptions, 9 | SwallowStrategyMode, 10 | DataLevel, 11 | SwallowStrategyDetail, 12 | FailAction, 13 | LevelSwallowStrategy, 14 | } from "squirrel-report"; 15 | import { FcEventEmitter } from "@fe-console/util"; 16 | /** 17 | * 存储者,负责保存数据,至于怎么保存,存在哪,存多久,看具体实现 18 | */ 19 | export abstract class FcStoragerImpl 20 | extends FcEventEmitter> 21 | implements IFcStorager { 22 | constructor() { 23 | super(); 24 | } 25 | push(data: FcProduct) { 26 | this.emit("data", data); 27 | } 28 | } 29 | 30 | /** 31 | * 存储数据在内存中 32 | */ 33 | export abstract class FcMemoryStoragerImpl 34 | extends FcEventEmitter> 35 | implements IFcStorager { 36 | protected list: FcProduct[] = []; 37 | constructor() { 38 | super(); 39 | } 40 | push(data: FcProduct) { 41 | this.list.push(data); 42 | this.emit("data", data); 43 | } 44 | destory() { 45 | super.destory(); 46 | this.list.splice(0, this.list.length); 47 | } 48 | } 49 | 50 | /** 51 | * 存储数据到网络中 52 | */ 53 | export abstract class FcNetworkStoragerImpl extends FcStoragerImpl { 54 | protected reporter: Squirrel; 55 | constructor( 56 | public request: FcStoragerRequestHandler>, 57 | reportOptions?: SquirrelOptions 58 | ) { 59 | super(); 60 | if (!reportOptions) { 61 | // 数据还是存在内存中,如果插入的数据优先级较高时才上传 62 | reportOptions = { 63 | adapter: this.request, 64 | failAction: FailAction.recovery, 65 | strategy: { 66 | [DataLevel.high]: { 67 | mode: SwallowStrategyMode.intervalCount, 68 | value: 1, 69 | } as SwallowStrategyDetail, 70 | } as LevelSwallowStrategy, 71 | }; 72 | } 73 | this.reporter = new Squirrel(reportOptions); 74 | } 75 | push(data: FcProduct, level: DataLevel = DataLevel.normal) { 76 | super.push(data); 77 | this.reporter.stuff(data, level); 78 | } 79 | destory() { 80 | super.destory(); 81 | this.reporter && this.reporter.destory(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /packages/types/storage.ts: -------------------------------------------------------------------------------- 1 | import { MpView, EBus, MkMap } from "@mpkit/types"; 2 | export enum FecStorageType { 3 | Api = "Api", 4 | View = "View", 5 | Method = "Method", 6 | Console = "Console", 7 | Event = "Event", 8 | } 9 | export interface FecStorageDataLike { 10 | id?: string; 11 | type: FecStorageType; 12 | time?: number; 13 | } 14 | export interface FecStorageData extends FecStorageDataLike { 15 | id: string; 16 | time: number; 17 | } 18 | interface MethodData extends FecStorageData { 19 | name: string; 20 | args: any[]; 21 | result?: any; 22 | status: FecMethodStatus; 23 | endTime?: number; 24 | error?: Error; 25 | errorType?: string; 26 | } 27 | export interface FecStorageMethodData extends MethodData { 28 | view: MpView; 29 | } 30 | export interface FecStorageViewData extends FecStorageData { 31 | view: MpView; 32 | } 33 | export enum FecMethodStatus { 34 | Executed = "Executed", 35 | Success = "Success", 36 | Fail = "Fail", 37 | } 38 | export enum MpHasTaskApi { 39 | request = "request", 40 | downloadFile = "downloadFile", 41 | uploadFile = "uploadFile", 42 | connectSocket = "connectSocket", 43 | createUDPSocket = "createUDPSocket", 44 | } 45 | export interface FecStorageApiData extends MethodData { 46 | response?: any; 47 | children?: FecStorageApiData[]; 48 | } 49 | export interface MpEventTarget { 50 | dataset: any; 51 | } 52 | export interface MpEvent { 53 | type: string; 54 | target: MpEventTarget; 55 | currentTarget: MpEventTarget; 56 | detail: any; 57 | } 58 | export interface FecStorageEventData extends FecStorageData { 59 | name: string; 60 | args: any[]; 61 | event: MpEvent; 62 | triggerView: MpView; 63 | handleView: MpView; 64 | } 65 | export interface FecStorageConsoleData extends FecStorageData { 66 | args: any[]; 67 | } 68 | export interface FecStorageFinder { 69 | (item: T, index: number, arr: T[]): boolean; 70 | } 71 | 72 | export interface FecStorageLike extends EBus { 73 | push(data: FecStorageDataLike); 74 | pushApiTask(apiData: FecStorageApiData); 75 | removeApiTask(apiName: MpHasTaskApi, dataId: string); 76 | getApiTaskMap(apiName: MpHasTaskApi): MkMap; 77 | get(id: string): FecStorageData; 78 | getAll(): FecStorageData[]; 79 | getType(type: FecStorageType): FecStorageData[]; 80 | findType( 81 | type: FecStorageType, 82 | finder: FecStorageFinder 83 | ): null | FecStorageData; 84 | filterType( 85 | type: FecStorageType, 86 | finder: FecStorageFinder 87 | ): FecStorageData[]; 88 | } 89 | -------------------------------------------------------------------------------- /packages/core/storage.ts: -------------------------------------------------------------------------------- 1 | import { 2 | FecStorageLike, 3 | FecStorageData, 4 | FecStorageDataLike, 5 | FecStorageType, 6 | FecStorageFinder, 7 | FecStorageApiData, 8 | MpHasTaskApi, 9 | } from "@fe-console/types"; 10 | import { EventEmitter } from "@mpkit/ebus"; 11 | import { MkEnumMap, MkMap } from "@mpkit/types"; 12 | import { uuid } from "@mpkit/util"; 13 | export default class FecStorage extends EventEmitter implements FecStorageLike { 14 | private dataMap: MkEnumMap; 15 | private idMap: MkMap; 16 | private apiTaskMap: MkEnumMap>; 17 | constructor() { 18 | super(); 19 | this.idMap = {} as MkMap; 20 | this.apiTaskMap = {} as MkEnumMap< 21 | MpHasTaskApi, 22 | MkMap 23 | >; 24 | this.dataMap = {} as MkEnumMap; 25 | for (let prop in FecStorageType) { 26 | this.dataMap[prop] = []; 27 | } 28 | for (let prop in MpHasTaskApi) { 29 | this.apiTaskMap[prop] = {}; 30 | } 31 | } 32 | push(data: FecStorageDataLike) { 33 | if (!data.id) { 34 | data.id = uuid(); 35 | } 36 | if (!data.time) { 37 | data.time = Date.now(); 38 | } 39 | this.dataMap[data.type].push(data as FecStorageData); 40 | this.emit(`Push.${data.type}`, data); 41 | } 42 | pushApiTask(apiData: FecStorageApiData) { 43 | this.apiTaskMap[apiData.name][apiData.id] = apiData; 44 | this.emit(`Push.ApiTask`, apiData); 45 | } 46 | removeApiTask(apiName: MpHasTaskApi, dataId: string) { 47 | const map = this.apiTaskMap[apiName]; 48 | if (map) { 49 | const apiData = map[dataId]; 50 | delete map[dataId]; 51 | this.emit(`Remove.ApiTask`, apiData); 52 | } 53 | } 54 | getApiTaskMap(apiName: MpHasTaskApi): MkMap { 55 | return this.apiTaskMap[apiName]; 56 | } 57 | get(id: string) { 58 | return this.idMap[id]; 59 | } 60 | getAll(): FecStorageData[] { 61 | return Object.keys(this.dataMap).reduce((sum, item) => { 62 | return sum.concat(this.dataMap[item]); 63 | }, []); 64 | } 65 | getType(type: FecStorageType): FecStorageData[] { 66 | return this.dataMap[type]; 67 | } 68 | findType( 69 | type: FecStorageType, 70 | finder: FecStorageFinder 71 | ): FecStorageData { 72 | return this.dataMap[type].find(finder); 73 | } 74 | filterType( 75 | type: FecStorageType, 76 | finder: FecStorageFinder 77 | ): FecStorageData[] { 78 | return this.dataMap[type].filter(finder); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/vquery.ts: -------------------------------------------------------------------------------- 1 | import { IMap } from "./util"; 2 | 3 | export default class VQuery { 4 | private idMap: IMap = {} as IMap; 5 | private parentMap: IMap = {} as IMap; 6 | private childrenMap: IMap = {} as IMap; 7 | private idFiledName: string; 8 | constructor(idFiledName: string) { 9 | this.idFiledName = idFiledName; 10 | } 11 | add(el: T) { 12 | this.idMap[el[this.idFiledName]] = el; 13 | } 14 | 15 | getMpType() { 16 | if (typeof wx === "object") { 17 | return "wechat"; 18 | } else if (typeof my === "object") { 19 | return "alipay"; 20 | } else if (typeof swan === "object") { 21 | return "smart"; 22 | } else if (typeof tt === "object") { 23 | return "tiktok"; 24 | } else { 25 | return "unknown"; 26 | } 27 | } 28 | 29 | getElType(el: T) { 30 | const mpType = this.getMpType(); 31 | } 32 | 33 | queryRelation(el: T, refresh: boolean = false) { 34 | const id = el[this.idFiledName]; 35 | if (!this.parentMap[id] || refresh) { 36 | const tsEl = el as any; 37 | if (typeof tsEl.selectOwnerComponent === "function") { 38 | // wechat 39 | const parent = tsEl.selectOwnerComponent() as void | T; 40 | if (parent) { 41 | this.parentMap[id] = parent; 42 | const parentId = parent[this.idFiledName]; 43 | if (!this.childrenMap[parentId]) { 44 | this.childrenMap[parentId] = [] as T[]; 45 | } 46 | this.childrenMap[parentId].push(el); 47 | } 48 | } else if (typeof tsEl.selectAllComponents === "function") { 49 | // tiktok 50 | } 51 | } 52 | } 53 | 54 | get(id: string): T { 55 | return this.idMap[id]; 56 | } 57 | getElSelector(el: T) { 58 | const tsEl = el as any; 59 | let res = ""; 60 | if (tsEl.id) { 61 | res += `#${tsEl.id}`; 62 | } 63 | if (tsEl.className) { 64 | res += 65 | "." + 66 | tsEl.className 67 | .split(" ") 68 | .reduce((sum, item) => { 69 | if ((item = item && item.trim())) { 70 | sum.push(item); 71 | } 72 | return sum; 73 | }, []) 74 | .join("."); 75 | } 76 | return res; 77 | } 78 | getParent(id: string | T): Promise { 79 | const tsId = 80 | typeof id === "string" 81 | ? id 82 | : ((id as T)[this.idFiledName] as string); 83 | return this.parentMap[tsId]; 84 | } 85 | getChildren(id: string | T): Promise { 86 | const tsId = 87 | typeof id === "string" 88 | ? id 89 | : ((id as T)[this.idFiledName] as string); 90 | return this.childrenMap[tsId]; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/vars.ts: -------------------------------------------------------------------------------- 1 | import { Storage } from "./storage"; 2 | import { DataViewLike } from "./viewer"; 3 | 4 | export enum MpViewType { 5 | App = "App", 6 | Page = "Page", 7 | Component = "Component", 8 | } 9 | export enum MpPlatfrom { 10 | wechat = "wechat", 11 | alipay = "alipay", 12 | smart = "smart", 13 | tiktok = "tiktok", 14 | unknown = "unknown", 15 | } 16 | export interface ApiHandler { 17 | (res: any); 18 | } 19 | export interface ApiOptions { 20 | success: ApiHandler; 21 | fail: ApiHandler; 22 | } 23 | export interface MpViewSpec { 24 | data: any; 25 | } 26 | export interface MpViewComponetPropSpec { 27 | type: Function; 28 | default?: any; 29 | observer?: Function; 30 | } 31 | export interface MpViewComponentSpec extends MpViewSpec { 32 | properties?: { 33 | [prop: string]: Function | MpViewComponetPropSpec; 34 | }; 35 | methods: { 36 | [prop: string]: Function; 37 | }; 38 | } 39 | export interface MpViewLike { 40 | $viewSpec: MpViewSpec; 41 | $viewType: MpViewType; 42 | $mpcId: string; 43 | $mpcStorage: Storage; 44 | $mpcInitState: boolean; 45 | $isRewriteSetData?: boolean; 46 | $nativeSetData: SetDataHandler; 47 | data: any; 48 | setData: SetDataHandler; 49 | } 50 | export interface MpWechatSelectOwnerComponent { 51 | (): void | MpViewLike; 52 | } 53 | export interface MpWechatView extends MpViewLike { 54 | __wxExparserNodeId__: string; 55 | __wxWebviewId__: number; 56 | is: string; 57 | selectOwnerComponent: MpWechatSelectOwnerComponent; 58 | } 59 | export interface MpTiktokView extends MpViewLike { 60 | __webviewId__: number; 61 | __nodeId__: number; 62 | is: string; 63 | } 64 | export interface MpComponentPropObserver { 65 | (this: MpViewLike, oldValue: any, newVal: any): void; 66 | } 67 | 68 | export interface MpComponentPropSpec { 69 | type: Function; 70 | default: any; 71 | observer: MpComponentPropObserver; 72 | } 73 | 74 | export interface MpAlipayView extends MpViewLike { 75 | $id: number; 76 | } 77 | 78 | export interface MpAlipayViewPage extends MpAlipayView { 79 | $viewId: string; 80 | route: string; 81 | } 82 | export interface MpAlipayViewComponent extends MpAlipayView { 83 | $page: MpAlipayViewPage; 84 | is: string; 85 | props: { 86 | [prop: string]: any; 87 | __tag: string; 88 | }; 89 | } 90 | export interface MpSmartViewPage extends MpViewLike { 91 | route: string; 92 | } 93 | export interface MpSmartViewComponent extends MpViewLike { 94 | componentName: string; 95 | nodeId: string; 96 | pageinstance: MpSmartViewPage; 97 | is: string; 98 | } 99 | export interface SetDataHandler { 100 | (data: any, callback?: Function): void; 101 | } 102 | 103 | export interface MpViewElementSpec { 104 | key: string; 105 | tag: string; 106 | is: string; 107 | active?: boolean; 108 | open?: boolean; 109 | openable?: boolean; 110 | view: MpViewLike; 111 | attrs?: DataViewLike[]; 112 | events?: { 113 | [prop: string]: string; 114 | }; 115 | children?: MpViewElementSpec[]; 116 | } 117 | -------------------------------------------------------------------------------- /src/mp-console/index.scss: -------------------------------------------------------------------------------- 1 | $tab-bar-bg:rgb(243, 243, 243); 2 | $tab-bar-color:rgb(51, 51, 51); 3 | $tab-bar-height:80rpx; 4 | $tab-bar-brcolor:rgb(204, 204, 204); 5 | $tab-bar-item-active-brcolor:rgb(26, 115, 234); 6 | $cr-string:rgb(196, 26, 22); 7 | $cr-fold:rgb(114, 114, 114); 8 | $attr-margin:14rpx; 9 | $fold-size:12rpx; 10 | 11 | .mpc-hand { 12 | position: fixed; 13 | bottom: 100rpx; 14 | right: 100rpx; 15 | border-radius: 50%; 16 | width: 100rpx; 17 | height: 100rpx; 18 | background-color: #000; 19 | color: #fff; 20 | font-size: 30rpx; 21 | text-align: center; 22 | line-height: 100rpx; 23 | 24 | &.is-hide { 25 | display: none; 26 | } 27 | } 28 | 29 | .mpc-modal { 30 | position: fixed; 31 | top: 0; 32 | left: 0; 33 | right: 0; 34 | bottom: 0; 35 | color: rgb(51, 51, 51); 36 | } 37 | 38 | .mpc-modal-body { 39 | position: absolute; 40 | left: 0; 41 | right: 0; 42 | bottom: 0; 43 | height: 70%; 44 | background-color: #fff; 45 | display: flex; 46 | flex-direction: column; 47 | } 48 | 49 | .mpc-tabs-container { 50 | background: $tab-bar-bg; 51 | color: $tab-bar-color; 52 | border-top: 1px solid $tab-bar-brcolor; 53 | border-bottom: 1px solid $tab-bar-brcolor; 54 | flex-shrink: 0; 55 | } 56 | 57 | .mpc-tabs-body { 58 | height: 100%; 59 | flex-shrink: 1; 60 | } 61 | 62 | .mpc-tabs { 63 | display: flex; 64 | flex-wrap: nowrap; 65 | margin-bottom: -1px; 66 | } 67 | 68 | .mpc-tab { 69 | box-sizing: border-box; 70 | flex-shrink: 0; 71 | height: $tab-bar-height; 72 | line-height: $tab-bar-height; 73 | padding: 0 30rpx; 74 | text-align: center; 75 | border-bottom: 6rpx solid transparent; 76 | font-size: 28rpx; 77 | transition: border-color .5s; 78 | 79 | &.active { 80 | border-bottom-color: $tab-bar-item-active-brcolor; 81 | } 82 | } 83 | 84 | .mpc-tabs-panels { 85 | display: flex; 86 | flex-wrap: nowrap; 87 | overflow: hidden; 88 | box-sizing: border-box; 89 | transition: transform .5s; 90 | 91 | .mpc-tabs-panel { 92 | flex-shrink: 0; 93 | flex: 1; 94 | box-sizing: border-box; 95 | padding: 20rpx 0; 96 | } 97 | } 98 | 99 | .mpc-item { 100 | font-size: 30rpx; 101 | padding: 0 20rpx; 102 | 103 | &.is-fold { 104 | padding-left: 20rpx+$fold-size+10rpx; 105 | 106 | &::before { 107 | left: 20rpx; 108 | } 109 | } 110 | } 111 | 112 | .is-fold { 113 | padding-left: $fold-size+10rpx; 114 | position: relative; 115 | 116 | &:before { 117 | content: ''; 118 | position: absolute; 119 | top: 0; 120 | left: 0; 121 | width: $fold-size; 122 | height: $fold-size; 123 | overflow: hidden; 124 | border: $fold-size solid transparent; 125 | border-left-color: $cr-fold; 126 | box-sizing: border-box; 127 | } 128 | 129 | &.is-open { 130 | border-left-color: none; 131 | border-top-color: $cr-fold; 132 | } 133 | } 134 | 135 | 136 | .mpc-item-view { 137 | &:hover { 138 | background-color: rgb(235, 241, 251); 139 | } 140 | 141 | &:before { 142 | top: 12rpx; 143 | } 144 | 145 | .view-head, 146 | .view-body, 147 | .view-footer { 148 | display: inline-block; 149 | } 150 | 151 | &.is-open { 152 | .view-head { 153 | background-color: rgb(207, 232, 252); 154 | } 155 | 156 | .view-head, 157 | .view-body, 158 | .view-footer { 159 | display: block; 160 | } 161 | 162 | .view-arrow.arrow-end { 163 | margin-left: 0; 164 | } 165 | } 166 | 167 | .view-arrow.arrow-end { 168 | margin-left: $attr-margin; 169 | } 170 | 171 | .view-part, 172 | .attr-part { 173 | display: inline-block; 174 | } 175 | 176 | .view-arrow, 177 | .attr-equal, 178 | .attr-sem { 179 | color: rgb(169, 149, 167); 180 | } 181 | 182 | .view-tag { 183 | color: rgb(140, 29, 134); 184 | } 185 | 186 | .view-attr { 187 | margin-left: $attr-margin; 188 | } 189 | 190 | .attr-name { 191 | color: rgb(154, 72, 4); 192 | } 193 | 194 | .attr-value { 195 | color: rgb(26, 26, 166); 196 | 197 | &.attr-string { 198 | color: $cr-string; 199 | } 200 | } 201 | } -------------------------------------------------------------------------------- /packages/mp-console/console/index.scss: -------------------------------------------------------------------------------- 1 | $tab-bar-bg:rgb(243, 243, 243); 2 | $tab-bar-color:rgb(51, 51, 51); 3 | $tab-bar-height:80rpx; 4 | $tab-bar-brcolor:rgb(204, 204, 204); 5 | $tab-bar-item-active-brcolor:rgb(26, 115, 234); 6 | $cr-string:rgb(196, 26, 22); 7 | $cr-fold:rgb(114, 114, 114); 8 | $attr-margin:14rpx; 9 | $fold-size:12rpx; 10 | 11 | .mpc-hand { 12 | position: fixed; 13 | bottom: 100rpx; 14 | right: 100rpx; 15 | border-radius: 50%; 16 | width: 100rpx; 17 | height: 100rpx; 18 | background-color: #000; 19 | color: #fff; 20 | font-size: 30rpx; 21 | text-align: center; 22 | line-height: 100rpx; 23 | 24 | &.is-hide { 25 | display: none; 26 | } 27 | } 28 | 29 | .mpc-modal { 30 | position: fixed; 31 | top: 0; 32 | left: 0; 33 | right: 0; 34 | bottom: 0; 35 | color: rgb(51, 51, 51); 36 | } 37 | 38 | .mpc-modal-body { 39 | position: absolute; 40 | left: 0; 41 | right: 0; 42 | bottom: 0; 43 | height: 70%; 44 | background-color: #fff; 45 | display: flex; 46 | flex-direction: column; 47 | } 48 | 49 | .mpc-tabs-container { 50 | background: $tab-bar-bg; 51 | color: $tab-bar-color; 52 | border-top: 1px solid $tab-bar-brcolor; 53 | border-bottom: 1px solid $tab-bar-brcolor; 54 | flex-shrink: 0; 55 | } 56 | 57 | .mpc-tabs-body { 58 | height: 100%; 59 | flex-shrink: 1; 60 | } 61 | 62 | .mpc-tabs { 63 | display: flex; 64 | flex-wrap: nowrap; 65 | margin-bottom: -1px; 66 | } 67 | 68 | .mpc-tab { 69 | box-sizing: border-box; 70 | flex-shrink: 0; 71 | height: $tab-bar-height; 72 | line-height: $tab-bar-height; 73 | padding: 0 30rpx; 74 | text-align: center; 75 | border-bottom: 6rpx solid transparent; 76 | font-size: 28rpx; 77 | transition: border-color .5s; 78 | 79 | &.active { 80 | border-bottom-color: $tab-bar-item-active-brcolor; 81 | } 82 | } 83 | 84 | .mpc-tabs-panels { 85 | display: flex; 86 | flex-wrap: nowrap; 87 | overflow: hidden; 88 | box-sizing: border-box; 89 | transition: transform .5s; 90 | 91 | .mpc-tabs-panel { 92 | flex-shrink: 0; 93 | flex: 1; 94 | box-sizing: border-box; 95 | padding: 20rpx 0; 96 | } 97 | } 98 | 99 | .mpc-item { 100 | font-size: 30rpx; 101 | padding: 0 20rpx; 102 | 103 | &.is-fold { 104 | padding-left: 20rpx+$fold-size+10rpx; 105 | 106 | &::before { 107 | left: 20rpx; 108 | } 109 | } 110 | } 111 | 112 | .is-fold { 113 | padding-left: $fold-size+10rpx; 114 | position: relative; 115 | 116 | &:before { 117 | content: ''; 118 | position: absolute; 119 | top: 0; 120 | left: 0; 121 | width: $fold-size; 122 | height: $fold-size; 123 | overflow: hidden; 124 | border: $fold-size solid transparent; 125 | border-left-color: $cr-fold; 126 | box-sizing: border-box; 127 | } 128 | 129 | &.is-open { 130 | border-left-color: none; 131 | border-top-color: $cr-fold; 132 | } 133 | } 134 | 135 | 136 | .mpc-item-view { 137 | &:hover { 138 | background-color: rgb(235, 241, 251); 139 | } 140 | 141 | &:before { 142 | top: 12rpx; 143 | } 144 | 145 | .view-head, 146 | .view-body, 147 | .view-footer { 148 | display: inline-block; 149 | } 150 | 151 | &.is-open { 152 | .view-head { 153 | background-color: rgb(207, 232, 252); 154 | } 155 | 156 | .view-head, 157 | .view-body, 158 | .view-footer { 159 | display: block; 160 | } 161 | 162 | .view-arrow.arrow-end { 163 | margin-left: 0; 164 | } 165 | } 166 | 167 | .view-arrow.arrow-end { 168 | margin-left: $attr-margin; 169 | } 170 | 171 | .view-part, 172 | .attr-part { 173 | display: inline-block; 174 | } 175 | 176 | .view-arrow, 177 | .attr-equal, 178 | .attr-sem { 179 | color: rgb(169, 149, 167); 180 | } 181 | 182 | .view-tag { 183 | color: rgb(140, 29, 134); 184 | } 185 | 186 | .view-attr { 187 | margin-left: $attr-margin; 188 | } 189 | 190 | .attr-name { 191 | color: rgb(154, 72, 4); 192 | } 193 | 194 | .attr-value { 195 | color: rgb(26, 26, 166); 196 | 197 | &.attr-string { 198 | color: $cr-string; 199 | } 200 | } 201 | } -------------------------------------------------------------------------------- /packages/core/data-parser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DpChunk, 3 | DpChild, 4 | DpRow, 5 | DpItemType, 6 | } from "@fe-console/types/data-parser"; 7 | 8 | const getDpType = (obj): DpItemType => { 9 | const type = typeof obj; 10 | if (type === "object") { 11 | if (Array.isArray(obj)) { 12 | return DpItemType.array; 13 | } 14 | return DpItemType.object; 15 | } 16 | return DpItemType[type]; 17 | }; 18 | const isBaseType = (type: DpItemType) => { 19 | return ( 20 | type === DpItemType.boolean || 21 | type === DpItemType.number || 22 | type === DpItemType.string || 23 | type === DpItemType.undefined 24 | ); 25 | }; 26 | const isOpenable = (type: DpItemType) => { 27 | return ( 28 | type === DpItemType.array || 29 | type === DpItemType.object || 30 | type === DpItemType.function || 31 | type === DpItemType.symbol 32 | ); 33 | }; 34 | const getFunHead = (fun) => { 35 | const str = fun.toString(); 36 | const funName = fun.name; 37 | if (fun.name) { 38 | } 39 | let index; 40 | const index1 = str.indexOf("{"); 41 | const index2 = str.indexOf("=>"); 42 | if (index1 !== -1 && index2 !== -1) { 43 | index = index1 < index2 ? index1 : index2; 44 | } else if (index1 !== -1) { 45 | index = index1; 46 | } else { 47 | index = index2; 48 | } 49 | let head = str.substr(0, index); 50 | head.replace("function ", ""); 51 | // TODO:待完善 52 | return head; 53 | }; 54 | const notOpenPushChildren = ( 55 | children: DpChild[], 56 | type: DpItemType, 57 | value: any, 58 | ellipsis?: boolean 59 | ): boolean => { 60 | if (isBaseType(type)) { 61 | children.push({ 62 | type, 63 | value, 64 | }); 65 | return true; 66 | } 67 | if (type === DpItemType.symbol) { 68 | children.push({ 69 | type: DpItemType.symbol, 70 | value: value.toString(), 71 | }); 72 | return true; 73 | } 74 | if (ellipsis) { 75 | if (type === DpItemType.function) { 76 | children.push({ 77 | type: DpItemType.ellipsisFcuntion, 78 | value: "ƒ", 79 | }); 80 | return true; 81 | } 82 | if (type === DpItemType.object) { 83 | children.push({ 84 | type: DpItemType.ellipsisObject, 85 | value: "{...}", 86 | }); 87 | } else if (type === DpItemType.array) { 88 | children.push({ 89 | type: DpItemType.ellipsisArray, 90 | value: `Array(${value.length})`, 91 | }); 92 | } 93 | } 94 | return false; 95 | }; 96 | export default function parse( 97 | type: "chunk" | "child" | "row", 98 | ...source 99 | ): Array { 100 | if (type === "chunk") { 101 | return source.reduce((sum, item) => { 102 | const valType = getDpType(item); 103 | if (valType === DpItemType.object || valType === DpItemType.array) { 104 | sum.push({ 105 | type: valType, 106 | openable: true, 107 | opened: false, 108 | children: parse("child", item, valType), 109 | }); 110 | } else if (valType === DpItemType.function) { 111 | sum.push({ 112 | type: valType, 113 | value: item.toString().substr(0, 100), 114 | }); 115 | } else { 116 | notOpenPushChildren(sum, valType, item, false); 117 | } 118 | return sum; 119 | }, []) as DpChunk[]; 120 | } else if (type === "child") { 121 | const obj = source[0]; 122 | const type = source[1] as DpItemType; 123 | const children: DpChild[] = []; 124 | if (!notOpenPushChildren(children, type, obj)) { 125 | if (type === DpItemType.object) { 126 | children.push({ 127 | type: DpItemType.bracket, 128 | value: "{", 129 | }); 130 | Object.keys(obj).forEach((key, index, arr) => { 131 | children.push({ 132 | type: DpItemType.prop, 133 | value: key, 134 | }); 135 | children.push({ 136 | type: DpItemType.separator, 137 | value: ":", 138 | }); 139 | const value = obj[key]; 140 | notOpenPushChildren( 141 | children, 142 | getDpType(value), 143 | value, 144 | true 145 | ); 146 | if (index < arr.length - 1) { 147 | children.push({ 148 | type: DpItemType.separator, 149 | value: ",", 150 | }); 151 | } 152 | }); 153 | children.push({ 154 | type: DpItemType.bracket, 155 | value: "}", 156 | }); 157 | } else if (type === DpItemType.array) { 158 | children.push({ 159 | type: DpItemType.length, 160 | value: `(${obj.length})`, 161 | }); 162 | children.push({ 163 | type: DpItemType.bracket, 164 | value: "[", 165 | }); 166 | obj.forEach((item) => { 167 | notOpenPushChildren(children, getDpType(item), item, true); 168 | }); 169 | children.push({ 170 | type: DpItemType.bracket, 171 | value: "]", 172 | }); 173 | } 174 | } 175 | if (children.length) { 176 | return children; 177 | } 178 | return; 179 | } else if (type === "row") { 180 | const obj = source[0]; 181 | return Object.keys(obj).map((prop) => { 182 | const value = obj[prop]; 183 | const type = getDpType(value); 184 | const dpRow: DpRow = { 185 | prop, 186 | type, 187 | openable: isOpenable(type), 188 | }; 189 | if (isBaseType(type)) { 190 | dpRow.value = value; 191 | } else if (type === DpItemType.symbol) { 192 | dpRow.value = value.toString(); 193 | } else if (type === DpItemType.function) { 194 | dpRow.value = getFunHead(value); 195 | } 196 | if (dpRow.openable) { 197 | dpRow.opened = false; 198 | const children = parse("child", value, type) as DpRow[]; 199 | if (children && children.length) { 200 | dpRow.children = children; 201 | } 202 | } 203 | return dpRow; 204 | }) as DpRow[]; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/viewer.ts: -------------------------------------------------------------------------------- 1 | import { isArray, uuid, IMap } from "./util"; 2 | export enum DataViewType { 3 | number = "number", 4 | string = "string", 5 | boolean = "boolean", 6 | function = "function", 7 | object = "object", 8 | ellipsisObject = "ellipsisObject", 9 | null = "null", 10 | array = "array", 11 | undefined = "undefined", 12 | key = "key", 13 | row = "row", 14 | getter = "getter", 15 | protectKey = "protectKey", 16 | br = "br", 17 | symbol = "symbol", 18 | } 19 | export interface DataViewLike { 20 | name?: string; 21 | key?: string; 22 | type: DataViewType; 23 | value?: any; 24 | chilren?: DataView[]; 25 | length?: number; 26 | original?: any; 27 | open?: boolean; 28 | objectKey?: boolean; 29 | arrayKey?: boolean; 30 | } 31 | export interface DataView extends DataViewLike { 32 | key: string; 33 | } 34 | 35 | export interface DataViewResult { 36 | detail: DataView | DataView[]; 37 | map: IMap; 38 | } 39 | 40 | export interface ParseDataViewOptions { 41 | convertBr?: boolean; 42 | getChilren?: boolean; 43 | ellipsisObject?: boolean; 44 | maxArrShowItemCount: number; 45 | arrShowItemCount: number; 46 | maxObjectShowKeysCount: number; 47 | objectShowKeysCount: number; 48 | } 49 | const DEFAULT_ITEM_COUNT = 10; 50 | export const getDataView = ( 51 | obj, 52 | options: ParseDataViewOptions = { 53 | maxArrShowItemCount: DEFAULT_ITEM_COUNT, 54 | arrShowItemCount: DEFAULT_ITEM_COUNT, 55 | maxObjectShowKeysCount: DEFAULT_ITEM_COUNT, 56 | objectShowKeysCount: DEFAULT_ITEM_COUNT, 57 | }, 58 | map?: IMap, 59 | objName?: string 60 | ): DataViewResult => { 61 | const { 62 | convertBr, 63 | ellipsisObject, 64 | getChilren, 65 | maxArrShowItemCount, 66 | arrShowItemCount, 67 | maxObjectShowKeysCount, 68 | objectShowKeysCount, 69 | } = options; 70 | const subOptions: ParseDataViewOptions = JSON.parse( 71 | JSON.stringify(options) 72 | ); 73 | subOptions.convertBr = false; 74 | subOptions.getChilren = !subOptions.getChilren; 75 | let detail; 76 | if (!map) { 77 | map = {} as IMap; 78 | } 79 | const newView = (dt: DataViewLike): DataView => { 80 | const key = uuid(); 81 | dt.key = key; 82 | const original = dt.original; 83 | delete dt.original; 84 | map[key] = { 85 | ...dt, 86 | original, 87 | }; 88 | return dt as DataView; 89 | }; 90 | 91 | const argType = typeof obj; 92 | if (argType === "string") { 93 | if (obj.indexOf("\n") !== -1 && convertBr) { 94 | detail = [] as DataView[]; 95 | obj.split("\n").forEach((str) => { 96 | detail.push( 97 | newView({ 98 | type: DataViewType.string, 99 | value: str, 100 | }) 101 | ); 102 | detail.push( 103 | newView({ 104 | type: DataViewType.br, 105 | }) 106 | ); 107 | }); 108 | } else { 109 | detail = newView({ 110 | type: DataViewType.string, 111 | value: obj, 112 | }); 113 | } 114 | } else if ( 115 | argType === "boolean" || 116 | argType === "undefined" || 117 | argType === "number" || 118 | argType === "symbol" || 119 | obj === null 120 | ) { 121 | detail = newView({ 122 | type: obj === null ? DataViewType.null : DataViewType[argType], 123 | value: argType === "symbol" ? obj.toString() : obj, 124 | }); 125 | } else if (argType === "function") { 126 | detail = newView({ 127 | type: DataViewType.function, 128 | original: obj, 129 | }); 130 | } else if (isArray(obj)) { 131 | subOptions.ellipsisObject = true; 132 | subOptions.convertBr = false; 133 | detail = newView({ 134 | type: DataViewType.array, 135 | length: obj.length, 136 | original: obj, 137 | [`${getChilren ? "children" : "value"}`]: obj 138 | .slice(0, getChilren ? maxArrShowItemCount : arrShowItemCount) 139 | .reduce((sum, item, index): DataView[] => { 140 | const res = getDataView(item, subOptions, map).detail; 141 | if (getChilren) { 142 | sum.push( 143 | newView({ 144 | type: DataViewType.row, 145 | value: [ 146 | newView({ 147 | type: DataViewType.key, 148 | value: index, 149 | arrayKey: true, 150 | }), 151 | ...(isArray(res) 152 | ? (res as DataView[]) 153 | : [res]), 154 | ], 155 | }) 156 | ); 157 | } else { 158 | sum.push( 159 | newView({ 160 | type: DataViewType.key, 161 | value: index, 162 | arrayKey: true, 163 | }) 164 | ); 165 | sum.push( 166 | ...(isArray(res) ? (res as DataView[]) : [res]) 167 | ); 168 | } 169 | return sum; 170 | }, []), 171 | }); 172 | } else { 173 | if (ellipsisObject) { 174 | detail = newView({ 175 | type: DataViewType.ellipsisObject, 176 | original: obj, 177 | }); 178 | } else { 179 | subOptions.ellipsisObject = true; 180 | detail = newView({ 181 | type: DataViewType.object, 182 | original: obj, 183 | [`${getChilren ? "children" : "value"}`]: Object.keys(obj) 184 | .slice( 185 | 0, 186 | getChilren 187 | ? maxObjectShowKeysCount 188 | : objectShowKeysCount 189 | ) 190 | .reduce((sum, key) => { 191 | const res = getDataView(obj[key], subOptions, map) 192 | .detail; 193 | if (getChilren) { 194 | sum.push( 195 | newView({ 196 | type: DataViewType.row, 197 | value: [ 198 | newView({ 199 | type: DataViewType.key, 200 | value: key, 201 | }), 202 | ...(isArray(res) 203 | ? (res as DataView[]) 204 | : [res]), 205 | ], 206 | }) 207 | ); 208 | } else { 209 | sum.push( 210 | newView({ 211 | type: DataViewType.key, 212 | value: key, 213 | objectKey: true, 214 | }) 215 | ); 216 | sum.push( 217 | ...(isArray(res) ? (res as DataView[]) : [res]) 218 | ); 219 | } 220 | return sum; 221 | }, []), 222 | }); 223 | } 224 | } 225 | return { 226 | detail: detail as DataView | DataView[], 227 | map, 228 | }; 229 | }; 230 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MpPlatfrom, 3 | MpViewType, 4 | MpAlipayViewComponent, 5 | MpTiktokView, 6 | MpViewLike, 7 | MpWechatView, 8 | MpAlipayViewPage, 9 | MpSmartViewPage, 10 | MpSmartViewComponent, 11 | MpViewElementSpec, 12 | MpViewComponentSpec, 13 | } from "./vars"; 14 | import { DataViewType, DataViewLike } from "./viewer"; 15 | export interface EachHandler { 16 | (value: T, prop: number | string): void; 17 | } 18 | export type IMap = { 19 | P: T; 20 | }; 21 | export const toString = Object.prototype.toString; 22 | export const isArray = 23 | "isArray" in Array 24 | ? Array.isArray 25 | : (obj: any): boolean => toString.call(obj) === "[object Array]"; 26 | export const each = (list: Array | object, hander: EachHandler) => { 27 | const type = typeof list; 28 | if (isArray(list)) { 29 | const arr: Array = list as Array; 30 | for (let i = 0, len = arr.length; i < len; i++) { 31 | hander(arr[i], i); 32 | } 33 | } else if (type === "object") { 34 | const obj: object = list as object; 35 | for (let prop in obj) { 36 | hander(list[prop], prop); 37 | } 38 | } 39 | }; 40 | 41 | export const rewrite = (target: object, hander: EachHandler) => { 42 | const result = {}; 43 | each(target, (value, prop) => { 44 | if (typeof value === "function") { 45 | result[prop] = hander(value, prop); 46 | } else { 47 | result[prop] = value; 48 | } 49 | }); 50 | return result; 51 | }; 52 | 53 | export const uuid = () => { 54 | return "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, function (c) { 55 | // tslint:disable-next-line:no-bitwise 56 | var r = (Math.random() * 16) | 0; 57 | // tslint:disable-next-line:no-bitwise 58 | var v = c === "x" ? r : (r & 0x3) | 0x8; 59 | return v.toString(16); 60 | }); 61 | }; 62 | 63 | export const getMpPlatformName = (): MpPlatfrom => { 64 | if (typeof wx === "object") { 65 | return MpPlatfrom.wechat; 66 | } else if (typeof my === "object") { 67 | return MpPlatfrom.alipay; 68 | } else if (typeof swan === "object") { 69 | return MpPlatfrom.smart; 70 | } else if (typeof tt === "object") { 71 | return MpPlatfrom.tiktok; 72 | } else { 73 | return MpPlatfrom.unknown; 74 | } 75 | }; 76 | export const getMpPlatformApiVar = (): any => { 77 | if (typeof wx === "object") { 78 | return wx; 79 | } else if (typeof my === "object") { 80 | return my; 81 | } else if (typeof swan === "object") { 82 | return swan; 83 | } else if (typeof tt === "object") { 84 | return tt; 85 | } else { 86 | return undefined; 87 | } 88 | }; 89 | export const MP_API_VAR = getMpPlatformApiVar(); 90 | export const MP_PLATFORM: MpPlatfrom = getMpPlatformName(); 91 | 92 | export const getMpNativeViewId = ( 93 | vm: MpViewLike, 94 | viewType: MpViewType 95 | ): string => { 96 | if (MP_PLATFORM === MpPlatfrom.unknown) { 97 | return "unknown"; 98 | } 99 | if (viewType === MpViewType.App) { 100 | return "app"; 101 | } 102 | if (viewType === MpViewType.Page) { 103 | if (MP_PLATFORM === MpPlatfrom.wechat) { 104 | return (vm as MpWechatView).__wxWebviewId__ + ""; 105 | } 106 | if (MP_PLATFORM === MpPlatfrom.alipay) { 107 | return (vm as MpAlipayViewPage).$viewId; 108 | } 109 | if (MP_PLATFORM === MpPlatfrom.tiktok) { 110 | return (vm as MpTiktokView).__webviewId__ + ""; 111 | } 112 | if (MP_PLATFORM === MpPlatfrom.smart) { 113 | return (vm as MpSmartViewPage).$mpcId; 114 | } 115 | } 116 | if (viewType === MpViewType.Component) { 117 | if (MP_PLATFORM === MpPlatfrom.wechat) { 118 | return (vm as MpWechatView).__wxExparserNodeId__; 119 | } 120 | if (MP_PLATFORM === MpPlatfrom.alipay) { 121 | return (vm as MpAlipayViewComponent).$id + ""; 122 | } 123 | if (MP_PLATFORM === MpPlatfrom.tiktok) { 124 | return (vm as MpTiktokView).__nodeId__ + ""; 125 | } 126 | if (MP_PLATFORM === MpPlatfrom.smart) { 127 | return (vm as MpSmartViewComponent).nodeId; 128 | } 129 | } 130 | }; 131 | export const getMpComponentPageNativeViewId = (vm: MpViewLike): string => { 132 | if (MP_PLATFORM === MpPlatfrom.wechat) { 133 | return (vm as MpWechatView).__wxWebviewId__ + ""; 134 | } 135 | if (MP_PLATFORM === MpPlatfrom.alipay) { 136 | return (vm as MpAlipayViewComponent).$page.$id + ""; 137 | } 138 | if (MP_PLATFORM === MpPlatfrom.tiktok) { 139 | return (vm as MpTiktokView).__webviewId__ + ""; 140 | } 141 | if (MP_PLATFORM === MpPlatfrom.smart) { 142 | return (vm as MpSmartViewComponent).pageinstance.$mpcId; 143 | } 144 | }; 145 | export const getMpViewPathName = ( 146 | viewType: MpViewType, 147 | vm?: MpViewLike 148 | ): string => { 149 | if (viewType === MpViewType.App) { 150 | return "app"; 151 | } 152 | if (!vm) { 153 | return ""; 154 | } 155 | if (MP_PLATFORM === MpPlatfrom.wechat) { 156 | return (vm as MpWechatView).is; 157 | } 158 | if (MP_PLATFORM === MpPlatfrom.alipay) { 159 | if (viewType === MpViewType.Page) { 160 | return (vm as MpAlipayViewPage).route; 161 | } 162 | return (vm as MpAlipayViewComponent).is; 163 | } 164 | if (MP_PLATFORM === MpPlatfrom.tiktok) { 165 | return (vm as MpTiktokView).is; 166 | } 167 | if (MP_PLATFORM === MpPlatfrom.smart) { 168 | if (viewType === MpViewType.Page) { 169 | return (vm as MpSmartViewPage).route; 170 | } 171 | return (vm as MpSmartViewComponent).is; 172 | } 173 | }; 174 | 175 | export const getMpViewChildren = (vm: MpViewLike) => { 176 | }; 177 | 178 | export const getMpViewElementSpec = ( 179 | vm: MpViewLike, 180 | viewType: MpViewType 181 | ): MpViewElementSpec => { 182 | const spec: MpViewElementSpec = { 183 | key: viewType === MpViewType.App ? "app" : vm.$mpcId, 184 | } as MpViewElementSpec; 185 | if (viewType === MpViewType.App) { 186 | spec.tag = "App"; 187 | } else if (viewType === MpViewType.Page) { 188 | spec.tag = "Page"; 189 | const tsVm = vm as MpWechatView & MpAlipayViewPage & MpTiktokView; 190 | spec.is = tsVm.is || tsVm.route; 191 | } else { 192 | if ( 193 | MP_PLATFORM === MpPlatfrom.wechat || 194 | MP_PLATFORM === MpPlatfrom.tiktok 195 | ) { 196 | spec.tag = "Component"; 197 | spec.is = (vm as MpWechatView & MpTiktokView).is; 198 | } else if (MP_PLATFORM === MpPlatfrom.alipay) { 199 | spec.tag = (vm as MpAlipayViewComponent).props.__tag; 200 | spec.is = (vm as MpAlipayViewComponent).is; 201 | } else if (MP_PLATFORM === MpPlatfrom.smart) { 202 | spec.tag = (vm as MpSmartViewComponent).componentName; 203 | spec.is = (vm as MpSmartViewComponent).is; 204 | } 205 | const tsViewSpec = vm.$viewSpec as MpViewComponentSpec; 206 | if (tsViewSpec.properties) { 207 | const attrs = [] as DataViewLike[]; 208 | each(tsViewSpec.properties, (propSpec, prop) => { 209 | const value = 210 | vm[ 211 | `${ 212 | MP_PLATFORM === MpPlatfrom.alipay ? "props" : "data" 213 | }` 214 | ][prop]; 215 | const dataType = typeof value; 216 | if (isArray(value)) { 217 | spec.attrs.push({ 218 | name: prop, 219 | type: DataViewType.array, 220 | length: (value as any).length, 221 | } as DataViewLike); 222 | } else if (dataType == "object") { 223 | spec.attrs.push({ 224 | name: prop, 225 | type: DataViewType.object, 226 | value: value === null ? "null" : "{...}", 227 | } as DataViewLike); 228 | } else if (dataType === "string") { 229 | spec.attrs.push({ 230 | name: prop, 231 | type: DataViewType.string, 232 | value, 233 | } as DataViewLike); 234 | } else if (dataType === "symbol") { 235 | spec.attrs.push({ 236 | name: prop, 237 | type: DataViewType.symbol, 238 | value: value.toString(), 239 | } as DataViewLike); 240 | } else if (dataType === "function") { 241 | spec.attrs.push({ 242 | name: prop, 243 | type: DataViewType.function, 244 | } as DataViewLike); 245 | } else if (dataType !== "undefined") { 246 | spec.attrs.push({ 247 | name: prop, 248 | type: DataViewType[prop], 249 | value, 250 | } as DataViewLike); 251 | } 252 | }); 253 | if (attrs.length) { 254 | spec.attrs = attrs; 255 | } 256 | } 257 | } 258 | return spec; 259 | }; 260 | 261 | export const isEmptyObject = (obj) => { 262 | for (let prop in obj) { 263 | return false; 264 | } 265 | return true; 266 | }; 267 | 268 | export function isPlainObject(value) { 269 | if (typeof value !== "object") { 270 | return false; 271 | } 272 | if (Object.getPrototypeOf(value) === null) { 273 | return true; 274 | } 275 | let proto = value; 276 | while (Object.getPrototypeOf(proto) !== null) { 277 | proto = Object.getPrototypeOf(proto); 278 | } 279 | return Object.getPrototypeOf(value) === proto; 280 | } 281 | -------------------------------------------------------------------------------- /src/storage.ts: -------------------------------------------------------------------------------- 1 | import { 2 | uuid, 3 | IMap, 4 | each, 5 | getMpComponentPageNativeViewId, 6 | getMpNativeViewId, 7 | getMpViewElementSpec, 8 | } from "./util"; 9 | import { getDataView, DataView, DataViewType } from "./viewer"; 10 | import { MpViewLike, MpViewElementSpec, MpViewType } from "./vars"; 11 | 12 | export const enum StorageType { 13 | NETWORK, 14 | API, 15 | VIEW, 16 | CONSOLE, 17 | EVENT, 18 | } 19 | 20 | type StorageMap = { 21 | [prop in StorageType]: StorageQueueItem[]; 22 | }; 23 | type StorageQueueItem = { 24 | id?: string; 25 | type?: StorageType; 26 | data: StorageQueueData; 27 | time: number; 28 | }; 29 | type StorageQueueData = { 30 | name?: string; 31 | label?: string; 32 | args?: any[]; 33 | view?: any; 34 | method?: string; 35 | category?: string; 36 | response?: any; 37 | result?: any; 38 | }; 39 | export enum NetWorkType { 40 | xhr, 41 | downloadFile, 42 | uploadFile, 43 | webSocket, 44 | } 45 | type NetWorkDataItem = { 46 | detail: StorageQueueItem; 47 | urlPath: string; 48 | urlOrigin: string; 49 | statusCode: number; 50 | statusText: string; 51 | type: NetWorkType; 52 | requestSize: number; 53 | requestSizeText: number; 54 | responseSize: number; 55 | responseSizeText: number; 56 | totalTime: string; 57 | request: object; 58 | response: object; 59 | }; 60 | 61 | export enum ConsoleMethod { 62 | log, 63 | dir, 64 | error, 65 | warn, 66 | info, 67 | } 68 | interface ConsoleDataItem { 69 | method: ConsoleMethod; 70 | views: DataView[]; 71 | } 72 | 73 | export class Storage { 74 | private queue: StorageQueueItem[] = []; 75 | private map: StorageMap = { 76 | [StorageType.NETWORK]: [], 77 | [StorageType.API]: [], 78 | [StorageType.VIEW]: [], 79 | [StorageType.CONSOLE]: [], 80 | [StorageType.EVENT]: [], 81 | } as StorageMap; 82 | private idMap: IMap = {} as IMap< 83 | string, 84 | StorageQueueItem[] 85 | >; 86 | private nativeViewIdMap: IMap = {} as IMap< 87 | string, 88 | MpViewLike 89 | >; 90 | private nativePageComponentsMap: IMap = {} as IMap< 91 | string, 92 | MpViewLike[] 93 | >; 94 | private viewIdMap: IMap = {} as IMap< 95 | string, 96 | MpViewLike 97 | >; 98 | private dataStatusChangeHandlers = {}; 99 | private arrShowItemCount: number; 100 | private objectShowKeysCount: number; 101 | private maxArrShowItemCount: number; 102 | private maxObjectShowKeysCount: number; 103 | private dataViewMap: IMap = {} as IMap; 104 | constructor( 105 | maxArrShowItemCount: number = 10, 106 | maxObjectShowKeysCount: number = 5 107 | ) { 108 | this.maxArrShowItemCount = maxArrShowItemCount; 109 | this.maxObjectShowKeysCount = maxObjectShowKeysCount; 110 | } 111 | push(type: StorageType, data: any, id: string = uuid()) { 112 | const time = Date.now(); 113 | this.queue.push({ 114 | id, 115 | type, 116 | data, 117 | time, 118 | }); 119 | this.map[type].push({ 120 | id, 121 | data, 122 | time, 123 | }); 124 | if (!this.idMap[id]) { 125 | this.idMap[id] = []; 126 | } 127 | this.idMap[id].push({ 128 | data, 129 | time, 130 | }); 131 | if ( 132 | type === StorageType.VIEW && 133 | data.view && 134 | !this.viewIdMap[data.view.$mpcId] 135 | ) { 136 | const mpView: MpViewLike = data.view as MpViewLike; 137 | if (mpView.$viewType === "Component") { 138 | const pageId = getMpComponentPageNativeViewId(data.view); 139 | if (pageId) { 140 | if (!this.nativePageComponentsMap[pageId]) { 141 | this.nativePageComponentsMap[pageId] = []; 142 | } 143 | this.nativePageComponentsMap[pageId].push(data.view); 144 | } 145 | } 146 | this.nativeViewIdMap[ 147 | getMpNativeViewId(mpView, mpView.$viewType) 148 | ] = this.viewIdMap[mpView.$mpcId] = mpView; 149 | } 150 | if (this.dataStatusChangeHandlers[id]) { 151 | this.dataStatusChangeHandlers[id].forEach((item) => { 152 | item[1](id, type, data, time); 153 | }); 154 | } 155 | if (this.dataStatusChangeHandlers["all"]) { 156 | this.dataStatusChangeHandlers["all"].forEach((item) => { 157 | item[1](id, type, data, time); 158 | }); 159 | } 160 | } 161 | onDataStatusChange(id: string, handler: Function, handlerName: string) { 162 | if (!this.dataStatusChangeHandlers[id]) { 163 | this.dataStatusChangeHandlers[id] = []; 164 | } 165 | if ( 166 | !this.dataStatusChangeHandlers[id].some( 167 | (item) => item[0] === handlerName 168 | ) 169 | ) { 170 | } else { 171 | this.dataStatusChangeHandlers[id].push([handlerName, handler]); 172 | } 173 | } 174 | offDataStatusChange(id: string, handlerName: string) { 175 | if (this.dataStatusChangeHandlers[id]) { 176 | const index = this.dataStatusChangeHandlers[id].findIndex( 177 | (item) => item[0] === handlerName 178 | ); 179 | index >= 0 && this.dataStatusChangeHandlers[id].splice(index, 1); 180 | } 181 | } 182 | // 分页获取数据 183 | getPageList(pageIndex: number, type?: StorageType, pageSize: number = 30) { 184 | const allList = type ? this.map[type] : this.queue; 185 | const pageCount = Math.ceil(allList.length / pageSize); 186 | if (pageIndex >= pageCount) { 187 | return []; 188 | } 189 | return this.convertList( 190 | allList.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize), 191 | type 192 | ); 193 | } 194 | getMpViewDetail(mpcId: string): MpViewLike { 195 | return this.viewIdMap[mpcId]; 196 | } 197 | getMpViewChildrenSpec(mpcId: string): MpViewElementSpec[] { 198 | const children = [] as MpViewElementSpec[]; 199 | 200 | if (mpcId === "app") { 201 | const activePages = getCurrentPages() as MpViewLike[]; 202 | const unactivePage: MpViewLike[] = []; 203 | each(this.viewIdMap, (view, id) => { 204 | if ( 205 | view.$viewType === "Page" && 206 | activePages.every((item) => item.$mpcId !== view.$mpcId) 207 | ) { 208 | unactivePage.push(view); 209 | } 210 | }); 211 | [ 212 | [true, activePages], 213 | [false, unactivePage], 214 | ].forEach(([isActive, pages]) => { 215 | const tsPages = pages as MpViewLike[]; 216 | tsPages.forEach((page) => { 217 | const pageSpec = getMpViewElementSpec( 218 | page, 219 | MpViewType.Page 220 | ); 221 | pageSpec.active = isActive as boolean; 222 | children.push(pageSpec); 223 | }); 224 | }); 225 | } else if (this.viewIdMap[mpcId]) { 226 | const view = this.viewIdMap[mpcId]; 227 | if (view.$viewType === MpViewType.Page) { 228 | } 229 | } 230 | return children; 231 | } 232 | getMpViewElementSpec(mpcId: string): MpViewElementSpec { 233 | const view: MpViewLike = this.getMpViewDetail(mpcId); 234 | return getMpViewElementSpec(view, view.$viewType); 235 | } 236 | getItems(type: StorageType) { 237 | if (type === StorageType.VIEW) { 238 | const app = getApp() as MpViewLike; 239 | const activePages = getCurrentPages() as MpViewLike[]; 240 | const unactivePage: MpViewLike[] = []; 241 | each(this.viewIdMap, (view, id) => { 242 | if ( 243 | view.$viewType === "Page" && 244 | activePages.every((item) => item.$mpcId !== view.$mpcId) 245 | ) { 246 | unactivePage.push(view); 247 | } 248 | }); 249 | const appViewSpec: MpViewElementSpec = getMpViewElementSpec( 250 | app, 251 | MpViewType.App 252 | ); 253 | return appViewSpec; 254 | } 255 | } 256 | convertList( 257 | list: StorageQueueItem[], 258 | type?: StorageType 259 | ): ConsoleDataItem[] | NetWorkDataItem[] { 260 | if (type === StorageType.NETWORK) { 261 | const result: NetWorkDataItem[] = []; 262 | list.forEach((item) => {}); 263 | } else if (type === StorageType.CONSOLE) { 264 | const result: ConsoleDataItem[] = []; 265 | list.forEach((item) => { 266 | result.push({ 267 | method: ConsoleMethod[item.data && item.data.name], 268 | views: 269 | item.data && 270 | item.data.args && 271 | item.data.args.reduce((sum, arg) => { 272 | const dtResult = getDataView(arg, { 273 | convertBr: typeof arg === "string", 274 | maxArrShowItemCount: this.maxArrShowItemCount, 275 | arrShowItemCount: this.arrShowItemCount, 276 | maxObjectShowKeysCount: this 277 | .maxObjectShowKeysCount, 278 | objectShowKeysCount: this.objectShowKeysCount, 279 | }); 280 | return sum; 281 | }, []), 282 | }); 283 | }); 284 | return result; 285 | } 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /packages/core/miniprogram/rewrite.ts: -------------------------------------------------------------------------------- 1 | import { 2 | FecStorageType, 3 | FecStorageLike, 4 | FecStorageApiData, 5 | MpHasTaskApi, 6 | FecMethodStatus, 7 | FecStorageMethodData, 8 | FecStorageEventData, 9 | FecStorageConsoleData, 10 | FecStorageViewData, 11 | } from "@fe-console/types"; 12 | import { MkApi, MkApp, MkPage, MkComponent, MixinStore } from "@mpkit/mixin"; 13 | import { MpViewType, MpPlatform } from "@mpkit/types"; 14 | import { getMpPlatform, uuid, getMpInitLifeName } from "@mpkit/util"; 15 | const socketLifes = ["onOpen", "onMessage", "onError", "onClose"]; 16 | 17 | const PALTFORM = getMpPlatform(); 18 | 19 | const hookWebSocketAction = ( 20 | name: string, 21 | args, 22 | apiStorageData?: FecStorageApiData, 23 | storage?: FecStorageLike, 24 | socketTask?: any, 25 | orgAction?: Function 26 | ) => { 27 | let apiStorageDataList: FecStorageApiData[] = []; 28 | if (!apiStorageData && storage) { 29 | const taskMap = storage.getApiTaskMap(MpHasTaskApi.connectSocket); 30 | apiStorageDataList = Object.keys(taskMap).map((item) => taskMap[item]); 31 | } else if (apiStorageData) { 32 | apiStorageDataList.push(apiStorageData); 33 | } 34 | const storageData: FecStorageApiData = { 35 | name, 36 | type: FecStorageType.Api, 37 | status: FecMethodStatus.Executed, 38 | id: uuid(), 39 | time: Date.now(), 40 | args, 41 | } as FecStorageApiData; 42 | if (!args.length || !args[0]) { 43 | args[0] = {}; 44 | } 45 | if (typeof args[0] === "object" && args[0]) { 46 | const { success, fail } = args[0]; 47 | args[0].success = (...s) => { 48 | storageData.endTime = Date.now(); 49 | storageData.status = FecMethodStatus.Success; 50 | if (s.length < 1) { 51 | storageData.response = s[0]; 52 | } else { 53 | storageData.response = s; 54 | } 55 | if (storage) { 56 | if (name === "close" && apiStorageData) { 57 | storage.removeApiTask( 58 | MpHasTaskApi.connectSocket, 59 | apiStorageData.id 60 | ); 61 | } else if ( 62 | name === "closeSocket" && 63 | apiStorageDataList.length 64 | ) { 65 | apiStorageDataList.forEach((item) => { 66 | storage.removeApiTask( 67 | MpHasTaskApi.connectSocket, 68 | item.id 69 | ); 70 | }); 71 | } 72 | } 73 | return success && success.apply(null, s); 74 | }; 75 | args[0].fail = (...s) => { 76 | storageData.endTime = Date.now(); 77 | storageData.status = FecMethodStatus.Fail; 78 | if (s.length < 1) { 79 | storageData.response = s[0]; 80 | } else { 81 | storageData.response = s; 82 | } 83 | return fail && fail.apply(null, s); 84 | }; 85 | } 86 | if (apiStorageDataList.length) { 87 | apiStorageDataList.forEach((item) => { 88 | if (!item.children) { 89 | item.children = []; 90 | } 91 | item.children.push(storageData); 92 | }); 93 | } 94 | 95 | if (orgAction) { 96 | return orgAction.apply(socketTask || null, args); 97 | } 98 | return storageData; 99 | }; 100 | 101 | const wrapWebSocketTask = ( 102 | socketTask: any, 103 | storage: FecStorageLike, 104 | apiStoreData: FecStorageApiData 105 | ) => { 106 | const { send, close } = socketTask; 107 | socketTask.send = function (...args) { 108 | return hookWebSocketAction( 109 | "send", 110 | args, 111 | apiStoreData, 112 | storage, 113 | socketTask, 114 | send 115 | ); 116 | }; 117 | socketTask.close = function (...args) { 118 | return hookWebSocketAction( 119 | "close", 120 | args, 121 | apiStoreData, 122 | storage, 123 | socketTask, 124 | close 125 | ); 126 | }; 127 | socketLifes.forEach((step) => { 128 | socketTask[step]((res) => { 129 | apiStoreData.children.push({ 130 | id: uuid(), 131 | time: Date.now(), 132 | type: FecStorageType.Api, 133 | name: step, 134 | args: [], 135 | response: res, 136 | status: FecMethodStatus.Executed, 137 | endTime: Date.now(), 138 | }); 139 | }); 140 | }); 141 | }; 142 | 143 | export const rewriteMpApi = (storage: FecStorageLike): any => { 144 | MixinStore.addHook("Api", { 145 | before(name, args, handler, id) { 146 | if (name === "sendSocketMessage" || name === "closeSocket") { 147 | storage.push(hookWebSocketAction(name, args, null, storage)); 148 | return; 149 | } 150 | storage.push({ 151 | id, 152 | type: FecStorageType.Api, 153 | args, 154 | name, 155 | status: FecMethodStatus.Executed, 156 | } as FecStorageApiData); 157 | }, 158 | after(name, args, result, id) { 159 | if (name === "sendSocketMessage" || name === "closeSocket") { 160 | return; 161 | } 162 | const data = storage.get(id) as FecStorageApiData; 163 | if (data) { 164 | data.result = result; 165 | if (MpHasTaskApi[name]) { 166 | data.children = []; 167 | storage.pushApiTask(data); 168 | } 169 | data.endTime = Date.now(); 170 | if (name === MpHasTaskApi.connectSocket) { 171 | wrapWebSocketTask(result, storage, data); 172 | } 173 | } 174 | }, 175 | complete(name, args, res, success, id) { 176 | if (name === "sendSocketMessage" || name === "closeSocket") { 177 | return; 178 | } 179 | const data = storage.get(id) as FecStorageApiData; 180 | if (data) { 181 | data.response = res; 182 | data.status = success 183 | ? FecMethodStatus.Success 184 | : FecMethodStatus.Fail; 185 | data.endTime = Date.now(); 186 | } 187 | }, 188 | catch(name, args, error, errTyoe, id) { 189 | const data = storage.get(id) as FecStorageApiData; 190 | if (data) { 191 | data.status = FecMethodStatus.Fail; 192 | data.endTime = Date.now(); 193 | data.error = error; 194 | data.errorType = errTyoe; 195 | } 196 | }, 197 | }); 198 | if (PALTFORM === MpPlatform.wechat) { 199 | wx = MkApi; 200 | return wx; 201 | } else if (PALTFORM === MpPlatform.alipay) { 202 | my = MkApi; 203 | return my; 204 | } else if (PALTFORM === MpPlatform.smart) { 205 | swan = MkApi; 206 | return swan; 207 | } else if (PALTFORM === MpPlatform.tiktok) { 208 | tt = MkApi; 209 | return tt; 210 | } 211 | }; 212 | 213 | export const rewriteMpView = (storage: FecStorageLike) => { 214 | const isEvent = (obj) => 215 | typeof obj === "object" && 216 | obj && 217 | "type" in obj && 218 | obj.type && 219 | "currentTarget" in obj && 220 | obj.currentTarget; 221 | const viewHook = { 222 | before(name, args, handler, id) { 223 | storage.push({ 224 | id, 225 | type: FecStorageType.Method, 226 | name, 227 | args, 228 | view: this, 229 | status: FecMethodStatus.Executed, 230 | } as FecStorageMethodData); 231 | if (isEvent(args[0])) { 232 | const wrapDetail = args[0].detail; 233 | if ( 234 | typeof wrapDetail === "object" && 235 | wrapDetail && 236 | wrapDetail._mpcWrap 237 | ) { 238 | const { id, orgDetail } = wrapDetail; 239 | const data = storage.get(id) as FecStorageEventData; 240 | if (data) { 241 | data.event = args[0]; 242 | data.handleView = this; 243 | } 244 | args[0].detail = orgDetail; 245 | } 246 | } 247 | }, 248 | after(name, args, result, id) { 249 | const data = storage.get(id) as FecStorageMethodData; 250 | if (data) { 251 | data.result = result; 252 | data.endTime = Date.now(); 253 | } 254 | }, 255 | catch(name, args, error, errTyoe, id) { 256 | const data = storage.get(id) as FecStorageMethodData; 257 | if (data) { 258 | data.status = FecMethodStatus.Fail; 259 | data.endTime = Date.now(); 260 | data.error = error; 261 | data.errorType = errTyoe; 262 | } 263 | }, 264 | }; 265 | MixinStore.addHook(MpViewType.App, viewHook); 266 | MixinStore.addHook(MpViewType.Page, viewHook); 267 | MixinStore.addHook(MpViewType.Component, viewHook); 268 | function rewriteTrigger() { 269 | if ("triggerEvent" in this) { 270 | this.$nativeTriggerEvent = this.triggerEvent; 271 | this.triggerEvent = function (...args) { 272 | const orgDetail = args[1]; 273 | const orgArgs = [args[0], args[1], args[2]]; 274 | const id = uuid(); 275 | const name = args[0]; 276 | args[1] = { 277 | id, 278 | _mpcWrap: true, 279 | orgDetail, 280 | }; 281 | const data = {} as FecStorageEventData; 282 | data.id = id; 283 | data.type = FecStorageType.Event; 284 | data.name = name; 285 | data.args = orgArgs; 286 | data.triggerView = this; 287 | storage.push(data); 288 | return this.$nativeTriggerEvent.apply(this.args); 289 | }; 290 | } 291 | } 292 | MixinStore.addHook(MpViewType.App, { 293 | [getMpInitLifeName(MpViewType.App)]: { 294 | before() { 295 | storage.push({ 296 | type: FecStorageType.View, 297 | view: this, 298 | } as FecStorageViewData); 299 | }, 300 | }, 301 | }); 302 | MixinStore.addHook(MpViewType.Page, { 303 | [getMpInitLifeName(MpViewType.Page)]: { 304 | before() { 305 | storage.push({ 306 | type: FecStorageType.View, 307 | view: this, 308 | } as FecStorageViewData); 309 | rewriteTrigger.call(this); 310 | }, 311 | }, 312 | }); 313 | MixinStore.addHook(MpViewType.Component, { 314 | [getMpInitLifeName(MpViewType.Component)]: { 315 | before() { 316 | storage.push({ 317 | type: FecStorageType.View, 318 | view: this, 319 | } as FecStorageViewData); 320 | rewriteTrigger.call(this); 321 | }, 322 | }, 323 | }); 324 | const wrapView = (native, mkView) => { 325 | return (spec) => { 326 | return native(mkView(spec)); 327 | }; 328 | }; 329 | App = wrapView(App, MkApp); 330 | Page = wrapView(App, MkPage); 331 | Component = wrapView(App, MkComponent); 332 | }; 333 | 334 | export const rewriteMpConsole = (storage: FecStorageLike) => { 335 | if (typeof console === "object" && console) { 336 | Object.keys(console).forEach((key) => { 337 | const method = console[key]; 338 | if (typeof method === "function") { 339 | console[key] = function (...args) { 340 | storage.push({ 341 | type: FecStorageType.Console, 342 | args, 343 | } as FecStorageConsoleData); 344 | }; 345 | } 346 | }); 347 | } 348 | }; 349 | -------------------------------------------------------------------------------- /src/rewrite.ts: -------------------------------------------------------------------------------- 1 | import { 2 | uuid, 3 | rewrite, 4 | getMpViewPathName, 5 | each, 6 | isPlainObject, 7 | MP_PLATFORM, 8 | } from "./util"; 9 | import { 10 | MpPlatfrom, 11 | MpViewType, 12 | MpViewLike, 13 | MpComponentPropSpec, 14 | MpViewSpec, 15 | } from "./vars"; 16 | import { Storage, StorageType } from "./storage"; 17 | const networkApis = ["request", "downloadFile", "uploadFile"]; 18 | const socketLifes = ["onOpen", "onClose", "onError"]; 19 | export const rewriteMP = (nativeMp: object, storage: Storage) => { 20 | return rewrite(nativeMp, (value, prop) => { 21 | const methodHandler = value as Function; 22 | const methodName = prop as string; 23 | return function (...args) { 24 | const funId = uuid(); 25 | const res = methodHandler.apply(this, args); 26 | const asyncResult = { 27 | type: "wait", 28 | time: null, 29 | data: null, 30 | }; 31 | if (methodName.indexOf("Sync") === -1 && !args.length) { 32 | args[0] = {}; 33 | } 34 | if (typeof args[0] === "object" && args[0]) { 35 | const { success, fail } = args[0]; 36 | args[0].success = (...params) => { 37 | asyncResult.type = "success"; 38 | if (params.length < 1) { 39 | asyncResult.data = params[0]; 40 | } 41 | asyncResult.time = Date.now(); 42 | return success && success.apply(null, params); 43 | }; 44 | args[0].fail = (...params) => { 45 | asyncResult.type = "fail"; 46 | if (params.length < 1) { 47 | asyncResult.data = params[0]; 48 | } 49 | asyncResult.time = Date.now(); 50 | return fail && fail.apply(null, params); 51 | }; 52 | } 53 | if (methodName === "connectSocket") { 54 | const orgSend = res.send; 55 | res.send = function (...params) { 56 | const sendResult = { 57 | type: "wait", 58 | time: null, 59 | data: null, 60 | }; 61 | if (!params.length) { 62 | params[0] = {}; 63 | } 64 | if (typeof params[0] === "object" && params[0]) { 65 | const { success, fail } = params[0]; 66 | params[0].success = (...s) => { 67 | sendResult.type = "success"; 68 | if (s.length < 1) { 69 | sendResult.data = s[0]; 70 | } else { 71 | sendResult.data = s; 72 | } 73 | sendResult.time = Date.now(); 74 | return success && success.apply(null, s); 75 | }; 76 | params[0].fail = (...s) => { 77 | sendResult.type = "fail"; 78 | if (s.length < 1) { 79 | sendResult.data = s[0]; 80 | } else { 81 | sendResult.data = s; 82 | } 83 | sendResult.time = Date.now(); 84 | return fail && fail.apply(null, s); 85 | }; 86 | } 87 | storage.push( 88 | StorageType.NETWORK, 89 | { 90 | name: methodName, 91 | args: params, 92 | category: "send", 93 | response: sendResult, 94 | }, 95 | funId 96 | ); 97 | return orgSend.apply(this, params); 98 | }; 99 | each(socketLifes, (life) => { 100 | res[life]((res) => { 101 | storage.push( 102 | StorageType.NETWORK, 103 | { 104 | name: methodName, 105 | category: life, 106 | response: res, 107 | }, 108 | funId 109 | ); 110 | }); 111 | }); 112 | res.onMessage((res) => { 113 | storage.push( 114 | StorageType.NETWORK, 115 | { 116 | name: methodName, 117 | category: "onMessage", 118 | response: res, 119 | }, 120 | funId 121 | ); 122 | }); 123 | } 124 | const storageData = { 125 | name: methodName, 126 | args, 127 | result: res, 128 | response: asyncResult, 129 | }; 130 | storage.push(StorageType.API, storageData, funId); 131 | if (networkApis.indexOf(methodName) !== -1) { 132 | storage.push(StorageType.NETWORK, storageData, funId); 133 | } 134 | return res; 135 | }; 136 | }); 137 | }; 138 | const consoleMethods = ["log", "dir", "error", "warn", "info"]; 139 | export const rewriteConsole = ( 140 | nativeTarget: Console, 141 | storage: Storage 142 | ): Console => { 143 | return rewrite(nativeTarget, (value, prop) => { 144 | if (consoleMethods.indexOf(prop as string) !== -1) { 145 | return function (...args) { 146 | storage.push(StorageType.CONSOLE, { 147 | name: prop, 148 | args, 149 | }); 150 | return value.apply(this, args); 151 | }; 152 | } 153 | return value; 154 | }) as Console; 155 | }; 156 | const viewLife = { 157 | App: ["onLaunch", "onShow", "onHide", "onError"], 158 | Page: ["onLoad", "onReady", "onShow", "onHide", "onUnload"], 159 | Component: ["created", "attached", "ready", "moved", "detached"], 160 | }; 161 | if (MP_PLATFORM === MpPlatfrom.alipay) { 162 | viewLife.Component = [ 163 | "onInit", 164 | "deriveDataFromProps", 165 | "didMount", 166 | "didUpdate", 167 | "didUnmount", 168 | ]; 169 | } 170 | const initViewMPC = ( 171 | vm: MpViewLike, 172 | storage: Storage, 173 | viewType: MpViewType, 174 | facData, 175 | viewSpec: MpViewSpec 176 | ) => { 177 | if (!vm.$viewType) { 178 | vm.$viewType = viewType; 179 | } 180 | if (!vm.$viewSpec) { 181 | vm.$viewSpec = viewSpec; 182 | } 183 | if (!vm.$mpcId) { 184 | vm.$mpcId = uuid(); 185 | } 186 | if (!vm.$mpcStorage) { 187 | vm.$mpcStorage = storage; 188 | } 189 | const label = getMpViewPathName(viewType, vm); 190 | if (!facData.label) { 191 | facData.label = label; 192 | } 193 | if (!vm.$mpcInitState) { 194 | vm.$mpcInitState = true; 195 | const initState = {}; 196 | each(vm, (value, prop) => { 197 | if (prop === "data") { 198 | initState[prop] = JSON.parse(JSON.stringify(value)); 199 | } else { 200 | const valType = typeof value; 201 | if (valType !== "function") { 202 | if (isPlainObject(value)) { 203 | initState[prop] = JSON.parse(JSON.stringify(value)); 204 | } else { 205 | initState[prop] = value; 206 | } 207 | } 208 | } 209 | }); 210 | vm.$mpcStorage.push( 211 | StorageType.VIEW, 212 | { 213 | label, 214 | method: "#initState", 215 | view: vm, 216 | response: initState, 217 | }, 218 | vm.$mpcId 219 | ); 220 | } 221 | }; 222 | const rewriteNativeMethod = (vm: MpViewLike) => { 223 | if (!vm.$isRewriteSetData) { 224 | vm.$isRewriteSetData = true; 225 | vm.$nativeSetData = vm.setData; 226 | vm.setData = function (data: any, callback: Function) {}; 227 | } 228 | }; 229 | const rewritePropObserver = ( 230 | propSpec: Function | Object, 231 | propName: string, 232 | storage: Storage, 233 | viewType: MpViewType, 234 | facData, 235 | viewSpec: MpViewSpec 236 | ): MpComponentPropSpec => { 237 | const specType = typeof propSpec; 238 | if (specType === "function") { 239 | return { 240 | type: propSpec, 241 | observer(...args) { 242 | initViewMPC(this, storage, viewType, facData, viewSpec); 243 | rewriteNativeMethod(this); 244 | }, 245 | } as MpComponentPropSpec; 246 | } else if (specType === "object") { 247 | const tsPropSpec = propSpec as MpComponentPropSpec; 248 | const orgObserver = tsPropSpec.observer; 249 | tsPropSpec.observer = function (...args) { 250 | initViewMPC(this, storage, viewType, facData, viewSpec); 251 | rewriteNativeMethod(this); 252 | return orgObserver.apply(this, args); 253 | }; 254 | return tsPropSpec; 255 | } 256 | }; 257 | const exexFunc = function ( 258 | this: MpViewLike, 259 | viewType: MpViewType, 260 | methodValue: Function, 261 | methodName: string, 262 | ...args 263 | ) { 264 | const res = (methodValue as Function).apply(this, args); 265 | const label = getMpViewPathName(viewType, this); 266 | const methodResult = { 267 | type: "wait", 268 | data: null, 269 | time: null, 270 | }; 271 | if (typeof res === "object" && res.then) { 272 | res.then((data) => { 273 | methodResult.type = "success"; 274 | methodResult.time = Date.now(); 275 | methodResult.data = data; 276 | }); 277 | res.catch((data) => { 278 | methodResult.type = "fail"; 279 | methodResult.time = Date.now(); 280 | methodResult.data = data; 281 | }); 282 | } else { 283 | methodResult.type = "done"; 284 | methodResult.time = Date.now(); 285 | methodResult.data = res; 286 | } 287 | this.$mpcStorage.push( 288 | StorageType.VIEW, 289 | { 290 | label, 291 | args, 292 | method: methodName, 293 | view: this, 294 | response: methodResult, 295 | }, 296 | this.$mpcId 297 | ); 298 | if ( 299 | args[0] && 300 | typeof args[0] === "object" && 301 | typeof args[0].currentTarget === "object" && 302 | args[0].type 303 | ) { 304 | this.$mpcStorage.push( 305 | StorageType.EVENT, 306 | { 307 | label, 308 | args, 309 | method: methodName, 310 | view: this, 311 | response: methodResult, 312 | event: args[0], 313 | }, 314 | this.$mpcId 315 | ); 316 | } 317 | return res; 318 | }; 319 | const mergeMethod = (viewType: MpViewType, target, plus?) => { 320 | each(target, (methodValue, methodName) => { 321 | if (typeof methodValue === "function") { 322 | target[methodName] = function (this: MpViewLike, ...args) { 323 | if (viewType !== "App") { 324 | rewriteNativeMethod(this); 325 | } 326 | plus && plus[methodName] && plus[methodName].apply(this, args); 327 | return exexFunc.apply(this, [ 328 | viewType, 329 | methodValue, 330 | methodName, 331 | ...args, 332 | ]); 333 | }; 334 | } 335 | }); 336 | }; 337 | export const rewriteView = ( 338 | nativeView: Function, 339 | viewType: MpViewType, 340 | storage: Storage 341 | ): Function => { 342 | function ViewFactory(spec: any) { 343 | const facData = { 344 | name: viewType, 345 | label: getMpViewPathName(viewType), 346 | args: [spec], 347 | }; 348 | storage.push(StorageType.VIEW, facData); 349 | let plus = {}; 350 | each(viewLife[viewType], (lifeName) => { 351 | plus[lifeName as string] = function (...args) { 352 | initViewMPC( 353 | this, 354 | storage, 355 | viewType, 356 | facData, 357 | spec as MpViewSpec 358 | ); 359 | }; 360 | }); 361 | mergeMethod(spec, plus); 362 | if (viewType === "Component") { 363 | if (spec.methods) { 364 | mergeMethod(viewType, spec.methods); 365 | } 366 | if (MP_PLATFORM === MpPlatfrom.wechat && spec.lifetimes) { 367 | mergeMethod(viewType, spec.lifetimes, plus); 368 | } 369 | if (MP_PLATFORM === MpPlatfrom.wechat && spec.pageLifetimes) { 370 | mergeMethod(viewType, spec.pageLifetimes); 371 | } 372 | each(plus, (methodValue, methodName) => { 373 | if ( 374 | !spec[methodName] && 375 | ((spec.lifetimes && !spec.lifetimes[methodName]) || 376 | !spec.lifetimes) 377 | ) { 378 | spec[methodName] = function (...args) { 379 | rewriteNativeMethod(this); 380 | return exexFunc.apply(this, [ 381 | viewType, 382 | methodValue, 383 | methodName, 384 | ...args, 385 | ]); 386 | }; 387 | } 388 | }); 389 | if (spec.properties) { 390 | each(spec.properties, (propSpec, propName) => { 391 | spec.properties[propName] = rewritePropObserver( 392 | propSpec, 393 | propName as string, 394 | storage, 395 | viewType, 396 | facData, 397 | spec as MpViewSpec 398 | ); 399 | }); 400 | } 401 | } 402 | return nativeView(spec); 403 | } 404 | ViewFactory.displayName = viewType; 405 | return ViewFactory; 406 | }; 407 | -------------------------------------------------------------------------------- /packages/core/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@fe-console/core", 3 | "version": "0.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@mpkit/ebus": { 8 | "version": "1.0.6", 9 | "resolved": "https://registry.npmjs.org/@mpkit/ebus/-/ebus-1.0.6.tgz", 10 | "integrity": "sha512-8CN3Vf+nRSyZ0RQAHwGvS5bEqjbWrIgJfnKOD12d9FAVuQhfwE3b/joqBvylmOTTGN8Isk54eoLI2mtl5AacmQ==", 11 | "requires": { 12 | "@mpkit/types": "^1.0.6", 13 | "@mpkit/util": "^1.0.6" 14 | } 15 | }, 16 | "@mpkit/mixin": { 17 | "version": "1.0.6", 18 | "resolved": "https://registry.npmjs.org/@mpkit/mixin/-/mixin-1.0.6.tgz", 19 | "integrity": "sha512-5cCpKCaj1pBq2Ot4QH0NJcUy8EjTar3VOZuWsJn1xt9QNhHerwrxwVeoMwIWLz0wjBEaYTv3CFH8MD4qccW2zg==", 20 | "requires": { 21 | "@mpkit/types": "^1.0.6", 22 | "@mpkit/util": "^1.0.6" 23 | } 24 | }, 25 | "@mpkit/types": { 26 | "version": "1.0.6", 27 | "resolved": "https://registry.npmjs.org/@mpkit/types/-/types-1.0.6.tgz", 28 | "integrity": "sha512-HzhH1394vY8DyYZ4cjVzar8kYyBex6wB0ZeobHALQXt9xS9sQPGT942QB8ueN0AGgQU2F0c5+TlxZs+5iGgDiw==" 29 | }, 30 | "@mpkit/util": { 31 | "version": "1.0.6", 32 | "resolved": "https://registry.npmjs.org/@mpkit/util/-/util-1.0.6.tgz", 33 | "integrity": "sha512-C2eleLBcPelr146yNrnGiyBPWDjOt4GGUq2EBl+Qft9kuOadzH2YNA1MPkBW9lkkDnjDAsto6+qIrTeX/XDOWw==", 34 | "requires": { 35 | "@mpkit/types": "^1.0.6" 36 | } 37 | }, 38 | "ansi-colors": { 39 | "version": "4.1.1", 40 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 41 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 42 | "dev": true 43 | }, 44 | "ansi-regex": { 45 | "version": "3.0.0", 46 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 47 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 48 | "dev": true 49 | }, 50 | "ansi-styles": { 51 | "version": "3.2.1", 52 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 53 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 54 | "dev": true, 55 | "requires": { 56 | "color-convert": "^1.9.0" 57 | } 58 | }, 59 | "anymatch": { 60 | "version": "3.1.1", 61 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 62 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 63 | "dev": true, 64 | "requires": { 65 | "normalize-path": "^3.0.0", 66 | "picomatch": "^2.0.4" 67 | } 68 | }, 69 | "argparse": { 70 | "version": "1.0.10", 71 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 72 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 73 | "dev": true, 74 | "requires": { 75 | "sprintf-js": "~1.0.2" 76 | } 77 | }, 78 | "array.prototype.map": { 79 | "version": "1.0.2", 80 | "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", 81 | "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", 82 | "dev": true, 83 | "requires": { 84 | "define-properties": "^1.1.3", 85 | "es-abstract": "^1.17.0-next.1", 86 | "es-array-method-boxes-properly": "^1.0.0", 87 | "is-string": "^1.0.4" 88 | } 89 | }, 90 | "assertion-error": { 91 | "version": "1.1.0", 92 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 93 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 94 | "dev": true 95 | }, 96 | "balanced-match": { 97 | "version": "1.0.0", 98 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 99 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 100 | "dev": true 101 | }, 102 | "binary-extensions": { 103 | "version": "2.1.0", 104 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", 105 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", 106 | "dev": true 107 | }, 108 | "brace-expansion": { 109 | "version": "1.1.11", 110 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 111 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 112 | "dev": true, 113 | "requires": { 114 | "balanced-match": "^1.0.0", 115 | "concat-map": "0.0.1" 116 | } 117 | }, 118 | "braces": { 119 | "version": "3.0.2", 120 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 121 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 122 | "dev": true, 123 | "requires": { 124 | "fill-range": "^7.0.1" 125 | } 126 | }, 127 | "browser-stdout": { 128 | "version": "1.3.1", 129 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 130 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 131 | "dev": true 132 | }, 133 | "camelcase": { 134 | "version": "5.3.1", 135 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 136 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 137 | "dev": true 138 | }, 139 | "chai": { 140 | "version": "4.2.0", 141 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", 142 | "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", 143 | "dev": true, 144 | "requires": { 145 | "assertion-error": "^1.1.0", 146 | "check-error": "^1.0.2", 147 | "deep-eql": "^3.0.1", 148 | "get-func-name": "^2.0.0", 149 | "pathval": "^1.1.0", 150 | "type-detect": "^4.0.5" 151 | } 152 | }, 153 | "chalk": { 154 | "version": "2.4.2", 155 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 156 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 157 | "dev": true, 158 | "requires": { 159 | "ansi-styles": "^3.2.1", 160 | "escape-string-regexp": "^1.0.5", 161 | "supports-color": "^5.3.0" 162 | }, 163 | "dependencies": { 164 | "supports-color": { 165 | "version": "5.5.0", 166 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 167 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 168 | "dev": true, 169 | "requires": { 170 | "has-flag": "^3.0.0" 171 | } 172 | } 173 | } 174 | }, 175 | "check-error": { 176 | "version": "1.0.2", 177 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 178 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 179 | "dev": true 180 | }, 181 | "chokidar": { 182 | "version": "3.3.1", 183 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", 184 | "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", 185 | "dev": true, 186 | "requires": { 187 | "anymatch": "~3.1.1", 188 | "braces": "~3.0.2", 189 | "fsevents": "~2.1.2", 190 | "glob-parent": "~5.1.0", 191 | "is-binary-path": "~2.1.0", 192 | "is-glob": "~4.0.1", 193 | "normalize-path": "~3.0.0", 194 | "readdirp": "~3.3.0" 195 | } 196 | }, 197 | "cliui": { 198 | "version": "5.0.0", 199 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 200 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 201 | "dev": true, 202 | "requires": { 203 | "string-width": "^3.1.0", 204 | "strip-ansi": "^5.2.0", 205 | "wrap-ansi": "^5.1.0" 206 | }, 207 | "dependencies": { 208 | "ansi-regex": { 209 | "version": "4.1.0", 210 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 211 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 212 | "dev": true 213 | }, 214 | "string-width": { 215 | "version": "3.1.0", 216 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 217 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 218 | "dev": true, 219 | "requires": { 220 | "emoji-regex": "^7.0.1", 221 | "is-fullwidth-code-point": "^2.0.0", 222 | "strip-ansi": "^5.1.0" 223 | } 224 | }, 225 | "strip-ansi": { 226 | "version": "5.2.0", 227 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 228 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 229 | "dev": true, 230 | "requires": { 231 | "ansi-regex": "^4.1.0" 232 | } 233 | } 234 | } 235 | }, 236 | "color-convert": { 237 | "version": "1.9.3", 238 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 239 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 240 | "dev": true, 241 | "requires": { 242 | "color-name": "1.1.3" 243 | } 244 | }, 245 | "color-name": { 246 | "version": "1.1.3", 247 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 248 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 249 | "dev": true 250 | }, 251 | "concat-map": { 252 | "version": "0.0.1", 253 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 254 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 255 | "dev": true 256 | }, 257 | "debug": { 258 | "version": "3.2.6", 259 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 260 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 261 | "dev": true, 262 | "requires": { 263 | "ms": "^2.1.1" 264 | } 265 | }, 266 | "decamelize": { 267 | "version": "1.2.0", 268 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 269 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 270 | "dev": true 271 | }, 272 | "deep-eql": { 273 | "version": "3.0.1", 274 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 275 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 276 | "dev": true, 277 | "requires": { 278 | "type-detect": "^4.0.0" 279 | } 280 | }, 281 | "define-properties": { 282 | "version": "1.1.3", 283 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 284 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 285 | "dev": true, 286 | "requires": { 287 | "object-keys": "^1.0.12" 288 | } 289 | }, 290 | "diff": { 291 | "version": "4.0.2", 292 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 293 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 294 | "dev": true 295 | }, 296 | "emoji-regex": { 297 | "version": "7.0.3", 298 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 299 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 300 | "dev": true 301 | }, 302 | "es-abstract": { 303 | "version": "1.17.6", 304 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", 305 | "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", 306 | "dev": true, 307 | "requires": { 308 | "es-to-primitive": "^1.2.1", 309 | "function-bind": "^1.1.1", 310 | "has": "^1.0.3", 311 | "has-symbols": "^1.0.1", 312 | "is-callable": "^1.2.0", 313 | "is-regex": "^1.1.0", 314 | "object-inspect": "^1.7.0", 315 | "object-keys": "^1.1.1", 316 | "object.assign": "^4.1.0", 317 | "string.prototype.trimend": "^1.0.1", 318 | "string.prototype.trimstart": "^1.0.1" 319 | } 320 | }, 321 | "es-array-method-boxes-properly": { 322 | "version": "1.0.0", 323 | "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", 324 | "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", 325 | "dev": true 326 | }, 327 | "es-get-iterator": { 328 | "version": "1.1.0", 329 | "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", 330 | "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", 331 | "dev": true, 332 | "requires": { 333 | "es-abstract": "^1.17.4", 334 | "has-symbols": "^1.0.1", 335 | "is-arguments": "^1.0.4", 336 | "is-map": "^2.0.1", 337 | "is-set": "^2.0.1", 338 | "is-string": "^1.0.5", 339 | "isarray": "^2.0.5" 340 | } 341 | }, 342 | "es-to-primitive": { 343 | "version": "1.2.1", 344 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 345 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 346 | "dev": true, 347 | "requires": { 348 | "is-callable": "^1.1.4", 349 | "is-date-object": "^1.0.1", 350 | "is-symbol": "^1.0.2" 351 | } 352 | }, 353 | "escape-string-regexp": { 354 | "version": "1.0.5", 355 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 356 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 357 | "dev": true 358 | }, 359 | "esprima": { 360 | "version": "4.0.1", 361 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 362 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 363 | "dev": true 364 | }, 365 | "fill-range": { 366 | "version": "7.0.1", 367 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 368 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 369 | "dev": true, 370 | "requires": { 371 | "to-regex-range": "^5.0.1" 372 | } 373 | }, 374 | "find-up": { 375 | "version": "4.1.0", 376 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 377 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 378 | "dev": true, 379 | "requires": { 380 | "locate-path": "^5.0.0", 381 | "path-exists": "^4.0.0" 382 | } 383 | }, 384 | "flat": { 385 | "version": "4.1.0", 386 | "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", 387 | "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", 388 | "dev": true, 389 | "requires": { 390 | "is-buffer": "~2.0.3" 391 | } 392 | }, 393 | "fs.realpath": { 394 | "version": "1.0.0", 395 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 396 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 397 | "dev": true 398 | }, 399 | "fsevents": { 400 | "version": "2.1.3", 401 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 402 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 403 | "dev": true, 404 | "optional": true 405 | }, 406 | "function-bind": { 407 | "version": "1.1.1", 408 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 409 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 410 | "dev": true 411 | }, 412 | "get-caller-file": { 413 | "version": "2.0.5", 414 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 415 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 416 | "dev": true 417 | }, 418 | "get-func-name": { 419 | "version": "2.0.0", 420 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 421 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 422 | "dev": true 423 | }, 424 | "glob": { 425 | "version": "7.1.6", 426 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 427 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 428 | "dev": true, 429 | "requires": { 430 | "fs.realpath": "^1.0.0", 431 | "inflight": "^1.0.4", 432 | "inherits": "2", 433 | "minimatch": "^3.0.4", 434 | "once": "^1.3.0", 435 | "path-is-absolute": "^1.0.0" 436 | } 437 | }, 438 | "glob-parent": { 439 | "version": "5.1.1", 440 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 441 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 442 | "dev": true, 443 | "requires": { 444 | "is-glob": "^4.0.1" 445 | } 446 | }, 447 | "growl": { 448 | "version": "1.10.5", 449 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 450 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 451 | "dev": true 452 | }, 453 | "has": { 454 | "version": "1.0.3", 455 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 456 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 457 | "dev": true, 458 | "requires": { 459 | "function-bind": "^1.1.1" 460 | } 461 | }, 462 | "has-flag": { 463 | "version": "3.0.0", 464 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 465 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 466 | "dev": true 467 | }, 468 | "has-symbols": { 469 | "version": "1.0.1", 470 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 471 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", 472 | "dev": true 473 | }, 474 | "he": { 475 | "version": "1.2.0", 476 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 477 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 478 | "dev": true 479 | }, 480 | "inflight": { 481 | "version": "1.0.6", 482 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 483 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 484 | "dev": true, 485 | "requires": { 486 | "once": "^1.3.0", 487 | "wrappy": "1" 488 | } 489 | }, 490 | "inherits": { 491 | "version": "2.0.4", 492 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 493 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 494 | "dev": true 495 | }, 496 | "is-arguments": { 497 | "version": "1.0.4", 498 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", 499 | "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", 500 | "dev": true 501 | }, 502 | "is-binary-path": { 503 | "version": "2.1.0", 504 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 505 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 506 | "dev": true, 507 | "requires": { 508 | "binary-extensions": "^2.0.0" 509 | } 510 | }, 511 | "is-buffer": { 512 | "version": "2.0.4", 513 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", 514 | "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", 515 | "dev": true 516 | }, 517 | "is-callable": { 518 | "version": "1.2.0", 519 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", 520 | "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", 521 | "dev": true 522 | }, 523 | "is-date-object": { 524 | "version": "1.0.2", 525 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", 526 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", 527 | "dev": true 528 | }, 529 | "is-extglob": { 530 | "version": "2.1.1", 531 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 532 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 533 | "dev": true 534 | }, 535 | "is-fullwidth-code-point": { 536 | "version": "2.0.0", 537 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 538 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 539 | "dev": true 540 | }, 541 | "is-glob": { 542 | "version": "4.0.1", 543 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 544 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 545 | "dev": true, 546 | "requires": { 547 | "is-extglob": "^2.1.1" 548 | } 549 | }, 550 | "is-map": { 551 | "version": "2.0.1", 552 | "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", 553 | "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", 554 | "dev": true 555 | }, 556 | "is-number": { 557 | "version": "7.0.0", 558 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 559 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 560 | "dev": true 561 | }, 562 | "is-plain-obj": { 563 | "version": "1.1.0", 564 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", 565 | "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", 566 | "dev": true 567 | }, 568 | "is-regex": { 569 | "version": "1.1.1", 570 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", 571 | "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", 572 | "dev": true, 573 | "requires": { 574 | "has-symbols": "^1.0.1" 575 | } 576 | }, 577 | "is-set": { 578 | "version": "2.0.1", 579 | "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", 580 | "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", 581 | "dev": true 582 | }, 583 | "is-string": { 584 | "version": "1.0.5", 585 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", 586 | "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", 587 | "dev": true 588 | }, 589 | "is-symbol": { 590 | "version": "1.0.3", 591 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 592 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 593 | "dev": true, 594 | "requires": { 595 | "has-symbols": "^1.0.1" 596 | } 597 | }, 598 | "isarray": { 599 | "version": "2.0.5", 600 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", 601 | "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", 602 | "dev": true 603 | }, 604 | "isexe": { 605 | "version": "2.0.0", 606 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 607 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 608 | "dev": true 609 | }, 610 | "iterate-iterator": { 611 | "version": "1.0.1", 612 | "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", 613 | "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", 614 | "dev": true 615 | }, 616 | "iterate-value": { 617 | "version": "1.0.2", 618 | "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", 619 | "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", 620 | "dev": true, 621 | "requires": { 622 | "es-get-iterator": "^1.0.2", 623 | "iterate-iterator": "^1.0.1" 624 | } 625 | }, 626 | "js-yaml": { 627 | "version": "3.13.1", 628 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 629 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 630 | "dev": true, 631 | "requires": { 632 | "argparse": "^1.0.7", 633 | "esprima": "^4.0.0" 634 | } 635 | }, 636 | "locate-path": { 637 | "version": "5.0.0", 638 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 639 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 640 | "dev": true, 641 | "requires": { 642 | "p-locate": "^4.1.0" 643 | } 644 | }, 645 | "log-symbols": { 646 | "version": "3.0.0", 647 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", 648 | "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", 649 | "dev": true, 650 | "requires": { 651 | "chalk": "^2.4.2" 652 | } 653 | }, 654 | "minimatch": { 655 | "version": "3.0.4", 656 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 657 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 658 | "dev": true, 659 | "requires": { 660 | "brace-expansion": "^1.1.7" 661 | } 662 | }, 663 | "mocha": { 664 | "version": "8.1.1", 665 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.1.tgz", 666 | "integrity": "sha512-p7FuGlYH8t7gaiodlFreseLxEmxTgvyG9RgPHODFPySNhwUehu8NIb0vdSt3WFckSneswZ0Un5typYcWElk7HQ==", 667 | "dev": true, 668 | "requires": { 669 | "ansi-colors": "4.1.1", 670 | "browser-stdout": "1.3.1", 671 | "chokidar": "3.3.1", 672 | "debug": "3.2.6", 673 | "diff": "4.0.2", 674 | "escape-string-regexp": "1.0.5", 675 | "find-up": "4.1.0", 676 | "glob": "7.1.6", 677 | "growl": "1.10.5", 678 | "he": "1.2.0", 679 | "js-yaml": "3.13.1", 680 | "log-symbols": "3.0.0", 681 | "minimatch": "3.0.4", 682 | "ms": "2.1.2", 683 | "object.assign": "4.1.0", 684 | "promise.allsettled": "1.0.2", 685 | "serialize-javascript": "4.0.0", 686 | "strip-json-comments": "3.0.1", 687 | "supports-color": "7.1.0", 688 | "which": "2.0.2", 689 | "wide-align": "1.1.3", 690 | "workerpool": "6.0.0", 691 | "yargs": "13.3.2", 692 | "yargs-parser": "13.1.2", 693 | "yargs-unparser": "1.6.1" 694 | } 695 | }, 696 | "ms": { 697 | "version": "2.1.2", 698 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 699 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 700 | "dev": true 701 | }, 702 | "normalize-path": { 703 | "version": "3.0.0", 704 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 705 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 706 | "dev": true 707 | }, 708 | "object-inspect": { 709 | "version": "1.8.0", 710 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", 711 | "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", 712 | "dev": true 713 | }, 714 | "object-keys": { 715 | "version": "1.1.1", 716 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 717 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 718 | "dev": true 719 | }, 720 | "object.assign": { 721 | "version": "4.1.0", 722 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 723 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 724 | "dev": true, 725 | "requires": { 726 | "define-properties": "^1.1.2", 727 | "function-bind": "^1.1.1", 728 | "has-symbols": "^1.0.0", 729 | "object-keys": "^1.0.11" 730 | } 731 | }, 732 | "once": { 733 | "version": "1.4.0", 734 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 735 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 736 | "dev": true, 737 | "requires": { 738 | "wrappy": "1" 739 | } 740 | }, 741 | "p-limit": { 742 | "version": "2.3.0", 743 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 744 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 745 | "dev": true, 746 | "requires": { 747 | "p-try": "^2.0.0" 748 | } 749 | }, 750 | "p-locate": { 751 | "version": "4.1.0", 752 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 753 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 754 | "dev": true, 755 | "requires": { 756 | "p-limit": "^2.2.0" 757 | } 758 | }, 759 | "p-try": { 760 | "version": "2.2.0", 761 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 762 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 763 | "dev": true 764 | }, 765 | "path-exists": { 766 | "version": "4.0.0", 767 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 768 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 769 | "dev": true 770 | }, 771 | "path-is-absolute": { 772 | "version": "1.0.1", 773 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 774 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 775 | "dev": true 776 | }, 777 | "pathval": { 778 | "version": "1.1.0", 779 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", 780 | "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", 781 | "dev": true 782 | }, 783 | "picomatch": { 784 | "version": "2.2.2", 785 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 786 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 787 | "dev": true 788 | }, 789 | "promise.allsettled": { 790 | "version": "1.0.2", 791 | "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", 792 | "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", 793 | "dev": true, 794 | "requires": { 795 | "array.prototype.map": "^1.0.1", 796 | "define-properties": "^1.1.3", 797 | "es-abstract": "^1.17.0-next.1", 798 | "function-bind": "^1.1.1", 799 | "iterate-value": "^1.0.0" 800 | } 801 | }, 802 | "randombytes": { 803 | "version": "2.1.0", 804 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 805 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 806 | "dev": true, 807 | "requires": { 808 | "safe-buffer": "^5.1.0" 809 | } 810 | }, 811 | "readdirp": { 812 | "version": "3.3.0", 813 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", 814 | "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", 815 | "dev": true, 816 | "requires": { 817 | "picomatch": "^2.0.7" 818 | } 819 | }, 820 | "require-directory": { 821 | "version": "2.1.1", 822 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 823 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 824 | "dev": true 825 | }, 826 | "require-main-filename": { 827 | "version": "2.0.0", 828 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 829 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 830 | "dev": true 831 | }, 832 | "safe-buffer": { 833 | "version": "5.2.1", 834 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 835 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 836 | "dev": true 837 | }, 838 | "serialize-javascript": { 839 | "version": "4.0.0", 840 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", 841 | "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", 842 | "dev": true, 843 | "requires": { 844 | "randombytes": "^2.1.0" 845 | } 846 | }, 847 | "set-blocking": { 848 | "version": "2.0.0", 849 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 850 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 851 | "dev": true 852 | }, 853 | "sprintf-js": { 854 | "version": "1.0.3", 855 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 856 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 857 | "dev": true 858 | }, 859 | "string-width": { 860 | "version": "2.1.1", 861 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 862 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 863 | "dev": true, 864 | "requires": { 865 | "is-fullwidth-code-point": "^2.0.0", 866 | "strip-ansi": "^4.0.0" 867 | } 868 | }, 869 | "string.prototype.trimend": { 870 | "version": "1.0.1", 871 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", 872 | "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", 873 | "dev": true, 874 | "requires": { 875 | "define-properties": "^1.1.3", 876 | "es-abstract": "^1.17.5" 877 | } 878 | }, 879 | "string.prototype.trimstart": { 880 | "version": "1.0.1", 881 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", 882 | "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", 883 | "dev": true, 884 | "requires": { 885 | "define-properties": "^1.1.3", 886 | "es-abstract": "^1.17.5" 887 | } 888 | }, 889 | "strip-ansi": { 890 | "version": "4.0.0", 891 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 892 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 893 | "dev": true, 894 | "requires": { 895 | "ansi-regex": "^3.0.0" 896 | } 897 | }, 898 | "strip-json-comments": { 899 | "version": "3.0.1", 900 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", 901 | "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", 902 | "dev": true 903 | }, 904 | "supports-color": { 905 | "version": "7.1.0", 906 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 907 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 908 | "dev": true, 909 | "requires": { 910 | "has-flag": "^4.0.0" 911 | }, 912 | "dependencies": { 913 | "has-flag": { 914 | "version": "4.0.0", 915 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 916 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 917 | "dev": true 918 | } 919 | } 920 | }, 921 | "to-regex-range": { 922 | "version": "5.0.1", 923 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 924 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 925 | "dev": true, 926 | "requires": { 927 | "is-number": "^7.0.0" 928 | } 929 | }, 930 | "type-detect": { 931 | "version": "4.0.8", 932 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 933 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 934 | "dev": true 935 | }, 936 | "which": { 937 | "version": "2.0.2", 938 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 939 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 940 | "dev": true, 941 | "requires": { 942 | "isexe": "^2.0.0" 943 | } 944 | }, 945 | "which-module": { 946 | "version": "2.0.0", 947 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 948 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 949 | "dev": true 950 | }, 951 | "wide-align": { 952 | "version": "1.1.3", 953 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 954 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 955 | "dev": true, 956 | "requires": { 957 | "string-width": "^1.0.2 || 2" 958 | } 959 | }, 960 | "workerpool": { 961 | "version": "6.0.0", 962 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", 963 | "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", 964 | "dev": true 965 | }, 966 | "wrap-ansi": { 967 | "version": "5.1.0", 968 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 969 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 970 | "dev": true, 971 | "requires": { 972 | "ansi-styles": "^3.2.0", 973 | "string-width": "^3.0.0", 974 | "strip-ansi": "^5.0.0" 975 | }, 976 | "dependencies": { 977 | "ansi-regex": { 978 | "version": "4.1.0", 979 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 980 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 981 | "dev": true 982 | }, 983 | "string-width": { 984 | "version": "3.1.0", 985 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 986 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 987 | "dev": true, 988 | "requires": { 989 | "emoji-regex": "^7.0.1", 990 | "is-fullwidth-code-point": "^2.0.0", 991 | "strip-ansi": "^5.1.0" 992 | } 993 | }, 994 | "strip-ansi": { 995 | "version": "5.2.0", 996 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 997 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 998 | "dev": true, 999 | "requires": { 1000 | "ansi-regex": "^4.1.0" 1001 | } 1002 | } 1003 | } 1004 | }, 1005 | "wrappy": { 1006 | "version": "1.0.2", 1007 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1008 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1009 | "dev": true 1010 | }, 1011 | "y18n": { 1012 | "version": "4.0.0", 1013 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 1014 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 1015 | "dev": true 1016 | }, 1017 | "yargs": { 1018 | "version": "13.3.2", 1019 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 1020 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 1021 | "dev": true, 1022 | "requires": { 1023 | "cliui": "^5.0.0", 1024 | "find-up": "^3.0.0", 1025 | "get-caller-file": "^2.0.1", 1026 | "require-directory": "^2.1.1", 1027 | "require-main-filename": "^2.0.0", 1028 | "set-blocking": "^2.0.0", 1029 | "string-width": "^3.0.0", 1030 | "which-module": "^2.0.0", 1031 | "y18n": "^4.0.0", 1032 | "yargs-parser": "^13.1.2" 1033 | }, 1034 | "dependencies": { 1035 | "ansi-regex": { 1036 | "version": "4.1.0", 1037 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1038 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1039 | "dev": true 1040 | }, 1041 | "find-up": { 1042 | "version": "3.0.0", 1043 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 1044 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 1045 | "dev": true, 1046 | "requires": { 1047 | "locate-path": "^3.0.0" 1048 | } 1049 | }, 1050 | "locate-path": { 1051 | "version": "3.0.0", 1052 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1053 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1054 | "dev": true, 1055 | "requires": { 1056 | "p-locate": "^3.0.0", 1057 | "path-exists": "^3.0.0" 1058 | } 1059 | }, 1060 | "p-locate": { 1061 | "version": "3.0.0", 1062 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1063 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1064 | "dev": true, 1065 | "requires": { 1066 | "p-limit": "^2.0.0" 1067 | } 1068 | }, 1069 | "path-exists": { 1070 | "version": "3.0.0", 1071 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1072 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1073 | "dev": true 1074 | }, 1075 | "string-width": { 1076 | "version": "3.1.0", 1077 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1078 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1079 | "dev": true, 1080 | "requires": { 1081 | "emoji-regex": "^7.0.1", 1082 | "is-fullwidth-code-point": "^2.0.0", 1083 | "strip-ansi": "^5.1.0" 1084 | } 1085 | }, 1086 | "strip-ansi": { 1087 | "version": "5.2.0", 1088 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1089 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1090 | "dev": true, 1091 | "requires": { 1092 | "ansi-regex": "^4.1.0" 1093 | } 1094 | } 1095 | } 1096 | }, 1097 | "yargs-parser": { 1098 | "version": "13.1.2", 1099 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 1100 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 1101 | "dev": true, 1102 | "requires": { 1103 | "camelcase": "^5.0.0", 1104 | "decamelize": "^1.2.0" 1105 | } 1106 | }, 1107 | "yargs-unparser": { 1108 | "version": "1.6.1", 1109 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", 1110 | "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", 1111 | "dev": true, 1112 | "requires": { 1113 | "camelcase": "^5.3.1", 1114 | "decamelize": "^1.2.0", 1115 | "flat": "^4.1.0", 1116 | "is-plain-obj": "^1.1.0", 1117 | "yargs": "^14.2.3" 1118 | }, 1119 | "dependencies": { 1120 | "ansi-regex": { 1121 | "version": "4.1.0", 1122 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1123 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1124 | "dev": true 1125 | }, 1126 | "find-up": { 1127 | "version": "3.0.0", 1128 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 1129 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 1130 | "dev": true, 1131 | "requires": { 1132 | "locate-path": "^3.0.0" 1133 | } 1134 | }, 1135 | "locate-path": { 1136 | "version": "3.0.0", 1137 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1138 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1139 | "dev": true, 1140 | "requires": { 1141 | "p-locate": "^3.0.0", 1142 | "path-exists": "^3.0.0" 1143 | } 1144 | }, 1145 | "p-locate": { 1146 | "version": "3.0.0", 1147 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1148 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1149 | "dev": true, 1150 | "requires": { 1151 | "p-limit": "^2.0.0" 1152 | } 1153 | }, 1154 | "path-exists": { 1155 | "version": "3.0.0", 1156 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1157 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1158 | "dev": true 1159 | }, 1160 | "string-width": { 1161 | "version": "3.1.0", 1162 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1163 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1164 | "dev": true, 1165 | "requires": { 1166 | "emoji-regex": "^7.0.1", 1167 | "is-fullwidth-code-point": "^2.0.0", 1168 | "strip-ansi": "^5.1.0" 1169 | } 1170 | }, 1171 | "strip-ansi": { 1172 | "version": "5.2.0", 1173 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1174 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1175 | "dev": true, 1176 | "requires": { 1177 | "ansi-regex": "^4.1.0" 1178 | } 1179 | }, 1180 | "yargs": { 1181 | "version": "14.2.3", 1182 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", 1183 | "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", 1184 | "dev": true, 1185 | "requires": { 1186 | "cliui": "^5.0.0", 1187 | "decamelize": "^1.2.0", 1188 | "find-up": "^3.0.0", 1189 | "get-caller-file": "^2.0.1", 1190 | "require-directory": "^2.1.1", 1191 | "require-main-filename": "^2.0.0", 1192 | "set-blocking": "^2.0.0", 1193 | "string-width": "^3.0.0", 1194 | "which-module": "^2.0.0", 1195 | "y18n": "^4.0.0", 1196 | "yargs-parser": "^15.0.1" 1197 | } 1198 | }, 1199 | "yargs-parser": { 1200 | "version": "15.0.1", 1201 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", 1202 | "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", 1203 | "dev": true, 1204 | "requires": { 1205 | "camelcase": "^5.0.0", 1206 | "decamelize": "^1.2.0" 1207 | } 1208 | } 1209 | } 1210 | } 1211 | } 1212 | } --------------------------------------------------------------------------------