✨ 终端展示服务端ping客户端延迟
This commit is contained in:
parent
d184a8bdaa
commit
94097a1c6d
@ -1,3 +1,10 @@
|
|||||||
|
## [2.2.7](https://github.com/chaos-zhu/easynode/releases) (2024-10-xx)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 终端连接页新增展示服务端ping客户端延迟ms
|
||||||
|
* 修复自定义客户端端口默认字符串的bug
|
||||||
|
|
||||||
## [2.2.6](https://github.com/chaos-zhu/easynode/releases) (2024-10-14)
|
## [2.2.6](https://github.com/chaos-zhu/easynode/releases) (2024-10-14)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
@ -4,7 +4,7 @@ const { verifyAuthSync } = require('../utils/verify-auth')
|
|||||||
const { AESDecryptSync } = require('../utils/encrypt')
|
const { AESDecryptSync } = require('../utils/encrypt')
|
||||||
const { readSSHRecord, readHostList } = require('../utils/storage')
|
const { readSSHRecord, readHostList } = require('../utils/storage')
|
||||||
const { asyncSendNotice } = require('../utils/notify')
|
const { asyncSendNotice } = require('../utils/notify')
|
||||||
const { isAllowedIp } = require('../utils/tools')
|
const { isAllowedIp, ping } = require('../utils/tools')
|
||||||
|
|
||||||
function createInteractiveShell(socket, sshClient) {
|
function createInteractiveShell(socket, sshClient) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@ -98,6 +98,7 @@ async function createTerminal(hostId, socket, sshClient) {
|
|||||||
...authInfo
|
...authInfo
|
||||||
// debug: (info) => console.log(info)
|
// debug: (info) => console.log(info)
|
||||||
})
|
})
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
consola.error('创建终端失败: ', host, err.message)
|
consola.error('创建终端失败: ', host, err.message)
|
||||||
socket.emit('create_fail', err.message)
|
socket.emit('create_fail', err.message)
|
||||||
@ -147,6 +148,7 @@ module.exports = (httpServer) => {
|
|||||||
}
|
}
|
||||||
socket.on('input', listenerInput)
|
socket.on('input', listenerInput)
|
||||||
socket.on('resize', resizeShell)
|
socket.on('resize', resizeShell)
|
||||||
|
|
||||||
// 重连
|
// 重连
|
||||||
socket.on('reconnect_terminal', async () => {
|
socket.on('reconnect_terminal', async () => {
|
||||||
consola.info('重连终端: ', hostId)
|
consola.info('重连终端: ', hostId)
|
||||||
@ -168,6 +170,14 @@ module.exports = (httpServer) => {
|
|||||||
stream = await createTerminal(hostId, socket, sshClient)
|
stream = await createTerminal(hostId, socket, sshClient)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
socket.on('get_ping',async (ip) => {
|
||||||
|
try {
|
||||||
|
socket.emit('ping_data', await ping(ip, 2500))
|
||||||
|
} catch (error) {
|
||||||
|
socket.emit('ping_data', { success: false, msg: error.message })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
socket.on('disconnect', (reason) => {
|
socket.on('disconnect', (reason) => {
|
||||||
consola.info('终端socket连接断开:', reason)
|
consola.info('终端socket连接断开:', reason)
|
||||||
})
|
})
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
const { exec } = require('child_process')
|
||||||
|
const os = require('os')
|
||||||
const net = require('net')
|
const net = require('net')
|
||||||
|
const iconv = require('iconv-lite')
|
||||||
const axios = require('axios')
|
const axios = require('axios')
|
||||||
const request = axios.create({ timeout: 3000 })
|
const request = axios.create({ timeout: 3000 })
|
||||||
|
|
||||||
@ -240,6 +243,45 @@ const isAllowedIp = (requestIP) => {
|
|||||||
return flag
|
return flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ping = (ip, timeout = 5000) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve({ success: false, msg: 'ping timeout!' })
|
||||||
|
}, timeout)
|
||||||
|
let isWin = os.platform() === 'win32'
|
||||||
|
const command = isWin ? `ping -n 1 ${ ip }` : `ping -c 1 ${ ip }`
|
||||||
|
const options = isWin ? { encoding: 'buffer' } : {}
|
||||||
|
|
||||||
|
exec(command, options, (error, stdout) => {
|
||||||
|
if (error) {
|
||||||
|
resolve({ success: false, msg: 'ping error!' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let output
|
||||||
|
if (isWin) {
|
||||||
|
output = iconv.decode(stdout, 'cp936')
|
||||||
|
} else {
|
||||||
|
output = stdout.toString()
|
||||||
|
}
|
||||||
|
// console.log('output:', output)
|
||||||
|
let match
|
||||||
|
if (isWin) {
|
||||||
|
match = output.match(/平均 = (\d+)ms/)
|
||||||
|
if (!match) {
|
||||||
|
match = output.match(/Average = (\d+)ms/)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match = output.match(/rtt min\/avg\/max\/mdev = [\d.]+\/([\d.]+)\/[\d.]+\/[\d.]+/)
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
resolve({ success: true, time: parseFloat(match[1]) })
|
||||||
|
} else {
|
||||||
|
resolve({ success: false, msg: 'Could not find time in ping output!' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getNetIPInfo,
|
getNetIPInfo,
|
||||||
throwError,
|
throwError,
|
||||||
@ -250,5 +292,6 @@ module.exports = {
|
|||||||
resolvePath,
|
resolvePath,
|
||||||
shellThrottle,
|
shellThrottle,
|
||||||
isProd,
|
isProd,
|
||||||
isAllowedIp
|
isAllowedIp,
|
||||||
|
ping
|
||||||
}
|
}
|
@ -28,6 +28,7 @@
|
|||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"global": "^4.4.0",
|
"global": "^4.4.0",
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"koa": "^2.15.3",
|
"koa": "^2.15.3",
|
||||||
"koa-body": "^6.0.1",
|
"koa-body": "^6.0.1",
|
||||||
|
@ -299,7 +299,7 @@ const formField = {
|
|||||||
password: '',
|
password: '',
|
||||||
privateKey: '',
|
privateKey: '',
|
||||||
credential: '', // credentials -> _id
|
credential: '', // credentials -> _id
|
||||||
clientPort: '22022',
|
clientPort: 22022,
|
||||||
index: 0,
|
index: 0,
|
||||||
expired: null,
|
expired: null,
|
||||||
expiredNotify: false,
|
expiredNotify: false,
|
||||||
|
@ -14,7 +14,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span style="margin-right: 10px;">{{ host }}</span>
|
<span style="margin-right: 10px;">{{ host }}</span>
|
||||||
<el-tag size="small" style="cursor: pointer;" @click="handleCopy">复制</el-tag>
|
<template v-if="pingMs">
|
||||||
|
<span class="host-ping" :style="{backgroundColor: handlePingColor(pingMs)}">{{ pingMs }}ms</span>
|
||||||
|
</template>
|
||||||
|
<el-tag size="small" style="cursor: pointer;margin-left: 15px;" @click="handleCopy">复制</el-tag>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item>
|
<el-descriptions-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
@ -22,16 +25,15 @@
|
|||||||
位置
|
位置
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<!-- <div size="small">{{ ipInfo.country || '--' }} {{ ipInfo.regionName }} {{ ipInfo.city }}</div> -->
|
|
||||||
<div size="small">{{ ipInfo.country || '--' }} {{ ipInfo.regionName }}</div>
|
<div size="small">{{ ipInfo.country || '--' }} {{ ipInfo.regionName }}</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<!-- <el-descriptions-item>
|
<!-- <el-descriptions-item v-if="pingMs">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="item-title">
|
<div class="item-title">
|
||||||
延迟
|
延迟
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span style="margin-right: 10px;" class="host-ping">{{ ping }}</span>
|
<span style="margin-right: 10px;" class="host-ping">{{ pingMs }}</span>
|
||||||
</el-descriptions-item> -->
|
</el-descriptions-item> -->
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
|
|
||||||
@ -54,7 +56,7 @@
|
|||||||
:text-inside="true"
|
:text-inside="true"
|
||||||
:stroke-width="18"
|
:stroke-width="18"
|
||||||
:percentage="cpuUsage"
|
:percentage="cpuUsage"
|
||||||
:color="handleColor(cpuUsage)"
|
:color="handleUsedColor(cpuUsage)"
|
||||||
/>
|
/>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item>
|
<el-descriptions-item>
|
||||||
@ -67,7 +69,7 @@
|
|||||||
:text-inside="true"
|
:text-inside="true"
|
||||||
:stroke-width="18"
|
:stroke-width="18"
|
||||||
:percentage="usedMemPercentage"
|
:percentage="usedMemPercentage"
|
||||||
:color="handleColor(usedMemPercentage)"
|
:color="handleUsedColor(usedMemPercentage)"
|
||||||
/>
|
/>
|
||||||
<div class="position-right">
|
<div class="position-right">
|
||||||
{{ $tools.toFixed(memInfo.usedMemMb / 1024) }}/{{ $tools.toFixed(memInfo.totalMemMb / 1024) }}G
|
{{ $tools.toFixed(memInfo.usedMemMb / 1024) }}/{{ $tools.toFixed(memInfo.totalMemMb / 1024) }}G
|
||||||
@ -83,7 +85,7 @@
|
|||||||
:text-inside="true"
|
:text-inside="true"
|
||||||
:stroke-width="18"
|
:stroke-width="18"
|
||||||
:percentage="swapPercentage"
|
:percentage="swapPercentage"
|
||||||
:color="handleColor(swapPercentage)"
|
:color="handleUsedColor(swapPercentage)"
|
||||||
/>
|
/>
|
||||||
<div class="position-right">
|
<div class="position-right">
|
||||||
{{ $tools.toFixed(swapInfo.swapUsed / 1024) }}/{{ $tools.toFixed(swapInfo.swapTotal / 1024) }}G
|
{{ $tools.toFixed(swapInfo.swapUsed / 1024) }}/{{ $tools.toFixed(swapInfo.swapTotal / 1024) }}G
|
||||||
@ -99,7 +101,7 @@
|
|||||||
:text-inside="true"
|
:text-inside="true"
|
||||||
:stroke-width="18"
|
:stroke-width="18"
|
||||||
:percentage="usedPercentage"
|
:percentage="usedPercentage"
|
||||||
:color="handleColor(usedPercentage)"
|
:color="handleUsedColor(usedPercentage)"
|
||||||
/>
|
/>
|
||||||
<div class="position-right">
|
<div class="position-right">
|
||||||
{{ driveInfo.usedGb || '--' }}/{{ driveInfo.totalGb || '--' }}G
|
{{ driveInfo.usedGb || '--' }}/{{ driveInfo.totalGb || '--' }}G
|
||||||
@ -229,18 +231,18 @@ const props = defineProps({
|
|||||||
showInputCommand: {
|
showInputCommand: {
|
||||||
required: true,
|
required: true,
|
||||||
type: Boolean
|
type: Boolean
|
||||||
|
},
|
||||||
|
pingData: {
|
||||||
|
required: true,
|
||||||
|
type: Object
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:inputCommandStyle', 'connect-sftp', 'click-input-command',])
|
const emit = defineEmits(['update:inputCommandStyle', 'connect-sftp', 'click-input-command',])
|
||||||
|
|
||||||
const socket = ref(null)
|
const socket = ref(null)
|
||||||
// const name = ref('')
|
|
||||||
const ping = ref(0)
|
|
||||||
const pingTimer = ref(null)
|
const pingTimer = ref(null)
|
||||||
// const sftpStatus = ref(false)
|
|
||||||
|
|
||||||
// const token = computed(() => $store.token)
|
|
||||||
const hostData = computed(() => props.hostInfo.monitorData || {})
|
const hostData = computed(() => props.hostInfo.monitorData || {})
|
||||||
const host = computed(() => props.hostInfo.host)
|
const host = computed(() => props.hostInfo.host)
|
||||||
const ipInfo = computed(() => hostData.value?.ipInfo || {})
|
const ipInfo = computed(() => hostData.value?.ipInfo || {})
|
||||||
@ -280,6 +282,12 @@ const inputCommandStyle = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const pingMs = computed(() => {
|
||||||
|
let curPingData = props.pingData[host.value] || {}
|
||||||
|
if (!curPingData?.success) return false
|
||||||
|
return Number(curPingData?.time).toFixed(0)
|
||||||
|
})
|
||||||
|
|
||||||
// const handleSftp = () => {
|
// const handleSftp = () => {
|
||||||
// sftpStatus.value = !sftpStatus.value
|
// sftpStatus.value = !sftpStatus.value
|
||||||
// emit('connect-sftp', sftpStatus.value)
|
// emit('connect-sftp', sftpStatus.value)
|
||||||
@ -295,23 +303,17 @@ const handleCopy = async () => {
|
|||||||
$message.success({ message: 'success', center: true })
|
$message.success({ message: 'success', center: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleColor = (num) => {
|
const handleUsedColor = (num) => {
|
||||||
if (num < 60) return '#13ce66'
|
if (num < 60) return '#13ce66'
|
||||||
if (num < 80) return '#e6a23c'
|
if (num < 80) return '#e6a23c'
|
||||||
if (num <= 100) return '#ff4949'
|
if (num <= 100) return '#ff4949'
|
||||||
}
|
}
|
||||||
|
|
||||||
// const getHostPing = () => {
|
const handlePingColor = (num) => {
|
||||||
// pingTimer.value = setInterval(() => {
|
if (num < 100) return 'rgba(19, 206, 102, 0.5)' // #13ce66
|
||||||
// $tools.ping(`http://${ props.host }:22022`)
|
if (num < 250) return 'rgba(230, 162, 60, 0.5)' // #e6a23c
|
||||||
// .then(res => {
|
return 'rgba(255, 73, 73, 0.5)' // #ff4949
|
||||||
// ping.value = res
|
}
|
||||||
// if (!import.meta.env.DEV) {
|
|
||||||
// console.warn('Please tick \'Preserve Log\'')
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }, 3000)
|
|
||||||
// }
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
socket.value && socket.value.close()
|
socket.value && socket.value.close()
|
||||||
@ -351,10 +353,9 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
.host-ping {
|
.host-ping {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 13px;
|
font-size: 10px;
|
||||||
color: #009933;
|
|
||||||
background-color: #e8fff3;
|
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分割线title
|
// 分割线title
|
||||||
|
@ -48,13 +48,14 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['inputCommand', 'cdCommand',])
|
const emit = defineEmits(['inputCommand', 'cdCommand', 'ping-data',])
|
||||||
|
|
||||||
const socket = ref(null)
|
const socket = ref(null)
|
||||||
// const commandHistoryList = ref([])
|
// const commandHistoryList = ref([])
|
||||||
const term = ref(null)
|
const term = ref(null)
|
||||||
const command = ref('')
|
const command = ref('')
|
||||||
const timer = ref(null)
|
const timer = ref(null)
|
||||||
|
const pingTimer = ref(null)
|
||||||
const fitAddon = ref(null)
|
const fitAddon = ref(null)
|
||||||
const searchBar = ref(null)
|
const searchBar = ref(null)
|
||||||
const hasRegisterEvent = ref(false)
|
const hasRegisterEvent = ref(false)
|
||||||
@ -70,6 +71,7 @@ const fontSize = computed(() => props.fontSize)
|
|||||||
const background = computed(() => props.background)
|
const background = computed(() => props.background)
|
||||||
const hostObj = computed(() => props.hostObj)
|
const hostObj = computed(() => props.hostObj)
|
||||||
const hostId = computed(() => hostObj.value.id)
|
const hostId = computed(() => hostObj.value.id)
|
||||||
|
const host = computed(() => hostObj.value.host)
|
||||||
let menuCollapse = computed(() => $store.menuCollapse)
|
let menuCollapse = computed(() => $store.menuCollapse)
|
||||||
|
|
||||||
watch(menuCollapse, () => {
|
watch(menuCollapse, () => {
|
||||||
@ -126,6 +128,7 @@ const connectIO = () => {
|
|||||||
})
|
})
|
||||||
socket.value.on('connect', () => {
|
socket.value.on('connect', () => {
|
||||||
console.log('/terminal socket已连接:', hostId.value)
|
console.log('/terminal socket已连接:', hostId.value)
|
||||||
|
|
||||||
socketConnected.value = true
|
socketConnected.value = true
|
||||||
socket.value.emit('create', { hostId: hostId.value, token: token.value })
|
socket.value.emit('create', { hostId: hostId.value, token: token.value })
|
||||||
socket.value.on('connect_terminal_success', () => {
|
socket.value.on('connect_terminal_success', () => {
|
||||||
@ -151,6 +154,14 @@ const connectIO = () => {
|
|||||||
// })
|
// })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
pingTimer.value = setInterval(() => {
|
||||||
|
socket.value.emit('get_ping', host.value)
|
||||||
|
}, 3000)
|
||||||
|
socket.value.emit('get_ping', host.value) // 获取服务端到客户端的ping值
|
||||||
|
socket.value.on('ping_data', (pingMs) => {
|
||||||
|
emit('ping-data', Object.assign({ ip: host.value }, pingMs))
|
||||||
|
})
|
||||||
|
|
||||||
socket.value.on('token_verify_fail', () => {
|
socket.value.on('token_verify_fail', () => {
|
||||||
$notification({ title: 'Error', message: 'token校验失败,请重新登录', type: 'error' })
|
$notification({ title: 'Error', message: 'token校验失败,请重新登录', type: 'error' })
|
||||||
$router.push('/login')
|
$router.push('/login')
|
||||||
@ -412,6 +423,7 @@ onMounted(async () => {
|
|||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
socket.value?.close()
|
socket.value?.close()
|
||||||
window.removeEventListener('resize', handleResize)
|
window.removeEventListener('resize', handleResize)
|
||||||
|
clearInterval(pingTimer.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
@ -104,6 +104,7 @@
|
|||||||
v-model:show-input-command="showInputCommand"
|
v-model:show-input-command="showInputCommand"
|
||||||
:host-info="curHost"
|
:host-info="curHost"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
|
:ping-data="pingData"
|
||||||
@click-input-command="clickInputCommand"
|
@click-input-command="clickInputCommand"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -138,6 +139,7 @@
|
|||||||
:font-size="terminalFontSize"
|
:font-size="terminalFontSize"
|
||||||
@input-command="terminalInput"
|
@input-command="terminalInput"
|
||||||
@cd-command="cdCommand"
|
@cd-command="cdCommand"
|
||||||
|
@ping-data="getPingData"
|
||||||
/>
|
/>
|
||||||
<Sftp
|
<Sftp
|
||||||
v-if="showSftp"
|
v-if="showSftp"
|
||||||
@ -191,6 +193,7 @@ const emit = defineEmits(['closed', 'close-all-tab', 'removeTab', 'add-host',])
|
|||||||
|
|
||||||
const showInputCommand = ref(false)
|
const showInputCommand = ref(false)
|
||||||
const infoSideRef = ref(null)
|
const infoSideRef = ref(null)
|
||||||
|
const pingData = ref({})
|
||||||
const terminalRefs = ref([])
|
const terminalRefs = ref([])
|
||||||
const sftpRefs = ref([])
|
const sftpRefs = ref([])
|
||||||
const activeTabIndex = ref(0)
|
const activeTabIndex = ref(0)
|
||||||
@ -302,6 +305,10 @@ const cdCommand = (path) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getPingData = (data) => {
|
||||||
|
pingData.value[data.ip] = data
|
||||||
|
}
|
||||||
|
|
||||||
const tabChange = async (index) => {
|
const tabChange = async (index) => {
|
||||||
await $nextTick()
|
await $nextTick()
|
||||||
const curTerminalRef = terminalRefs.value[index]
|
const curTerminalRef = terminalRefs.value[index]
|
||||||
|
@ -2796,6 +2796,13 @@ iconv-lite@0.4.24:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3"
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
|
iconv-lite@^0.6.3:
|
||||||
|
version "0.6.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||||
|
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
||||||
|
dependencies:
|
||||||
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
ieee754@^1.1.13:
|
ieee754@^1.1.13:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
@ -4022,7 +4029,7 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||||
|
|
||||||
"safer-buffer@>= 2.1.2 < 3", safer-buffer@~2.1.0:
|
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
|
Loading…
x
Reference in New Issue
Block a user