创建链接还是有问题

This commit is contained in:
lingling 2024-12-01 01:37:10 +08:00
parent 771d4223bc
commit 6f551540f0
17 changed files with 1036 additions and 409 deletions

486
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,10 @@
"@quasar/extras": "^1.0.0",
"@waiting/base64": "^4.2.9",
"axios": "^1.2.1",
"chai": "^5.1.2",
"js-base64": "^3.7.5",
"link-chang": "file:",
"mocha": "^10.8.2",
"quasar": "^2.6.0",
"vue": "^3.0.0",
"vue-router": "^4.0.0",

View File

@ -1,11 +1,9 @@
import { decode, encode } from 'js-base64'
import { getdata } from 'src/api/api';
import { vless, VlessLink, vmess } from 'src/models/models';
import { VlessLink, vmess } from 'src/models/models';
import { is_ip } from './comm';
import { vmessDefault } from 'src/config';
const is_ip = (ip: string) => {
const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
return reg.test(ip);
}
/**
* vmess
* @param ip IP地址
@ -14,8 +12,7 @@ const is_ip = (ip: string) => {
async function CreatVmessDirect(ip: string): Promise<string> {
let tmp = ''
const api = new getdata;
const def_link = 'ew0KICAidiI6ICIyIiwNCiAgInBzIjogIjAiLA0KICAiYWRkIjogIjE4NS4yMTguNi4xMDgiLA0KICAicG9ydCI6ICI5MDAwIiwNCiAgImlkIjogIjJlZTU3ODA2LWY2ZTQtNDgyYS1lZjA4LTczNjBjMDRjZDNlNSIsDQogICJhaWQiOiAiMCIsDQogICJzY3kiOiAiYXV0byIsDQogICJuZXQiOiAid3MiLA0KICAidHlwZSI6ICJub25lIiwNCiAgImhvc3QiOiAiIiwNCiAgInBhdGgiOiAiLyIsDQogICJ0bHMiOiAiIiwNCiAgInNuaSI6ICIiLA0KICAiYWxwbiI6ICIiDQp9'
const obj = JSON.parse(decode(def_link))
const obj = JSON.parse(decode(vmessDefault))
const array = ip.split(/[\s\n]/)
for (let index = 0; index < array.length; index++) {
if (!is_ip(array[index])) {
@ -40,13 +37,15 @@ function ChangVmessServer() {
*
* @param type vmess |vless
*/
function CreateLink(type: string, linkinfo: vmess | vless) {
const tmp = ''
switch (type) {
case 'vless':
linkinfo.add
function CreateLink(type: 'vmess' | 'vless', linkinfo: vmess | VlessLink) {
let tmp = ''
switch (true) {
case type === 'vless':
if ('uuid' in linkinfo) {
tmp = createVlessLink(linkinfo)
}
break;
case 'vmess':
case type === 'vmess':
break;
default:
@ -55,13 +54,8 @@ function CreateLink(type: string, linkinfo: vmess | vless) {
return tmp
}
/**
* vless
* @param link
* @returns
*/
function parseVlessLink(link: string): VlessLink | null {
const regex = /^vless:\/\/([a-f0-9-]+)@([^:]+):(\d+)(\?.*)?(#.*)?$/i;
const regex = /^vless:/;
const match = link.match(regex);
if (!match) {
@ -72,8 +66,8 @@ function parseVlessLink(link: string): VlessLink | null {
const uuid = match[1];
const host = match[2];
const port = parseInt(match[3], 10);
const params = parseParams(match[4]);
const name = match[5] ? match[5].slice(1) : undefined; // 去掉 # 符号
const params = parseParams(match[4]); // 解析参数
const name = match[5] ? decodeURIComponent(match[5].slice(1)) : undefined; // 去掉 "#" 并解码
return {
uuid,
@ -83,27 +77,20 @@ function parseVlessLink(link: string): VlessLink | null {
name,
};
}
/**
* vless携带的其他参数
* @param paramString
* @returns
*/
function parseParams(paramString: string | undefined): Record<string, string> {
if (!paramString) return {};
const params: Record<string, string> = {};
const query = paramString.slice(1); // Remove the "?" at the start
const pairs = query.split('&');
function parseParams(paramsString?: string): Record<string, string> | undefined {
if (!paramsString || !paramsString.startsWith('?')) return undefined;
pairs.forEach((pair) => {
return paramsString
.slice(1) // 去掉开头的 "?"
.split('&') // 分割每个键值对
.reduce<Record<string, string>>((acc, pair) => {
const [key, value] = pair.split('=');
if (key && value) {
params[key] = decodeURIComponent(value);
}
});
return params;
if (key) acc[key] = value || ''; // 处理可能的无值参数
return acc;
}, {});
}
/**
* vless链接
* @param param0
@ -111,7 +98,7 @@ function parseParams(paramString: string | undefined): Record<string, string> {
*/
function createVlessLink({ uuid, host, port, params, name }: VlessLink): string {
// 基本的 VLESS 链接格式
let link = `vless://${uuid}@${host}:${port}`;
let link = `vless://${uuid}@${host}:${port}\n`;
// 如果有查询参数,则拼接它们
if (params && Object.keys(params).length > 0) {
@ -121,7 +108,7 @@ function createVlessLink({ uuid, host, port, params, name }: VlessLink): string
// 如果有名称字段,将名称放在 # 后面
if (name) {
link += `#${name}`;
link += `#${encodeURIComponent(name)}`;
}
return link;

View File

@ -1,13 +1,15 @@
import { copyToClipboard, useQuasar } from 'quasar'
import { copyToClipboard, QVueGlobals, useQuasar } from 'quasar'
const $q = useQuasar()
/**
*
* @param string
*/
function copy(string: string) {
function copy(string: string, $q: QVueGlobals) {
copyToClipboard(string)
.then(() => {
// success!
$q.notify({
message: '复制成功',
@ -16,6 +18,7 @@ function copy(string: string) {
})
})
.catch(() => {
// fail
$q.notify({
message: '复制失败',
@ -28,30 +31,21 @@ function copy(string: string) {
* @param bili ms
* @returns
*/
const getColorByBaiFenBi = (bili: number) => {
//var 百分之一 = (单色值范围) / 50; 单颜色的变化范围只在50%之内
const one = (255 + 255) / 100;
let r = 0;
let g = 0;
let b = 0;
function getColorForDelay(delay: number): string {
// 限制延迟在200到2000之间
const clampedDelay = Math.min(Math.max(delay, 200), 2000);
if (bili < 50) {
// 比例小于50的时候红色是越来越多的,直到红色为255时(红+绿)变为黄色.
r = one * bili;
g = 255;
}
if (bili >= 50) {
// 比例大于50的时候绿色是越来越少的,直到0 变为纯红
g = 255 - ((bili - 50) * one);
r = 255;
}
r = Math.round(r);// 取整
g = Math.round(g);// 取整
b = Math.round(b);// 取整
// 将延迟从[200, 2000]映射到[0, 1]
const normalizedDelay = (clampedDelay - 200) / (2000 - 200);
return 'rgb(' + r + ',' + g + ',' + b + ')';
// 计算从绿色到红色的颜色变化
const green = 255 - normalizedDelay * 255;
const red = normalizedDelay * 255;
// 返回 RGB 颜色格式
return `rgb(${Math.round(red)}, ${Math.round(green)}, 0)`;
}
/**
*
* @param bili
@ -68,5 +62,21 @@ function signal_style(bili: number) {
}
return tmp
}
const is_ip = (ip: string) => {
const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
return reg.test(ip);
}
function extractIPv4(ip: string): string | null {
const ipv4Regex = /(\b25[0-5]\b|\b2[0-4][0-9]\b|\b[01]?[0-9][0-9]?\b)\.(\b25[0-5]\b|\b2[0-4][0-9]\b|\b[01]?[0-9][0-9]?\b)\.(\b25[0-5]\b|\b2[0-4][0-9]\b|\b[01]?[0-9][0-9]?\b)\.(\b25[0-5]\b|\b2[0-4][0-9]\b|\b[01]?[0-9][0-9]?\b)/g;
const matches = ip.match(ipv4Regex);
export { copy, getColorByBaiFenBi, signal_style }
// 如果没有匹配到任何IPv4地址返回 null
if (!matches) {
return null;
}
// 返回第一个匹配到的IPv4地址
return matches[0];
}
export { copy, getColorForDelay, signal_style, is_ip, extractIPv4 }

152
src/Util/node/Vless.ts Normal file
View File

@ -0,0 +1,152 @@
import { Base64 } from 'js-base64';
class VLESSQuery {
constructor(
public security: string,
public alpn: string[],
public sni: string,
public fp: string,
public sid: string,
public pbk: string,
public flow: string,
public encryption: string,
public type: string,
public headerType: string,
public path: string,
public host: string
) { }
}
class VLESS {
constructor(
public name: string,
public uuid: string,
public server: string,
public port: number,
public query: VLESSQuery
) { }
// Base64 解码函数
// private static base64Decode(str: string): string {
// return Buffer.from(str, 'base64').toString('utf-8');
// }
// 编码 VLESS URL
encodeURL(): string {
const url = new URL(`vless://${this.uuid}@${this.server}:${this.port}`);
// 设置 Query 参数
const query = url.searchParams;
query.set('security', this.query.security);
query.set('sni', this.query.sni);
query.set('fp', this.query.fp);
query.set('sid', this.query.sid);
query.set('pbk', this.query.pbk);
query.set('flow', this.query.flow);
query.set('encryption', this.query.encryption);
query.set('type', this.query.type);
query.set('headerType', this.query.headerType);
query.set('path', this.query.path);
query.set('host', this.query.host);
// 移除空值参数
for (const [key, value] of query) {
if (value === '') {
query.delete(key);
}
}
// 如果有 name设置为 Fragment
if (this.name) {
url.hash = this.name;
} else {
url.hash = `${this.server}:${this.port}`;
}
return url.toString();
}
// 解码 VLESS URL
static decodeURL(urlStr: string): VLESS {
if (!urlStr.startsWith('vless://')) {
throw new Error(`Invalid vless URL: ${urlStr}`);
}
const decodedUrl = urlStr.split('@');
const url = new URL(`http://${decodedUrl[1]}`);
const regex = /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/;
const match = urlStr.match(regex);
const uuid = match[0];
const hostname = url.hostname;
const port = parseInt(url.port, 10);
const query = url.searchParams;
const encryption = query.get('encryption') || '';
const security = query.get('security') || '';
const type = query.get('type') || '';
const flow = query.get('flow') || '';
const headerType = query.get('headerType') || '';
const pbk = query.get('pbk') || '';
const sid = query.get('sid') || '';
const fp = query.get('fp') || '';
const alpns = query.get('alpn') || '';
const alpn = alpns ? alpns.split(',') : [];
const sni = query.get('sni') || '';
const path = query.get('path') || '';
const host = query.get('host') || '';
// 获取 name若为空则使用 `hostname:port`
const name = url.hash ? decodeURIComponent(url.hash.slice(1)) : `${hostname}:${port}`;
const queryObj = new VLESSQuery(
security,
alpn,
sni,
fp,
sid,
pbk,
flow,
encryption,
type,
headerType,
path,
host
);
return new VLESS(name, uuid, hostname, port, queryObj);
}
}
// // 示例用法
// function callVLESS() {
// const vless = new VLESS(
// 'Sharon-香港',
// '6adb4f43-9813-45f4-abf8-772be7db08sd',
// 'ss.com',
// 443,
// new VLESSQuery(
// 'reality',
// ['http/1.1'],
// 'ss.com',
// 'chrome',
// '',
// 'g-oxbqigzCaXqARxuyD2_vbTYeMD9zn8wnTo02S69QM',
// 'xtls-rprx-vision',
// 'none',
// 'tcp',
// 'none',
// '',
// ''
// )
// );
// const encoded = vless.encodeURL();
// console.log('Encoded VLESS URL:', encoded);
// const decoded = VLESS.decodeURL(encoded);
// console.log('Decoded VLESS:', decoded);
// }
// callVLESS();
export { VLESS }

122
src/Util/node/Vmess.ts Normal file
View File

@ -0,0 +1,122 @@
class Vmess {
add?: string;
aid?: any; // This could be number or string depending on usage
alpn?: string;
fp?: string;
host?: string;
id?: string;
net?: string;
path?: string;
port?: any; // This could be a number or string
ps?: string;
scy?: string;
sni?: string;
tls?: string;
type?: string;
v?: string;
constructor(data: {
add?: string;
aid?: any;
alpn?: string;
fp?: string;
host?: string;
id?: string;
net?: string;
path?: string;
port?: any;
ps?: string;
scy?: string;
sni?: string;
tls?: string;
type?: string;
v?: string;
}) {
this.add = data.add;
this.aid = data.aid;
this.alpn = data.alpn;
this.fp = data.fp;
this.host = data.host;
this.id = data.id;
this.net = data.net;
this.path = data.path;
this.port = data.port;
this.ps = data.ps;
this.scy = data.scy;
this.sni = data.sni;
this.tls = data.tls;
this.type = data.type;
this.v = data.v;
}
// 编码 Vmess URL
encodeURL(): string {
// 如果备注为空,则使用服务器地址 + 端口
if (!this.ps) {
this.ps = `${this.add}:${this.port}`;
}
// 如果版本为空,则默认为 2
if (!this.v) {
this.v = '2';
}
const param = JSON.stringify(this);
return 'vmess://' + this.base64Encode(param);
}
// 解码 Vmess URL
static decodeURL(url: string): Vmess {
if (!url.startsWith('vmess://')) {
throw new Error(`Invalid vmess URL: ${url}`);
}
const param = url.slice(8); // Remove "vmess://"
const decoded = Vmess.base64Decode(param.trim());
try {
const parsed = JSON.parse(decoded);
if (parsed.scy === '') {
parsed.scy = 'auto';
}
if (!parsed.ps) {
parsed.ps = parsed.add + ':' + parsed.port;
}
return new Vmess(parsed);
} catch (error) {
throw new Error(`Failed to parse VMESS URL: ${error}`);
}
}
// Base64 编码
private base64Encode(str: string): string {
return Buffer.from(str, 'utf-8').toString('base64');
}
// Base64 解码
private static base64Decode(str: string): string {
return Buffer.from(str, 'base64').toString('utf-8');
}
}
// 开发者测试
function callVmessURL() {
const vmess = new Vmess({
add: 'xx.xxx.ru',
port: '2095',
aid: 0,
scy: 'auto',
net: 'ws',
type: 'none',
id: '7a737f41-b792-4260-94ff-3d864da67380',
host: 'xx.xxx.ru',
path: '/',
tls: ''
});
const encoded = vmess.encodeURL();
console.log('Encoded VMESS URL:', encoded);
const decoded = Vmess.decodeURL(encoded);
console.log('Decoded VMESS:', decoded);
}
callVmessURL();

View File

@ -17,12 +17,13 @@ class getdata {
ip,
});
res = res.data.country
return res
if (typeof (res) == 'string') { return res }
return ''
}
async get_server_ms(ip: string, port: number, to_ip: string, istls: number) {
const http = istls == 0 ? 'http' : 'https'
const res = await this.text_server(`${http}://${ip}:${port}/${to_ip}`)
return res
return this.text_server(`${http}://${ip}:${port}/${to_ip}`)
}
}

View File

@ -1,49 +0,0 @@
<template>
<q-item
clickable
tag="a"
target="_blank"
:href="link"
>
<q-item-section
v-if="icon"
avatar
>
<q-icon :name="icon" />
</q-item-section>
<q-item-section>
<q-item-label>{{ title }}</q-item-label>
<q-item-label caption>{{ caption }}</q-item-label>
</q-item-section>
</q-item>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'EssentialLink',
props: {
title: {
type: String,
required: true
},
caption: {
type: String,
default: ''
},
link: {
type: String,
default: '#'
},
icon: {
type: String,
default: ''
}
}
});
</script>

View File

@ -1,64 +0,0 @@
<template>
<div>
<p>{{ title }}</p>
<ul>
<li v-for="todo in todos" :key="todo.id" @click="increment">
{{ todo.id }} - {{ todo.content }}
</li>
</ul>
<p>Count: {{ todoCount }} / {{ meta.totalCount }}</p>
<p>Active: {{ active ? 'yes' : 'no' }}</p>
<p>Clicks on todos: {{ clickCount }}</p>
</div>
</template>
<script lang="ts">
import {
defineComponent,
PropType,
computed,
ref,
toRef,
Ref,
} from 'vue';
import { Todo, Meta } from '../models/models';
function useClickCount() {
const clickCount = ref(0);
function increment() {
clickCount.value += 1
return clickCount.value;
}
return { clickCount, increment };
}
function useDisplayTodo(todos: Ref<Todo[]>) {
const todoCount = computed(() => todos.value.length);
return { todoCount };
}
export default defineComponent({
name: 'ExampleComponent',
props: {
title: {
type: String,
required: true
},
todos: {
type: Array as PropType<Todo[]>,
default: () => []
},
meta: {
type: Object as PropType<Meta>,
required: true
},
active: {
type: Boolean
}
},
setup(props) {
return { ...useClickCount(), ...useDisplayTodo(toRef(props, 'todos')) };
},
});
</script>

View File

@ -19,11 +19,13 @@ import {
defineComponent,
computed,
ref,
onMounted,
} from 'vue';
import { copyToClipboard } from 'quasar'
import { encode, decode } from 'js-base64';
import { useQuasar } from 'quasar'
import { getdata } from 'src/api/api'
import { copy, extractIPv4, getColorForDelay } from 'src/Util/comm';
import { vlessLink } from 'src/config';
import { getdata } from 'src/api/api';
import { CreateLink } from 'src/Util/Link';
export default defineComponent({
name: 'LinkItem',
props: {
@ -31,31 +33,42 @@ export default defineComponent({
type: Object,
required: true
},
text: {
type: String
names: {
type: Array as () => string[],
required: true
}
},
setup(props) {
const online = ref(false);
const api = new getdata;
const $q = useQuasar()
const time = ref(0)
const outtext = ref('')
const api = new getdata;
const signal_style = computed(() => {
let tmp = ''
if (time.value >= 0 && time.value <= 700) {
tmp = 'green'
} else if (time.value > 700 && time.value < 1400) {
tmp = '#FF9800'
} else {
tmp = 'red'
}
return tmp
return getColorForDelay(time.value)
})
onMounted(() => {
for (let index = 0; index < props.names.length; index++) {
let ip = extractIPv4(props.names[index])
if (ip == null) { continue }
let vless = vlessLink
vless.name = props.names[index]
vless.host = props.serve.host
vless.port = props.serve.port
if (props.serve.istls == 1 && vless.params) {
vless.params.security = 'tls'
}
api.get_server_ms(props.serve.host, props.serve.port, ip, props.serve.istls).then((res) => {
console.log(res)
time.value = res.time
online.value = res.is_online
})
const copy_link = () => { let tmp = 0 }
outtext.value += CreateLink('vless', vless)
}
})
const copy_link = () => { copy(outtext.value, $q) }
return { props, online, time, signal_style, outtext, copy_link };
},
});

View File

@ -1,9 +1,8 @@
<template>
<div class="row">
<div class="col-12">
<h6 style="text-align: center;margin: 1rem;">{{ props.serve.tips }} <q-icon v-show="online" title="在线"
name="check_circle_outline" style="color: green;" /> <q-icon v-show="!online" title="离线" name="highlight_off"
style="color: red;" /></h6>
<h6 style="text-align: center;margin: 1rem;">直连<q-icon v-show="online" title="在线" name="check_circle_outline"
style="color: green;" /> <q-icon v-show="!online" title="离线" name="highlight_off" style="color: red;" /></h6>
<div v-show="online" style="text-align: center;"><q-icon title="在线" name="signal_cellular_alt"
:style="{ color: signal_style }" /><span>{{ time }}ms</span></div>
<q-input v-model="outtext" filled autogrow readonly />
@ -19,20 +18,19 @@ import {
defineComponent,
computed,
ref,
onMounted,
} from 'vue';
import { copyToClipboard } from 'quasar'
import { encode, decode } from 'js-base64';
import { useQuasar } from 'quasar'
import { getdata } from 'src/api/api'
import { vlessLink } from 'src/config';
import { copy, extractIPv4, getColorForDelay } from 'src/Util/comm';
import { CreateLink } from 'src/Util/Link';
export default defineComponent({
name: 'LinkItem',
props: {
serve: {
type: Object,
names: {
type: Array as () => string[],
required: true
},
text: {
type: String
}
},
setup(props) {
@ -43,19 +41,34 @@ export default defineComponent({
const outtext = ref('')
const signal_style = computed(() => {
let tmp = ''
if (time.value >= 0 && time.value <= 700) {
tmp = 'green'
} else if (time.value > 700 && time.value < 1400) {
tmp = '#FF9800'
} else {
tmp = 'red'
}
return tmp
// let tmp = ''
// if (time.value >= 0 && time.value <= 700) {
// tmp = 'green'
// } else if (time.value > 700 && time.value < 1400) {
// tmp = '#FF9800'
// } else {
// tmp = 'red'
// }
return getColorForDelay(time.value)
})
onMounted(() => {
for (let index = 0; index < props.names.length; index++) {
let ip = extractIPv4(props.names[index])
if (ip == null) { continue }
let vless = vlessLink
const copy_link = () => { let tmp = 0 }
vless.name = props.names[index]
vless.host = ip
api.get_server_ms(ip, 9000, ip, 0).then((res) => {
console.log(res)
time.value = res.time
online.value = res.is_online
})
outtext.value += CreateLink('vless', vless)
}
})
const copy_link = () => { copy(outtext.value, $q) }
return { props, online, time, signal_style, outtext, copy_link };
},
});

23
src/config/index.ts Normal file
View File

@ -0,0 +1,23 @@
import { VlessLink } from 'src/models/models';
/**
* vmess模板链接
*/
const vmessDefault = 'ew0KICAidiI6ICIyIiwNCiAgInBzIjogIjAiLA0KICAiYWRkIjogIjE4NS4yMTguNi4xMDgiLA0KICAicG9ydCI6ICI5MDAwIiwNCiAgImlkIjogIjJlZTU3ODA2LWY2ZTQtNDgyYS1lZjA4LTczNjBjMDRjZDNlNSIsDQogICJhaWQiOiAiMCIsDQogICJzY3kiOiAiYXV0byIsDQogICJuZXQiOiAid3MiLA0KICAidHlwZSI6ICJub25lIiwNCiAgImhvc3QiOiAiIiwNCiAgInBhdGgiOiAiLyIsDQogICJ0bHMiOiAiIiwNCiAgInNuaSI6ICIiLA0KICAiYWxwbiI6ICIiDQp9'
const vlessDefault = 'vless://2ee57806-f6e4-482a-ef08-7360c04cd3e5@1.1.1.1:9000?encryption=none&security=none&type=ws&path=%2F#%E9%9F%A9%E5%9B%BD1.1.1.1'
/**
* vless对象模板
*/
const vlessLink: VlessLink = {
uuid: '2ee57806-f6e4-482a-ef08-7360c04cd3e5',
host: '150.109.81.208',
port: 9000,
params: {
encryption: 'none',
security: 'none',
type: 'ws',
path: '/'
},
name: '韩国150.109.81.208'
};
export { vmessDefault, vlessDefault, vlessLink }

View File

@ -42,7 +42,7 @@ export interface vmess {
export interface vless {
add: string;
port: number;
id: string;
uuid: string;
encryption: string;
/**传输协议 */
net: string;

View File

@ -7,7 +7,7 @@
<q-input v-model="text" filled autogrow placeholder="IP" />
<div style="height:1rem"></div>
<q-input v-model="outlink" filled autogrow />
<q-btn color="white" text-color="black" @click="copy" label="复制" />
<q-btn color="white" text-color="black" @click="copy_link" label="复制" />
</div>
</div>
</div>
@ -19,69 +19,44 @@
<script lang="ts">
import { defineComponent, ref, watch } from 'vue';
import { getdata } from 'src/api/api'
import { decode, encode } from 'js-base64';
import { copyToClipboard, useQuasar } from 'quasar';
import { copy, is_ip } from 'src/Util/comm';
import { CreateLink, CreatVmessDirect } from 'src/Util/Link';
import { useQuasar } from 'quasar';
import { vlessLink } from 'src/config';
import { getdata } from 'src/api/api';
export default defineComponent({
name: 'CreateLink',
setup() {
const $q = useQuasar()
const api = new getdata;
const text = ref('');
const outlink = ref('');
const def_link = 'ew0KICAidiI6ICIyIiwNCiAgInBzIjogIjAiLA0KICAiYWRkIjogIjE4NS4yMTguNi4xMDgiLA0KICAicG9ydCI6ICI5MDAwIiwNCiAgImlkIjogIjJlZTU3ODA2LWY2ZTQtNDgyYS1lZjA4LTczNjBjMDRjZDNlNSIsDQogICJhaWQiOiAiMCIsDQogICJzY3kiOiAiYXV0byIsDQogICJuZXQiOiAid3MiLA0KICAidHlwZSI6ICJub25lIiwNCiAgImhvc3QiOiAiIiwNCiAgInBhdGgiOiAiLyIsDQogICJ0bHMiOiAiIiwNCiAgInNuaSI6ICIiLA0KICAiYWxwbiI6ICIiDQp9'
const is_ip = (ip: string) => {
var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
return reg.test(ip);
}
const $q = useQuasar()
const api = new getdata();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
watch(() => text.value, (newValue, oldValue) => { //
let obj = JSON.parse(decode(def_link))
watch(() => text.value, async (newValue, oldValue) => { //
let array = newValue.split(/[\s\n]/)
for (let index = 0; index < array.length; index++) {
if (!is_ip(array[index])) {
outlink.value = 'erroe ip'
return
}
}
outlink.value = ''
for (let index = 0; index < array.length; index++) {
api.get_country(array[index]).then(res => {
// let name = res.data.country == '' ? res.data.province : res.data.country
let name = res.data.country
obj.ps = name + array[index]
obj.add = array[index]
outlink.value += 'vmess://' + encode(JSON.stringify(obj)) + '\n'
})
// outlink.value += await CreatVmessDirect(array[index])
let vless = vlessLink
let country = await api.get_country(array[index])
vless.name = country + array[index]
vless.host = array[index]
outlink.value += CreateLink('vless', vless) + '\n'
}
})
const copy_link = () => { copy(outlink.value, $q) }
return {
text,
outlink,
copy() {
copyToClipboard(outlink.value)
.then(() => {
// success!
$q.notify({
message: '复制成功',
color: 'positive',
position: 'top'
})
})
.catch(() => {
// fail
$q.notify({
message: '复制失败',
color: 'negative'
})
})
}
copy_link
};
}

View File

@ -24,30 +24,6 @@
</q-card-section>
</q-card>
</div>
<!-- <div class="col-sm-8 col-md-4 col-lg-2 col-xl-1 q-pa-md">
<q-card class="my-card">
<img class="rounded-full q-pa-md" src="img/v2rayng.png">
<q-card-section class="text-center">
<div class="text-h6 text-center">v2ray</div>
<q-btn color="positive">
<q-icon left name="file_download" />
<div>安卓手机</div>
</q-btn>
<q-btn class="q-ma-md" color="positive">
<q-icon left name="file_download" />
<div>模拟器</div>
</q-btn>
<q-btn color="positive">
<q-icon left name="file_download" />
<div>PC</div>
</q-btn>
</q-card-section>
<q-card-section class="q-pt-none">
</q-card-section>
</q-card>
</div> -->
</div>
</template>
@ -72,9 +48,6 @@ export default defineComponent({
// eslint-disable-next-line vue/multi-word-component-names
name: 'Download',
setup() {
return {
array,
dow(url: string) {

View File

@ -13,13 +13,13 @@
<div class="row">
<div class="col-xs-1 col-md-4"></div>
<div class="col-xs-10 col-md-4">
<OriginalLinkItem v-model:text="text"></OriginalLinkItem>
<OriginalLinkItem :names="names"></OriginalLinkItem>
</div>
</div>
<div class="row" v-for="(item, index) in serve" :key="index">
<div class="row" v-for="(item, index) in serves" :key="index">
<div class="col-xs-1 col-md-4"></div>
<div class="col-xs-10 col-md-4">
<LinkItem :serve="item" v-model:text="text"></LinkItem>
<LinkItem :serve="item" v-model:names="names"></LinkItem>
</div>
</div>
</div>
@ -34,42 +34,46 @@ import { computed, defineComponent, onMounted, ref } from 'vue';
import { getdata } from 'src/api/api'
import LinkItem from 'components/LinkItem.vue';
import OriginalLinkItem from 'components/OriginalLinkItem.vue';
import { decode } from 'js-base64';
import { VLESS } from 'src/Util/node/Vless';
export default defineComponent({
name: 'IndexPage',
components: { LinkItem, OriginalLinkItem },
setup() {
const serve = ref(<server[]>[])
const serves = ref(<server[]>[])
const api = new getdata;
const text = ref('');
const online = ref(false);
const names = ref(<string[]>[])
onMounted(() => {
api.get_server().then((res) => {
for (let index = 0; index < res.data.length; index++) {
serve.value.push(res.data[index]);
serves.value.push(res.data[index]);
}
})
})
const isobj = computed(() => {
try {
if (text.value.length <= 0) {
return false
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
let texttmp = text.value!.replace(/\ +/g, '');
texttmp = texttmp.replace(/[\r\n]/g, '');
let arr = texttmp.split('vmess://');
let arr = texttmp.split('vless://');
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
names.value = [];
for (let iterator of arr) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
online.value = false
if (iterator.length > 0) {
let obj = JSON.parse(decode(iterator));
if (obj.id != '2ee57806-f6e4-482a-ef08-7360c04cd3e5' || obj.net != 'ws') {
// let tmp = parseVlessLink(iterator)
let tmp = VLESS.decodeURL('vless://' + iterator);
if (!(tmp != null && tmp.uuid == '2ee57806-f6e4-482a-ef08-7360c04cd3e5')) {
return false
}
let reg = new RegExp(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
let ip = obj.ps.match(reg)[0];
isonline(ip)
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
if (tmp.name) { names.value.push(tmp.name) }
}
}
@ -80,16 +84,12 @@ export default defineComponent({
return true
})
const isonline = (ip: string) => {
api.text_server(`http://${ip}:9000/`).then(res => {
online.value = res.data.sataus == 400
})
}
return {
serve,
serves,
text,
isobj,
online
online,
names
};
}
});

185
yarn.lock
View File

@ -777,6 +777,11 @@ ajv@^8.0.1:
require-from-string "^2.0.2"
uri-js "^4.2.2"
ansi-colors@^4.1.3:
version "4.1.3"
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz"
integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==
ansi-escapes@^4.2.1:
version "4.3.2"
resolved "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz"
@ -848,6 +853,11 @@ array-union@^2.1.0:
resolved "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
assertion-error@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz"
integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==
astral-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz"
@ -953,6 +963,11 @@ braces@^3.0.2, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
browser-stdout@^1.3.1:
version "1.3.1"
resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz"
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
browserslist@^4.21.5, browserslist@^4.24.0, "browserslist@>= 4.21.0":
version "4.24.2"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz"
@ -1007,11 +1022,27 @@ camel-case@^3.0.0:
no-case "^2.2.0"
upper-case "^1.1.1"
camelcase@^6.0.0:
version "6.3.0"
resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001669:
version "1.0.30001684"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz"
integrity sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==
chai@^5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz"
integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==
dependencies:
assertion-error "^2.0.1"
check-error "^2.1.1"
deep-eql "^5.0.1"
loupe "^3.1.0"
pathval "^2.0.0"
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1:
version "4.1.2"
resolved "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz"
@ -1025,6 +1056,11 @@ chardet@^0.7.0:
resolved "https://registry.npmmirror.com/chardet/-/chardet-0.7.0.tgz"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
check-error@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz"
integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
chokidar@^3.5.3, "chokidar@>=3.0.0 <4.0.0":
version "3.5.3"
resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz"
@ -1069,6 +1105,15 @@ cli-width@^3.0.0:
resolved "https://registry.npmmirror.com/cli-width/-/cli-width-3.0.0.tgz"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz"
integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
wrap-ansi "^7.0.0"
cliui@^8.0.1:
version "8.0.1"
resolved "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz"
@ -1222,6 +1267,13 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
dependencies:
ms "2.1.2"
debug@^4.3.5:
version "4.3.7"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz"
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
dependencies:
ms "^2.1.3"
debug@2.6.9:
version "2.6.9"
resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz"
@ -1229,6 +1281,16 @@ debug@2.6.9:
dependencies:
ms "2.0.0"
decamelize@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz"
integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
deep-eql@^5.0.1:
version "5.0.2"
resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz"
integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
deep-is@^0.1.3:
version "0.1.4"
resolved "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz"
@ -1261,6 +1323,11 @@ destroy@1.2.0:
resolved "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
diff@^5.2.0:
version "5.2.0"
resolved "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz"
integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz"
@ -1702,6 +1769,11 @@ flat-cache@^3.0.4:
flatted "^3.1.0"
rimraf "^3.0.2"
flat@^5.0.2:
version "5.0.2"
resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
flatted@^3.1.0:
version "3.2.7"
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz"
@ -1810,6 +1882,17 @@ glob@^7.1.3, glob@^7.1.4:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^8.1.0:
version "8.1.0"
resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^5.0.1"
once "^1.3.0"
globals@^11.1.0:
version "11.12.0"
resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz"
@ -2020,6 +2103,11 @@ is-path-inside@^3.0.3:
resolved "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz"
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
is-plain-obj@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz"
@ -2162,8 +2250,10 @@ levn@^0.4.1:
"@quasar/extras" "^1.0.0"
"@waiting/base64" "^4.2.9"
axios "^1.2.1"
chai "^5.1.2"
js-base64 "^3.7.5"
link-chang "file:"
mocha "^10.8.2"
quasar "^2.6.0"
vue "^3.0.0"
vue-router "^4.0.0"
@ -2224,6 +2314,11 @@ log-symbols@^4.1.0:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
loupe@^3.1.0:
version "3.1.2"
resolved "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz"
integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==
lower-case@^1.1.1:
version "1.1.4"
resolved "https://registry.npmmirror.com/lower-case/-/lower-case-1.1.4.tgz"
@ -2312,7 +2407,7 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
dependencies:
brace-expansion "^1.1.7"
minimatch@^5.0.1:
minimatch@^5.0.1, minimatch@^5.1.6:
version "5.1.6"
resolved "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz"
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
@ -2331,6 +2426,37 @@ minimist@^1.2.6:
resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
mocha@^10.8.2:
version "10.8.2"
resolved "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz"
integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==
dependencies:
ansi-colors "^4.1.3"
browser-stdout "^1.3.1"
chokidar "^3.5.3"
debug "^4.3.5"
diff "^5.2.0"
escape-string-regexp "^4.0.0"
find-up "^5.0.0"
glob "^8.1.0"
he "^1.2.0"
js-yaml "^4.1.0"
log-symbols "^4.1.0"
minimatch "^5.1.6"
ms "^2.1.3"
serialize-javascript "^6.0.2"
strip-json-comments "^3.1.1"
supports-color "^8.1.1"
workerpool "^6.5.1"
yargs "^16.2.0"
yargs-parser "^20.2.9"
yargs-unparser "^2.0.0"
ms@^2.1.3, ms@2.1.3:
version "2.1.3"
resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz"
@ -2341,11 +2467,6 @@ ms@2.1.2:
resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
ms@2.1.3:
version "2.1.3"
resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
mute-stream@0.0.8:
version "0.0.8"
resolved "https://registry.npmmirror.com/mute-stream/-/mute-stream-0.0.8.tgz"
@ -2552,6 +2673,11 @@ path-type@^4.0.0:
resolved "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
pathval@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz"
integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==
picocolors@^1.0.0, picocolors@^1.1.0:
version "1.1.1"
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"
@ -2865,6 +2991,13 @@ serialize-javascript@^6.0.0:
dependencies:
randombytes "^2.1.0"
serialize-javascript@^6.0.2:
version "6.0.2"
resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz"
integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==
dependencies:
randombytes "^2.1.0"
serve-static@1.15.0:
version "1.15.0"
resolved "https://registry.npmmirror.com/serve-static/-/serve-static-1.15.0.tgz"
@ -2999,6 +3132,13 @@ supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
supports-color@^8.1.1:
version "8.1.1"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
dependencies:
has-flag "^4.0.0"
supports-preserve-symlinks-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
@ -3234,6 +3374,11 @@ word-wrap@^1.2.3:
resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
workerpool@^6.5.1:
version "6.5.1"
resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz"
integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
@ -3268,11 +3413,39 @@ yallist@^4.0.0:
resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yargs-parser@^20.2.2, yargs-parser@^20.2.9:
version "20.2.9"
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
yargs-parser@^21.1.1:
version "21.1.1"
resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz"
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
yargs-unparser@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz"
integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==
dependencies:
camelcase "^6.0.0"
decamelize "^4.0.0"
flat "^5.0.2"
is-plain-obj "^2.1.0"
yargs@^16.2.0:
version "16.2.0"
resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz"
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
dependencies:
cliui "^7.0.2"
escalade "^3.1.1"
get-caller-file "^2.0.5"
require-directory "^2.1.1"
string-width "^4.2.0"
y18n "^5.0.5"
yargs-parser "^20.2.2"
yargs@^17.5.1:
version "17.7.1"
resolved "https://registry.npmmirror.com/yargs/-/yargs-17.7.1.tgz"