refactor: mirrors
68
README.md
|
@ -4,19 +4,22 @@
|
|||
解决一些网站和库无法访问或访问速度慢的问题
|
||||
|
||||
## 特性
|
||||
### 1、 解决git push某些情况下需要临时输入账号密码的问题
|
||||
|
||||
### 2、 github的release、source、zip下载加速
|
||||
### 1、 github的release、source、zip下载加速
|
||||
可解决npm install 时某些安装包下载不下来的问题
|
||||
|
||||
### 2、 解决git push某些情况下需要临时输入账号密码的问题
|
||||
通过将api.github.com域名解析到美国服务器
|
||||
|
||||
### 3、 github的源代码查看(raw/blame查看)
|
||||
|
||||
通过跳转到国内加速链接上
|
||||
### 4、 Stack Overflow 加速
|
||||
|
||||
将ajax.google.com代理到加速代理上
|
||||
### 5、 google cdn 加速
|
||||
通过代理到加速链接上
|
||||
|
||||
### 6、 gist.github.com 加速
|
||||
|
||||
### 6、 更多加速配置
|
||||
等你来提issue
|
||||
|
||||
## 快速开始
|
||||
|
||||
|
@ -85,13 +88,62 @@ sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keyc
|
|||
### npm加速
|
||||
1. yarn 设置淘宝镜像registry
|
||||
2. npm设置官方registry。
|
||||
3. 项目install使用yarn,publish用npm,互不影响
|
||||
3. 项目install使用yarn,发布包publish用npm,互不影响
|
||||
|
||||
### 其他加速
|
||||
1. git clone 加速 [fgit-go](https://github.com/FastGitORG/fgit-go)
|
||||
2. github.com代理网站(不能登录) [hub.fastgit.org](https://hub.fastgit.org/)
|
||||
|
||||
|
||||
|
||||
## api
|
||||
|
||||
### 拦截配置
|
||||
没有配置域名的不会拦截,其他根据配置进行拦截处理
|
||||
```js
|
||||
'github.com': [
|
||||
{ // 此条配置 release archive 下载链接替换,
|
||||
regexp: [ //需要拦截的url
|
||||
'/.*/.*/releases/download/',
|
||||
'/.*/.*/archive/'
|
||||
],
|
||||
//拦截类型
|
||||
// redirect:url, 临时重定向(url会变,一些下载资源可以通过此方式配置)
|
||||
// proxy:url, 代理(url不会变,没有跨域问题)
|
||||
// abort:true, 取消请求(适用于被GFW封锁的资源,找不到替代,直接取消请求,快速失败,节省时间)
|
||||
redirect: 'https://download.fastgit.org' //跳转到加速下载链接上
|
||||
},
|
||||
'ajax.googleapis.com': [
|
||||
{
|
||||
regexp:'.*' // .* 拦截全部url路径,可省略
|
||||
proxy: 'https://ajax.loli.net' //代理到加速链接上(url不会变,没有跨域问题,适用于一些静态资源比如js、css的请求)
|
||||
}
|
||||
],
|
||||
'clients*.google.com': [
|
||||
{
|
||||
abort: true //取消请求,被GFW封锁的资源,找不到替代,直接取消请求,快速失败,节省时间
|
||||
}
|
||||
]
|
||||
],
|
||||
```
|
||||
|
||||
### DNS配置
|
||||
某些域名(比如api.github.com)会被解析到新加坡的ip上,新加坡的服务器在上午挺好,到了晚上就卡死,基本不可用。
|
||||
所以将这些域名解析到美国服务器上就可以正常访问
|
||||
|
||||
```js
|
||||
dns: {
|
||||
mapping: {
|
||||
// "解决push的时候需要输入密码的问题",
|
||||
'api.github.com': 'usa', //配置该域名,使用USA的域名解析服务器
|
||||
'gist.github.com': 'usa'
|
||||
// "avatars*.githubusercontent.com": "usa"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
注意:暂时只支持IPv4的解析
|
||||
|
||||
|
||||
## 开发计划
|
||||
1. 桌面端,右下角小图标
|
||||
2. √ google cdn加速
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
server: {
|
||||
port: 1181
|
||||
},
|
||||
"intercepts": {
|
||||
'notify3.note.youdao.com': [
|
||||
{
|
||||
regexp: '.*',
|
||||
redirect: 'https://localhost:99999'
|
||||
}
|
||||
]
|
||||
},
|
||||
"dns": {
|
||||
"mapping": {
|
||||
//"avatars*.githubusercontent.com": "usa"
|
||||
}
|
||||
},
|
||||
// setting: {
|
||||
// startup: {
|
||||
// // 开机启动
|
||||
// server: true,
|
||||
// proxy: {
|
||||
// system: true,
|
||||
// npm: true
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
const Shell = require('./shell')
|
||||
const lodash = require('lodash')
|
||||
const defConfig = require('./config/index.js')
|
||||
let configTarget = lodash.cloneDeep(defConfig)
|
||||
|
||||
function _deleteDisabledItem (target, objKey) {
|
||||
const obj = lodash.get(target, objKey)
|
||||
for (const key in obj) {
|
||||
|
@ -10,7 +10,7 @@ function _deleteDisabledItem (target, objKey) {
|
|||
}
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
const configApi = {
|
||||
get () {
|
||||
return configTarget
|
||||
},
|
||||
|
@ -33,5 +33,32 @@ module.exports = {
|
|||
},
|
||||
resetDefault () {
|
||||
configTarget = lodash.cloneDeep(defConfig)
|
||||
},
|
||||
getMirrorEnv () {
|
||||
const envMap = Shell.getEnv()
|
||||
const list = []
|
||||
const mirrors = configTarget.mirrors
|
||||
for (const key in mirrors) {
|
||||
const exists = envMap[key] != null
|
||||
list.push({
|
||||
key,
|
||||
value: mirrors[key],
|
||||
exists
|
||||
})
|
||||
}
|
||||
console.log('mirrors:', list)
|
||||
return list
|
||||
},
|
||||
setupMirrors () {
|
||||
const list = configApi.getMirrorEnv()
|
||||
const noSetList = list.filter(item => {
|
||||
return !item.exists
|
||||
})
|
||||
console.log('mirrors will set:', noSetList)
|
||||
if (list.length > 0) {
|
||||
Shell.setEnv({ list: noSetList })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = configApi
|
||||
|
|
|
@ -104,6 +104,12 @@ module.exports = {
|
|||
// "avatars*.githubusercontent.com": "usa"
|
||||
}
|
||||
},
|
||||
mirrors: {
|
||||
SASS_BINARY_SITE: 'https://npm.taobao.org/mirrors/node-sass/',
|
||||
PHANTOMJS_CDNURL: 'https://npm.taobao.org/mirrors/phantomjs/',
|
||||
ELECTRON_MIRROR: 'https://npm.taobao.org/mirrors/electron/',
|
||||
CYPRESS_DOWNLOAD_MIRROR: 'https://cdn.cypress.io'
|
||||
},
|
||||
setting: {
|
||||
startup: { // 开机启动
|
||||
server: true,
|
||||
|
@ -111,6 +117,9 @@ module.exports = {
|
|||
system: true,
|
||||
npm: true,
|
||||
yarn: true
|
||||
},
|
||||
mirrors: {
|
||||
set: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ const proxy = require('./switch/proxy/index.js')
|
|||
const status = require('./status')
|
||||
const config = require('./config')
|
||||
const event = require('./event')
|
||||
|
||||
const shell = require('./shell')
|
||||
async function proxyStartup ({ ip, port }) {
|
||||
for (const key in proxy) {
|
||||
if (config.get().setting.startup.proxy[key]) {
|
||||
|
@ -30,10 +30,15 @@ module.exports = {
|
|||
config.set(newConfig)
|
||||
}
|
||||
try {
|
||||
if (config.get().setting.startup.server) {
|
||||
const startup = config.get().setting.startup
|
||||
if (startup.server) {
|
||||
server.start(newConfig)
|
||||
}
|
||||
await proxyStartup({ ip: '127.0.0.1', port: config.get().server.port })
|
||||
|
||||
if (startup.mirrors.set) {
|
||||
await config.setupMirrors()
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
|
@ -49,6 +54,7 @@ module.exports = {
|
|||
console.log(error)
|
||||
}
|
||||
},
|
||||
event
|
||||
event,
|
||||
shell
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
const url = require('url')
|
||||
module.exports = {
|
||||
requestInterceptor (interceptOpt, rOptions, req, res, ssl) {
|
||||
req.abort()
|
||||
|
|
|
@ -6,7 +6,6 @@ const createRequestHandler = require('./createRequestHandler')
|
|||
const createConnectHandler = require('./createConnectHandler')
|
||||
const createFakeServerCenter = require('./createFakeServerCenter')
|
||||
const createUpgradeHandler = require('./createUpgradeHandler')
|
||||
|
||||
module.exports = {
|
||||
createProxy ({
|
||||
port = config.defaultPort,
|
||||
|
|
|
@ -51,7 +51,7 @@ module.exports = class CertAndKeyContainer {
|
|||
}
|
||||
}
|
||||
let certObj
|
||||
const fast = false
|
||||
const fast = true
|
||||
if (fast) {
|
||||
certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname)
|
||||
_resolve(certObj)
|
||||
|
|
|
@ -5,29 +5,49 @@ const logger = getLogger('proxy')
|
|||
const config = require('../config')
|
||||
const event = require('../event')
|
||||
let server
|
||||
module.exports = {
|
||||
const serverApi = {
|
||||
async start (newConfig) {
|
||||
config.set(newConfig)
|
||||
const proxyOptions = ProxyOptions(config.get())
|
||||
server = mitmproxy.createProxy(proxyOptions, () => {
|
||||
event.fire('status', { key: 'server', value: true })
|
||||
server.on('close', () => {
|
||||
event.fire('status', { key: 'server', value: false })
|
||||
})
|
||||
})
|
||||
server.on('close', () => {
|
||||
event.fire('status', { key: 'server', value: false })
|
||||
})
|
||||
server.on('error', (e) => {
|
||||
event.fire('error', { key: 'server.start', error: e })
|
||||
})
|
||||
server.config = config.get()
|
||||
return server.config
|
||||
},
|
||||
close () {
|
||||
async close () {
|
||||
try {
|
||||
if (server) {
|
||||
server.close()
|
||||
return new Promise((resolve, reject) => {
|
||||
server.close((err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
}
|
||||
},
|
||||
async restart () {
|
||||
try {
|
||||
await serverApi.close()
|
||||
} catch (err) {
|
||||
console.log('stop error', err)
|
||||
}
|
||||
await serverApi.start()
|
||||
},
|
||||
getServer () {
|
||||
return server
|
||||
}
|
||||
}
|
||||
module.exports = serverApi
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
const killByPort = require('./scripts/kill-by-port')
|
||||
const setupCa = require('./scripts/setup-ca')
|
||||
const getEnv = require('./scripts/get-env')
|
||||
const setEnv = require('./scripts/set-env')
|
||||
module.exports = {
|
||||
killByPort,
|
||||
setupCa,
|
||||
getEnv,
|
||||
setEnv
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* 获取环境变量
|
||||
*/
|
||||
const Shell = require('../shell')
|
||||
const execute = Shell.execute
|
||||
const executor = {
|
||||
async windows (exec) {
|
||||
const ret = await exec(['set'], { type: 'cmd' })
|
||||
const map = {}
|
||||
if (ret != null) {
|
||||
const lines = ret.split('\r\n')
|
||||
for (const item of lines) {
|
||||
const kv = item.split('=')
|
||||
if (kv.length > 1) {
|
||||
map[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return map
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async function (args) {
|
||||
return execute(executor, args)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
const Shell = require('../shell')
|
||||
const execute = Shell.execute
|
||||
|
||||
const executor = {
|
||||
async windows (exec, { port }) {
|
||||
const cmds = [`for /f "tokens=5" %a in ('netstat -aon ^| find ":${port}" ^| find "LISTENING"') do taskkill /f /pid %a`]
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const ret = await exec(cmds, { type: 'cmd' })
|
||||
return true
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async function (args) {
|
||||
return execute(executor, args)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* 设置环境变量
|
||||
*/
|
||||
const Shell = require('../shell')
|
||||
const execute = Shell.execute
|
||||
const executor = {
|
||||
async windows (exec, { list }) {
|
||||
const cmds = []
|
||||
for (const item of list) {
|
||||
// [Environment]::SetEnvironmentVariable('FOO', 'bar', 'Machine')
|
||||
cmds.push(`[Environment]::SetEnvironmentVariable('${item.key} ', '${item.value}', 'Machine')`)
|
||||
}
|
||||
const ret = await exec(cmds, { type: 'ps' })
|
||||
return ret
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async function (args) {
|
||||
return execute(executor, args)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
const Shell = require('../shell')
|
||||
const execute = Shell.execute
|
||||
const proxyConfig = require('../../lib/proxy/common/config')
|
||||
const executor = {
|
||||
async windows (exec) {
|
||||
const cmds = ['start ' + proxyConfig.getDefaultCACertPath()]
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const ret = await exec(cmds, { type: 'cmd' })
|
||||
return true
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async function (args) {
|
||||
return execute(executor, args)
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
const util = require('util')
|
||||
const os = require('os')
|
||||
const childProcess = require('child_process')
|
||||
const _exec = childProcess.exec
|
||||
const exec = util.promisify(_exec)
|
||||
const Shell = require('node-powershell')
|
||||
|
||||
class SystemShell {
|
||||
static async exec (cmds, args) {
|
||||
throw new Error('You have to implement the method exec!')
|
||||
}
|
||||
}
|
||||
|
||||
class LinuxSystemShell extends SystemShell {
|
||||
static async exec (cmds) {
|
||||
if (cmds instanceof String) {
|
||||
cmds = [cmds]
|
||||
}
|
||||
for (const cmd of cmds) {
|
||||
await exec(cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DarwinSystemShell extends SystemShell {
|
||||
static async exec (cmds) {
|
||||
if (cmds instanceof String) {
|
||||
cmds = [cmds]
|
||||
}
|
||||
for (const cmd of cmds) {
|
||||
await exec(cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WindowsSystemShell extends SystemShell {
|
||||
static async exec (cmds, { type = 'ps' }) {
|
||||
if (cmds instanceof String) {
|
||||
cmds = [cmds]
|
||||
}
|
||||
if (type === 'ps') {
|
||||
const ps = new Shell({
|
||||
executionPolicy: 'Bypass',
|
||||
noProfile: true
|
||||
})
|
||||
|
||||
for (const cmd of cmds) {
|
||||
console.log('ps:', cmd)
|
||||
ps.addCommand(cmd)
|
||||
}
|
||||
|
||||
const ret = await ps.invoke()
|
||||
console.log('ps complete:', ret)
|
||||
return ret
|
||||
} else {
|
||||
let compose = 'chcp 65001 '
|
||||
for (const cmd of cmds) {
|
||||
compose += ' && ' + cmd
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
childProcess.exec(compose, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
console.error('cmd 命令执行错误:', compose, error, stderr)
|
||||
reject(error)
|
||||
} else {
|
||||
const data = stdout
|
||||
resolve(data)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSystemShell () {
|
||||
switch (getSystemPlatform()) {
|
||||
case 'mac':
|
||||
return DarwinSystemShell
|
||||
case 'linux':
|
||||
return LinuxSystemShell
|
||||
case 'windows':
|
||||
return WindowsSystemShell
|
||||
case 'unknown os':
|
||||
default:
|
||||
throw new Error(`UNKNOWN OS TYPE ${os.platform()}`)
|
||||
}
|
||||
}
|
||||
function getSystemPlatform () {
|
||||
switch (os.platform()) {
|
||||
case 'darwin':
|
||||
return 'mac'
|
||||
case 'linux':
|
||||
return 'linux'
|
||||
case 'win32':
|
||||
case 'win64':
|
||||
return 'windows'
|
||||
case 'unknown os':
|
||||
default:
|
||||
throw new Error(`UNKNOWN OS TYPE ${os.platform()}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function execute (executor, args) {
|
||||
return executor[getSystemPlatform()](getSystemShell().exec, args)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSystemShell,
|
||||
getSystemPlatform,
|
||||
execute
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
const cmd1 = require('node-cmd')
|
||||
cmd1.get('set',
|
||||
function (err, data, stderr) {
|
||||
console.log('cmd complete:', err, data, stderr)
|
||||
if (err) {
|
||||
console.error('cmd 命令执行错误:', err, stderr)
|
||||
} else {
|
||||
console.log('cmd 命令执行结果:', data)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// var process = require('child_process')
|
||||
//
|
||||
// var cmd = 'set'
|
||||
// process.exec(cmd, function (error, stdout, stderr) {
|
||||
// console.log('error:' + error)
|
||||
// console.log('stdout:' + stdout)
|
||||
// console.log('stderr:' + stderr)
|
||||
// })
|
|
@ -1,14 +1,11 @@
|
|||
const util = require('util')
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
const childProcess = require('child_process')
|
||||
const _exec = childProcess.exec
|
||||
const spawn = childProcess.spawn
|
||||
const Registry = require('winreg')
|
||||
// const cmd = require('node-cmd')
|
||||
console.log('childProcess', childProcess)
|
||||
const exec = util.promisify(_exec)
|
||||
const setproxyPs = require('./set-internet-proxy')
|
||||
const refreshInternetPs = require('./refresh-internet')
|
||||
const Shell = require('node-powershell')
|
||||
|
||||
|
@ -89,7 +86,7 @@ class WindowsSystemProxy extends SystemProxy {
|
|||
for (const string of _lanIP) {
|
||||
lanIpStr += string + ';'
|
||||
}
|
||||
console.log('lanIps:', lanIpStr, ip, port)
|
||||
// console.log('lanIps:', lanIpStr, ip, port)
|
||||
await Promise.all([
|
||||
WindowsSystemProxy._asyncRegSet(regKey, 'MigrateProxy', Registry.REG_DWORD, 1),
|
||||
WindowsSystemProxy._asyncRegSet(regKey, 'ProxyEnable', Registry.REG_DWORD, 1),
|
||||
|
|
|
@ -43,7 +43,7 @@ class WindowsSystemProxy extends SystemProxy {
|
|||
console.log('yarn https proxy unset success')
|
||||
|
||||
await winExec('yarn config delete ca')
|
||||
console.log('yarn cafile unset success')
|
||||
console.log('yarn ca unset success')
|
||||
|
||||
// await winExec(' yarn config delete strict-ssl')
|
||||
// console.log('yarn strict-ssl true success')
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const DevSidercar = require('.')
|
||||
require('json5/lib/register')
|
||||
const config = require('../../config/index.json5')
|
||||
// require('json5/lib/register')
|
||||
// const config = require('../../config/index.json5')
|
||||
// 启动服务
|
||||
DevSidercar.api.startup(config)
|
||||
DevSidercar.api.startup()
|
||||
async function onClose () {
|
||||
console.log('on sigint ')
|
||||
await DevSidercar.api.shutdown()
|
||||
|
|
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 584 B |
After Width: | Height: | Size: 941 B |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 353 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 584 B |
After Width: | Height: | Size: 941 B |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 353 KiB |
|
@ -1958,6 +1958,11 @@
|
|||
"integrity": "sha1-fuMwunyq+5gJC+zoal7kQRWQTCw=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/semver": {
|
||||
"version": "7.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.4.tgz",
|
||||
"integrity": "sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ=="
|
||||
},
|
||||
"@types/serve-static": {
|
||||
"version": "1.13.5",
|
||||
"resolved": "https://registry.npm.taobao.org/@types/serve-static/download/@types/serve-static-1.13.5.tgz?cache=0&sync_timestamp=1596840339942&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fserve-static%2Fdownload%2F%40types%2Fserve-static-1.13.5.tgz",
|
||||
|
@ -2367,16 +2372,6 @@
|
|||
"integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1601839122515&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"cacache": {
|
||||
"version": "13.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/cacache/download/cacache-13.0.1.tgz",
|
||||
|
@ -2403,34 +2398,6 @@
|
|||
"unique-filename": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npm.taobao.org/chalk/download/chalk-4.1.0.tgz",
|
||||
"integrity": "sha1-ThSHCmGNni7dl92DRf2dncMVZGo=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npm.taobao.org/color-name/download/color-name-1.1.4.tgz",
|
||||
"integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"find-cache-dir": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-3.3.1.tgz",
|
||||
|
@ -2452,25 +2419,6 @@
|
|||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz",
|
||||
|
@ -2535,16 +2483,6 @@
|
|||
"minipass": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1598611709087&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
|
||||
"integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"terser-webpack-plugin": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npm.taobao.org/terser-webpack-plugin/download/terser-webpack-plugin-2.3.8.tgz?cache=0&sync_timestamp=1602701885709&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fterser-webpack-plugin%2Fdownload%2Fterser-webpack-plugin-2.3.8.tgz",
|
||||
|
@ -2561,18 +2499,6 @@
|
|||
"terser": "^4.6.12",
|
||||
"webpack-sources": "^1.4.3"
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.0.0-beta.8",
|
||||
"resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-16.0.0-beta.8.tgz?cache=0&sync_timestamp=1600850354305&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-16.0.0-beta.8.tgz",
|
||||
"integrity": "sha1-H1I9n+qOjG5PW7mf12gWWvWEWHk=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3247,7 +3173,6 @@
|
|||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz?cache=0&sync_timestamp=1598649734444&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fargparse%2Fdownload%2Fargparse-1.0.10.tgz",
|
||||
"integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
|
@ -3511,8 +3436,7 @@
|
|||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/at-least-node/download/at-least-node-1.0.0.tgz",
|
||||
"integrity": "sha1-YCzUtG6EStTv/JKoARo8RuAjjcI=",
|
||||
"dev": true
|
||||
"integrity": "sha1-YCzUtG6EStTv/JKoARo8RuAjjcI="
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
|
@ -4934,7 +4858,6 @@
|
|||
"version": "8.7.2",
|
||||
"resolved": "https://registry.npm.taobao.org/builder-util-runtime/download/builder-util-runtime-8.7.2.tgz",
|
||||
"integrity": "sha1-2Tr8cUKKEnibQ34ThQ4fp9qVbXI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
"sax": "^1.2.4"
|
||||
|
@ -7282,6 +7205,52 @@
|
|||
"integrity": "sha1-Gt+sWv/OhNhbPXs9+8St4pOm/8Q=",
|
||||
"dev": true
|
||||
},
|
||||
"electron-updater": {
|
||||
"version": "4.3.5",
|
||||
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.3.5.tgz",
|
||||
"integrity": "sha512-5jjN7ebvfj1cLI0VZMdCnJk6aC4bP+dy7ryBf21vArR0JzpRVk0OZHA2QBD+H5rm6ZSeDYHOY6+8PrMEqJ4wlQ==",
|
||||
"requires": {
|
||||
"@types/semver": "^7.3.1",
|
||||
"builder-util-runtime": "8.7.2",
|
||||
"fs-extra": "^9.0.1",
|
||||
"js-yaml": "^3.14.0",
|
||||
"lazy-val": "^1.0.4",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"semver": "^7.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
|
||||
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
|
||||
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
|
||||
},
|
||||
"universalify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
|
||||
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.3.tgz",
|
||||
|
@ -7908,8 +7877,7 @@
|
|||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npm.taobao.org/esprima/download/esprima-4.0.1.tgz",
|
||||
"integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE=",
|
||||
"dev": true
|
||||
"integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE="
|
||||
},
|
||||
"esquery": {
|
||||
"version": "1.3.1",
|
||||
|
@ -8931,8 +8899,7 @@
|
|||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&sync_timestamp=1589682809142&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz",
|
||||
"integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=",
|
||||
"dev": true
|
||||
"integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs="
|
||||
},
|
||||
"gzip-size": {
|
||||
"version": "5.1.1",
|
||||
|
@ -10274,7 +10241,6 @@
|
|||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npm.taobao.org/js-yaml/download/js-yaml-3.14.0.tgz",
|
||||
"integrity": "sha1-p6NBcPJqIbsWJCTYray0ETpp5II=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
|
@ -10496,8 +10462,7 @@
|
|||
"lazy-val": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npm.taobao.org/lazy-val/download/lazy-val-1.0.4.tgz",
|
||||
"integrity": "sha1-iCY2pyRcLP5uCk47psXWihN+XGU=",
|
||||
"dev": true
|
||||
"integrity": "sha1-iCY2pyRcLP5uCk47psXWihN+XGU="
|
||||
},
|
||||
"lcid": {
|
||||
"version": "1.0.0",
|
||||
|
@ -10692,6 +10657,11 @@
|
|||
"integrity": "sha1-US6b1yHSctlOPTpjZT+hdRZ0HKY=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
||||
},
|
||||
"lodash.kebabcase": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/lodash.kebabcase/download/lodash.kebabcase-4.1.1.tgz",
|
||||
|
@ -13715,8 +13685,7 @@
|
|||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz",
|
||||
"integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=",
|
||||
"dev": true
|
||||
"integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk="
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "2.7.1",
|
||||
|
@ -14402,8 +14371,7 @@
|
|||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsprintf-js%2Fdownload%2Fsprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
|
@ -16367,6 +16335,87 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.0.0-beta.8",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.8.tgz",
|
||||
"integrity": "sha512-oouKUQWWHbSihqSD7mhymGPX1OQ4hedzAHyvm8RdyHh6m3oIvoRF+NM45i/bhNOlo8jCnuJhaSUf/6oDjv978g==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-ref": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/vue-ref/download/vue-ref-2.0.0.tgz",
|
||||
|
|
|
@ -10,13 +10,15 @@
|
|||
"electron:build": "vue-cli-service electron:build",
|
||||
"electron": "vue-cli-service electron:serve",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"postuninstall": "electron-builder install-app-deps"
|
||||
"postuninstall": "electron-builder install-app-deps",
|
||||
"electron:generate-icons": "electron-icon-builder --input=./public/icon.png --output=build --flatten"
|
||||
},
|
||||
"main": "background.js",
|
||||
"dependencies": {
|
||||
"@docmirror/dev-sidecar": "1.0.0",
|
||||
"ant-design-vue": "^1.6.5",
|
||||
"core-js": "^3.6.5",
|
||||
"electron-updater": "^4.3.5",
|
||||
"es-abstract": "^1.17.7",
|
||||
"json5": "^2.1.3",
|
||||
"lodash": "^4.17.20",
|
||||
|
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 40 KiB |
|
@ -0,0 +1,18 @@
|
|||
<svg id="svg_canvas" viewBox="0 0 260 260" width="260" height="260" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="scale(2)">
|
||||
<g class="logo-entity" transform="translate(139,-12.5) scale(-1.40,1.40)">
|
||||
<circle fill="#FFF" cx="45.9" cy="55.2" r="17.5"
|
||||
></circle>
|
||||
<circle cx="23.5" cy="21.7" r="9.6" fill="#FFF"></circle>
|
||||
<circle cx="52.3" cy="23.9" r="6.9" fill="#FFF"></circle>
|
||||
<circle stroke="#FFF" stroke-miterlimit="10" cx="32.5" cy="89.7" r="9.6" fill="#FFF"></circle>
|
||||
|
||||
<circle fill="none" stroke="#FFF" stroke-width="5" stroke-miterlimit="10" cx="84" cy="61.3" r="10.4"></circle>
|
||||
|
||||
<line fill="none" stroke="#FFF" stroke-width="5" stroke-miterlimit="10" x1="37.9" y1="44.7" x2="26.2" y2="26.9"></line>
|
||||
<line fill="none" stroke="#FFF" stroke-width="5" stroke-miterlimit="10" x1="48.1" y1="44.7" x2="51.3" y2="27.7"></line>
|
||||
<line fill="none" stroke="#FFF" stroke-width="5" stroke-miterlimit="10" x1="40.1" y1="67.4" x2="34.9" y2="82.5"></line>
|
||||
<line fill="none" stroke="#FFF" stroke-width="5" stroke-miterlimit="10" x1="57" y1="55.5" x2="71.8" y2="58.6"></line>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -1,18 +1,18 @@
|
|||
<svg id="svg_canvas" viewBox="0 0 260 260" width="260" height="260" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="scale(2)">
|
||||
<g class="logo-entity" transform="translate(144,-12.5) scale(-1.40,1.40)">
|
||||
<g class="logo-entity" transform="translate(139,-12.5) scale(-1.40,1.40)">
|
||||
<circle fill="#1B7FCD" cx="45.9" cy="55.2" r="17.5"
|
||||
></circle>
|
||||
<circle cx="23.5" cy="21.7" r="9.6" fill="#1B7FCD"></circle>
|
||||
<circle cx="52.3" cy="23.9" r="6.9" fill="#1B7FCD"></circle>
|
||||
<circle stroke="#1B7FCD" stroke-miterlimit="10" cx="32.5" cy="89.7" r="9.6" fill="#1B7FCD"></circle>
|
||||
|
||||
<circle fill="none" stroke="#1B7FCD" stroke-width="5" stroke-miterlimit="10" cx="87" cy="61.3" r="10.4"></circle>
|
||||
<circle fill="none" stroke="#1B7FCD" stroke-width="5" stroke-miterlimit="10" cx="84" cy="61.3" r="10.4"></circle>
|
||||
|
||||
<line fill="none" stroke="#1B7FCD" stroke-width="5" stroke-miterlimit="10" x1="37.9" y1="44.7" x2="26.2" y2="26.9"></line>
|
||||
<line fill="none" stroke="#1B7FCD" stroke-width="5" stroke-miterlimit="10" x1="48.1" y1="44.7" x2="51.3" y2="27.7"></line>
|
||||
<line fill="none" stroke="#1B7FCD" stroke-width="5" stroke-miterlimit="10" x1="57" y1="55.5" x2="77.8" y2="59.2"></line>
|
||||
<line fill="none" stroke="#1B7FCD" stroke-width="5" stroke-miterlimit="10" x1="40.1" y1="67.4" x2="34.9" y2="82.5"></line>
|
||||
<line fill="none" stroke="#1B7FCD" stroke-width="5" stroke-miterlimit="10" x1="57" y1="55.5" x2="71.8" y2="58.6"></line>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 51 KiB |
|
@ -1,4 +1,5 @@
|
|||
'use strict'
|
||||
/* global __static */
|
||||
import path from 'path'
|
||||
import { app, protocol, BrowserWindow, Menu, Tray } from 'electron'
|
||||
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
|
||||
|
@ -9,7 +10,8 @@ const isDevelopment = process.env.NODE_ENV !== 'production'
|
|||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let win
|
||||
let tray
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let tray // 防止被内存清理
|
||||
let forceClose = false
|
||||
|
||||
// Scheme must be registered before the app is ready
|
||||
|
@ -28,7 +30,7 @@ function setTray (app) {
|
|||
label: '退出',
|
||||
click: () => {
|
||||
forceClose = true
|
||||
app.quit()
|
||||
quit(app)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -57,14 +59,16 @@ function createWindow () {
|
|||
// Create the browser window.
|
||||
win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
height: 700,
|
||||
webPreferences: {
|
||||
enableRemoteModule: true,
|
||||
// preload: path.join(__dirname, 'preload.js'),
|
||||
// Use pluginOptions.nodeIntegration, leave this alone
|
||||
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
|
||||
nodeIntegration: true// process.env.ELECTRON_NODE_INTEGRATION
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line no-undef
|
||||
icon: path.join(__static, 'icon.png')
|
||||
})
|
||||
|
||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
|
@ -79,7 +83,7 @@ function createWindow () {
|
|||
|
||||
win.on('closed', async (e) => {
|
||||
win = null
|
||||
await bridge.devSidecar.api.shutdown()
|
||||
tray = null
|
||||
})
|
||||
|
||||
win.on('close', (e) => {
|
||||
|
@ -95,7 +99,7 @@ app.on('window-all-closed', () => {
|
|||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
quit(app)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -129,17 +133,22 @@ app.on('ready', async () => {
|
|||
}
|
||||
})
|
||||
|
||||
function quit (app) {
|
||||
bridge.devSidecar.api.shutdown().then(() => {
|
||||
app.quit()
|
||||
})
|
||||
}
|
||||
// Exit cleanly on request from parent process in development mode.
|
||||
if (isDevelopment) {
|
||||
if (process.platform === 'win32') {
|
||||
process.on('message', (data) => {
|
||||
if (data === 'graceful-exit') {
|
||||
app.quit()
|
||||
quit(app)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
process.on('SIGTERM', () => {
|
||||
app.quit()
|
||||
quit(app)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,14 @@ import fs from 'fs'
|
|||
import JSON5 from 'json5'
|
||||
|
||||
const localApi = {
|
||||
getApiList () {
|
||||
const core = lodash.cloneDeep(DevSidecar.api)
|
||||
const local = lodash.cloneDeep(localApi)
|
||||
lodash.merge(core, local)
|
||||
const list = []
|
||||
_deepFindFunction(list, core, '')
|
||||
return list
|
||||
},
|
||||
config: {
|
||||
/**
|
||||
* 保存自定义的 config
|
||||
|
@ -21,20 +29,30 @@ const localApi = {
|
|||
_merge(defConfig, newConfig, saveConfig, 'setting.startup.server', true)
|
||||
_merge(defConfig, newConfig, saveConfig, 'setting.startup.proxy')
|
||||
|
||||
// TODO 保存到文件
|
||||
// console.log('save config ', saveConfig)
|
||||
fs.writeFileSync(_getConfigPath(), JSON5.stringify(saveConfig, null, 2))
|
||||
return saveConfig
|
||||
},
|
||||
reload () {
|
||||
const path = _getConfigPath()
|
||||
if (!fs.existsSync(path)) {
|
||||
return
|
||||
return DevSidecar.api.config.get()
|
||||
}
|
||||
const file = fs.readFileSync(path)
|
||||
const userConfig = JSON5.parse(file.toString())
|
||||
DevSidecar.api.config.set(userConfig)
|
||||
return DevSidecar.api.config.get()
|
||||
const config = DevSidecar.api.config.get()
|
||||
return config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _deepFindFunction (list, parent, parentKey) {
|
||||
for (const key in parent) {
|
||||
const item = parent[key]
|
||||
if (item instanceof Function) {
|
||||
list.push(parentKey + key)
|
||||
} else if (item instanceof Object) {
|
||||
_deepFindFunction(list, item, parentKey + key + '.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +126,10 @@ export default {
|
|||
console.log('bridge on status', event)
|
||||
win.webContents.send('status', { ...event })
|
||||
})
|
||||
DevSidecar.api.event.register('error', (event) => {
|
||||
console.error('bridge on error', event)
|
||||
win.webContents.send('error.core', event)
|
||||
})
|
||||
|
||||
// 合并用户配置
|
||||
localApi.config.reload()
|
||||
|
|
|
@ -2,10 +2,15 @@ import Vue from 'vue'
|
|||
import App from './view/components/App.vue'
|
||||
import antd from 'ant-design-vue'
|
||||
import 'ant-design-vue/dist/antd.css'
|
||||
import './view'
|
||||
import view from './view'
|
||||
import { apiInit } from './view/api'
|
||||
Vue.config.productionTip = false
|
||||
Vue.use(antd)
|
||||
|
||||
new Vue({
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
apiInit().then(() => {
|
||||
const app = new Vue({
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
|
||||
view.register(app)
|
||||
})
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import lodash from 'lodash'
|
||||
import { ipcRenderer } from 'electron'
|
||||
const doInvoke = (api, args) => {
|
||||
return ipcRenderer.invoke('apiInvoke', [api, args])
|
||||
return ipcRenderer.invoke('apiInvoke', [api, args]).catch(err => {
|
||||
console.error('api invoke error:', err)
|
||||
})
|
||||
}
|
||||
|
||||
const bindApi = (api, param1) => {
|
||||
|
@ -15,23 +17,21 @@ const apiObj = {
|
|||
},
|
||||
doInvoke
|
||||
}
|
||||
let inited = false
|
||||
|
||||
bindApi('startup')
|
||||
bindApi('shutdown')
|
||||
|
||||
bindApi('config.set')
|
||||
bindApi('config.get')
|
||||
bindApi('config.save')
|
||||
bindApi('config.reload')
|
||||
|
||||
bindApi('server.start')
|
||||
bindApi('server.close')
|
||||
|
||||
bindApi('proxy.system.open')
|
||||
bindApi('proxy.system.close')
|
||||
bindApi('proxy.npm.open')
|
||||
bindApi('proxy.npm.close')
|
||||
bindApi('proxy.yarn.open')
|
||||
bindApi('proxy.yarn.close')
|
||||
|
||||
export function apiInit () {
|
||||
if (!inited) {
|
||||
return doInvoke('getApiList').then(list => {
|
||||
console.log('apiList', list)
|
||||
inited = true
|
||||
for (const item of list) {
|
||||
bindApi(item)
|
||||
}
|
||||
return apiObj
|
||||
})
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
resolve(apiObj)
|
||||
})
|
||||
}
|
||||
export default apiObj
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
<template>
|
||||
<div style="margin:auto">
|
||||
<div style="text-align: center"><img height="80px" src="/logo/logo-lang.svg"></div>
|
||||
<a-card title="DevSidecar-开发者辅助工具 " style="width: 500px;margin:auto">
|
||||
<a-card title="给开发者的辅助工具" style="width: 500px;margin:auto">
|
||||
<div style="display: flex; align-items:center;justify-content:space-around;flex-direction: row">
|
||||
<div style="text-align: center">
|
||||
<div class="big_button" >
|
||||
<a-button shape="circle" icon="poweroff" :type="startup.type()" :loading="startup.loading" @click="startup.doClick" ></a-button>
|
||||
<a-button shape="circle" :type="startup.type()" :loading="startup.loading" @click="startup.doClick" >
|
||||
<img v-if="!startup.loading && !status.server" width="50" src="/logo/logo-simple.svg">
|
||||
<img v-if="!startup.loading && status.server" width="50" src="/logo/logo-fff.svg">
|
||||
</a-button>
|
||||
<div style="margin-top: 10px">{{status.server?'已开启':'已关闭'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -32,11 +35,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<span slot="extra" >
|
||||
<span slot="extra" >
|
||||
<a-button style="margin-right:10px" @click="openSetupCa" >安装根证书</a-button>
|
||||
<a-button v-if="config" @click="openSettings" icon="setting" ></a-button>
|
||||
</span>
|
||||
</span>
|
||||
</a-card>
|
||||
|
||||
<setup-ca title="安装证书" :visible.sync="setupCa.visible"></setup-ca>
|
||||
<settings v-if="config" title="设置" :config="config" :visible.sync="settings.visible" @change="onConfigChanged"></settings>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -48,10 +53,11 @@ import api from '../api'
|
|||
import status from '../status'
|
||||
import lodash from 'lodash'
|
||||
import Settings from './settings'
|
||||
import setupCa from './setup-ca'
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Settings
|
||||
Settings, setupCa
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -87,6 +93,9 @@ export default {
|
|||
config: undefined,
|
||||
settings: {
|
||||
visible: false
|
||||
},
|
||||
setupCa: {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -105,6 +114,7 @@ export default {
|
|||
methods: {
|
||||
reloadConfig () {
|
||||
return api.config.reload().then(ret => {
|
||||
console.log('config', ret)
|
||||
this.config = ret
|
||||
return ret
|
||||
})
|
||||
|
@ -160,15 +170,14 @@ export default {
|
|||
},
|
||||
onConfigChanged (newConfig) {
|
||||
console.log('config chagned', newConfig)
|
||||
api.config.save(newConfig).then(() => {
|
||||
return this.reloadConfig()
|
||||
}).then(() => {
|
||||
this.reloadConfig().then(() => {
|
||||
if (this.status.server) {
|
||||
return this.onServerClick(false).then(() => {
|
||||
return this.onServerClick(true)
|
||||
})
|
||||
return api.server.restart()
|
||||
}
|
||||
})
|
||||
},
|
||||
openSetupCa () {
|
||||
this.setupCa.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,26 +42,53 @@
|
|||
<a-button type="primary" icon="plus" @click="addDnsMapping()" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="启动设置" key="3" >
|
||||
<a-tab-pane tab="镜像变量" key="3">
|
||||
<div>
|
||||
<div>某些库需要自己设置代理环境变量,才能安装,比如:electron</div>
|
||||
<div>
|
||||
<a-form-item label="镜像环境变量" >
|
||||
<a-switch v-model="targetConfig.setting.startup.mirrors.set" default-checked v-on:click="(checked)=>{targetConfig.setting.startup.mirrors.set = checked}">
|
||||
<a-icon slot="checkedChildren" type="check" />
|
||||
<a-icon slot="unCheckedChildren" type="close" />
|
||||
</a-switch>
|
||||
启动后自动检查设置
|
||||
|
||||
<a-button style="margin-left:10px" @click="doSetMirrorEnvNow">立即设置</a-button>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-row :gutter="10" style="margin-top: 10px" v-for="(item,index) of mirrorEnvs" :key = 'index'>
|
||||
<a-col :span="10">
|
||||
<a-input :disabled="item.key ===false" v-model="item.key"></a-input>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<a-input :disabled="item.value ===false" v-model="item.value"></a-input>
|
||||
</a-col>
|
||||
<a-col :span="4">
|
||||
<a-icon v-if="item.exists" style="color:green" type="check" />
|
||||
<a-icon v-if="!item.exists" title="还未设置" style="color:red" type="exclamation-circle" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane tab="启动设置" key="4" >
|
||||
<div>启动应用程序后自动启动</div>
|
||||
<a-form style="margin-top: 20px" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" >
|
||||
<a-form-item label="代理服务" style="margin-bottom: 10px">
|
||||
<a-form-item label="代理服务" >
|
||||
<a-switch v-model="targetConfig.setting.startup.server" default-checked v-on:click="(checked)=>{targetConfig.setting.startup.server = checked}">
|
||||
<a-icon slot="checkedChildren" type="check" />
|
||||
<a-icon slot="unCheckedChildren" type="close" />
|
||||
</a-switch>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item style="margin-bottom: 10px" v-for="(item,key) in targetConfig.setting.startup.proxy" :key="key" :label="key">
|
||||
<a-form-item v-for="(item,key) in targetConfig.setting.startup.proxy" :key="key" :label="key">
|
||||
<a-switch v-model="targetConfig.setting.startup.proxy[key]" default-checked v-on:click="(checked)=>{targetConfig.setting.startup.proxy[key] = checked}">
|
||||
<a-icon slot="checkedChildren" type="check" />
|
||||
<a-icon slot="unCheckedChildren" type="close" />
|
||||
</a-switch>
|
||||
</a-form-item>
|
||||
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
@ -72,8 +99,9 @@
|
|||
<script>
|
||||
import vueJsonEditor from 'vue-json-editor'
|
||||
import lodash from 'lodash'
|
||||
import api from '../api'
|
||||
export default {
|
||||
name: 'App',
|
||||
name: 'settings',
|
||||
components: {
|
||||
vueJsonEditor
|
||||
},
|
||||
|
@ -92,7 +120,8 @@ export default {
|
|||
data () {
|
||||
return {
|
||||
targetConfig: {},
|
||||
dnsMappings: []
|
||||
dnsMappings: [],
|
||||
mirrorEnvs: []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
@ -109,6 +138,10 @@ export default {
|
|||
key, value
|
||||
})
|
||||
}
|
||||
|
||||
api.config.getMirrorEnv().then(ret => {
|
||||
this.mirrorEnvs = ret
|
||||
})
|
||||
},
|
||||
onJsonChange (config) {
|
||||
},
|
||||
|
@ -141,13 +174,21 @@ export default {
|
|||
mapping[item.key] = item.value
|
||||
}
|
||||
this.targetConfig.dns.mapping = mapping
|
||||
|
||||
const mirrors = {}
|
||||
for (const item of this.mirrorEnvs) {
|
||||
mirrors[item.key] = item.value
|
||||
}
|
||||
this.targetConfig.mirrors = mirrors
|
||||
},
|
||||
isChanged () {
|
||||
this.syncTargetConfig()
|
||||
return !lodash.isEqual(this.config, this.targetConfig)
|
||||
},
|
||||
doSave () {
|
||||
this.$emit('change', this.targetConfig)
|
||||
return api.config.save(this.targetConfig).then(ret => {
|
||||
this.$emit('change', ret)
|
||||
})
|
||||
},
|
||||
deleteDnsMapping (item, index) {
|
||||
this.dnsMappings.splice(index, 1)
|
||||
|
@ -157,6 +198,21 @@ export default {
|
|||
},
|
||||
addDnsMapping () {
|
||||
this.dnsMappings.push({ key: '', value: 'usa' })
|
||||
},
|
||||
doSetMirrorEnvNow () {
|
||||
this.syncTargetConfig()
|
||||
this.doSave().then(() => {
|
||||
return api.config.setupMirrors()
|
||||
}).then(() => {
|
||||
return api.config.getMirrorEnv().then(ret => {
|
||||
this.mirrorEnvs = ret
|
||||
})
|
||||
}).then(() => {
|
||||
this.$message.info('设置成功')
|
||||
})
|
||||
},
|
||||
addMirrors () {
|
||||
this.mirrorEnvs.push({ key: '', value: '', exists: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -182,5 +238,11 @@ export default {
|
|||
}
|
||||
.json-wrapper .ant-tabs-tabpane-active{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.a-form{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
placement="right"
|
||||
:closable="false"
|
||||
:visible="visible"
|
||||
:after-visible-change="afterVisibleChange"
|
||||
@close="onClose"
|
||||
width="650px"
|
||||
height="100%"
|
||||
:slots="{ title: 'title' }"
|
||||
wrapClassName="json-wrapper"
|
||||
>
|
||||
<template slot="title">
|
||||
{{title}}
|
||||
<a-button type="primary" style="float:right" @click="doSetup()">点此去安装</a-button>
|
||||
</template>
|
||||
<img width="100%" src="/setup.png" />
|
||||
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import api from '../api'
|
||||
export default {
|
||||
name: 'setup-ca',
|
||||
components: {
|
||||
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '安装根证书'
|
||||
},
|
||||
visible: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods: {
|
||||
afterVisibleChange (val) {
|
||||
},
|
||||
showDrawer () {
|
||||
this.$emit('update:visible', true)
|
||||
},
|
||||
onClose () {
|
||||
this.$emit('update:visible', false)
|
||||
},
|
||||
doSetup () {
|
||||
api.shell.setupCa()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -0,0 +1,45 @@
|
|||
import api from './api'
|
||||
import status from './status'
|
||||
import lodash from 'lodash'
|
||||
function register (app) {
|
||||
api.on('status', (event, message) => {
|
||||
console.log('view on status', event, message)
|
||||
const value = message.value
|
||||
const key = message.key
|
||||
lodash.set(status, key, value)
|
||||
})
|
||||
|
||||
api.on('error.core', (event, message) => {
|
||||
console.error('view on error', message)
|
||||
const key = message.key
|
||||
if (key === 'server.start') {
|
||||
handleServerStartError(message.error, app)
|
||||
}
|
||||
})
|
||||
api.on('error', (event, message) => {
|
||||
console.error('error', event, message)
|
||||
})
|
||||
}
|
||||
|
||||
function handleServerStartError (err, app) {
|
||||
if (err.message.indexOf('listen EADDRINUSE') >= 0) {
|
||||
app.$confirm({
|
||||
title: '端口被占用,代理服务启动失败',
|
||||
content: '是否要杀掉占用进程?',
|
||||
onOk () {
|
||||
// TODO 杀掉进程
|
||||
api.config.get().then(config => {
|
||||
console.log('config', config)
|
||||
api.shell.killByPort({ port: config.server.port }).then(ret => {
|
||||
app.$message.info('杀掉进程成功,请重试开启代理服务')
|
||||
})
|
||||
})
|
||||
},
|
||||
onCancel () {
|
||||
console.log('Cancel')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default register
|
|
@ -1 +1,5 @@
|
|||
import './status'
|
||||
import register from './event'
|
||||
export default {
|
||||
register
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import api from './api'
|
||||
import lodash from 'lodash'
|
||||
const status = {
|
||||
server: false,
|
||||
proxy: {
|
||||
|
@ -7,11 +5,4 @@ const status = {
|
|||
npm: false
|
||||
}
|
||||
}
|
||||
|
||||
api.on('status', (event, message) => {
|
||||
console.log('view on status', event, message)
|
||||
const value = message.value
|
||||
const key = message.key
|
||||
lodash.set(status, key, value)
|
||||
})
|
||||
export default status
|
||||
|
|