添加websocket示例
This commit is contained in:
parent
8762ced5f8
commit
b7efe81e4c
@ -17,6 +17,7 @@
|
|||||||
"@pixi/graphics-extras": "^7.2.4",
|
"@pixi/graphics-extras": "^7.2.4",
|
||||||
"@quasar/extras": "^1.0.0",
|
"@quasar/extras": "^1.0.0",
|
||||||
"@stomp/stompjs": "^7.0.0",
|
"@stomp/stompjs": "^7.0.0",
|
||||||
|
"axios": "^1.4.0",
|
||||||
"google-protobuf": "^3.21.2",
|
"google-protobuf": "^3.21.2",
|
||||||
"js-base64": "^3.7.5",
|
"js-base64": "^3.7.5",
|
||||||
"pinia": "^2.0.11",
|
"pinia": "^2.0.11",
|
||||||
|
@ -28,7 +28,7 @@ module.exports = configure(function (/* ctx */) {
|
|||||||
// app boot file (/src/boot)
|
// app boot file (/src/boot)
|
||||||
// --> boot files are part of "main.js"
|
// --> boot files are part of "main.js"
|
||||||
// https://v2.quasar.dev/quasar-cli-vite/boot-files
|
// https://v2.quasar.dev/quasar-cli-vite/boot-files
|
||||||
boot: ['@pixi/graphics-extras'],
|
boot: ['axios', '@pixi/graphics-extras'],
|
||||||
|
|
||||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
||||||
css: ['app.scss'],
|
css: ['app.scss'],
|
||||||
|
111
src/boot/axios.ts
Normal file
111
src/boot/axios.ts
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import axios, { AxiosInstance } from 'axios';
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
|
import { Dialog } from 'quasar';
|
||||||
|
import { boot } from 'quasar/wrappers';
|
||||||
|
import { getJwtToken } from 'src/examples/app/configs/TokenManage';
|
||||||
|
import { getHttpBase } from 'src/examples/app/configs/UrlManage';
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
interface ComponentCustomProperties {
|
||||||
|
$axios: AxiosInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ErrorData {
|
||||||
|
status: number;
|
||||||
|
title: string;
|
||||||
|
detail: string;
|
||||||
|
code: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApiError {
|
||||||
|
origin: AxiosError;
|
||||||
|
/**
|
||||||
|
* 业务错误代码
|
||||||
|
*/
|
||||||
|
code: number;
|
||||||
|
/**
|
||||||
|
* 错误信息
|
||||||
|
*/
|
||||||
|
title: string;
|
||||||
|
/**
|
||||||
|
* 相关问题描述
|
||||||
|
*/
|
||||||
|
detail?: string;
|
||||||
|
constructor(origin: AxiosError<unknown, unknown>) {
|
||||||
|
this.origin = origin;
|
||||||
|
const response = origin.response;
|
||||||
|
if (response) {
|
||||||
|
const err = response.data as ErrorData;
|
||||||
|
this.code = err.code;
|
||||||
|
this.title = err.title;
|
||||||
|
this.detail = err.detail;
|
||||||
|
} else {
|
||||||
|
this.code = origin.status || -1;
|
||||||
|
this.title = origin.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static from(err: AxiosError<unknown, unknown>): ApiError {
|
||||||
|
return new ApiError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否认证失败(登录过期)
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
isAuthError(): boolean {
|
||||||
|
return this.origin.response?.status === 401;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Be careful when using SSR for cross-request state pollution
|
||||||
|
// due to creating a Singleton instance here;
|
||||||
|
// If any client changes this (global) instance, it might be a
|
||||||
|
// good idea to move this instance creation inside of the
|
||||||
|
// "export default () => {}" function below (which runs individually
|
||||||
|
// for each client)
|
||||||
|
const api = axios.create({ baseURL: getHttpBase() });
|
||||||
|
|
||||||
|
export default boot(({ app, router }) => {
|
||||||
|
// for use inside Vue files (Options API) through this.$axios and this.$api
|
||||||
|
|
||||||
|
// 拦截请求,添加
|
||||||
|
api.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
config.headers.Authorization = getJwtToken();
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(err: AxiosError) => {
|
||||||
|
return Promise.reject(ApiError.from(err));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
api.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
if (err.response && err.response.status === 401) {
|
||||||
|
Dialog.create({
|
||||||
|
title: '认证失败',
|
||||||
|
message: '认证失败或登录超时,请重新登录',
|
||||||
|
persistent: true,
|
||||||
|
}).onOk(() => {
|
||||||
|
router.push({ name: 'login' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.reject(ApiError.from(err));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
app.config.globalProperties.$axios = axios;
|
||||||
|
// ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
|
||||||
|
// so you won't necessarily have to import axios in each vue file
|
||||||
|
|
||||||
|
app.config.globalProperties.$api = api;
|
||||||
|
// ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
|
||||||
|
// so you can easily perform requests against your app's API
|
||||||
|
});
|
||||||
|
|
||||||
|
export { api };
|
13
src/examples/app/configs/TokenManage.ts
Normal file
13
src/examples/app/configs/TokenManage.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const JwtTokenKey = 'jwttoken';
|
||||||
|
|
||||||
|
export function saveJwtToken(token: string) {
|
||||||
|
sessionStorage.setItem(JwtTokenKey, `Bearer ${token}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getJwtToken(): string | null {
|
||||||
|
return sessionStorage.getItem(JwtTokenKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearJwtToken(): void {
|
||||||
|
sessionStorage.removeItem(JwtTokenKey);
|
||||||
|
}
|
13
src/examples/app/configs/UrlManage.ts
Normal file
13
src/examples/app/configs/UrlManage.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
function getHost(): string {
|
||||||
|
// return '192.168.3.7:9081';
|
||||||
|
// return '192.168.3.47:9081';
|
||||||
|
return '192.168.3.7:9081';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getHttpBase() {
|
||||||
|
return `http://${getHost()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getWebsocketUrl() {
|
||||||
|
return `ws://${getHost()}/ws-default`;
|
||||||
|
}
|
@ -9,8 +9,19 @@ import type { GraphicApp } from '../app/JlGraphicApp';
|
|||||||
import { GraphicState } from '../core/JlGraphic';
|
import { GraphicState } from '../core/JlGraphic';
|
||||||
|
|
||||||
export interface StompCliOption {
|
export interface StompCliOption {
|
||||||
wsUrl: string; // websocket url
|
/**
|
||||||
token: string; // 认证token
|
* websocket url地址
|
||||||
|
*/
|
||||||
|
wsUrl: string;
|
||||||
|
/**
|
||||||
|
* 认证token
|
||||||
|
*/
|
||||||
|
token?: string;
|
||||||
|
/**
|
||||||
|
* 认证失败处理
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
onAuthenticationFailed?: () => void;
|
||||||
reconnectDelay?: number; // 重连延时,默认3秒
|
reconnectDelay?: number; // 重连延时,默认3秒
|
||||||
heartbeatIncoming?: number; // 服务端过来的心跳间隔,默认30秒
|
heartbeatIncoming?: number; // 服务端过来的心跳间隔,默认30秒
|
||||||
heartbeatOutgoing?: number; // 到服务端的心跳间隔,默认30秒
|
heartbeatOutgoing?: number; // 到服务端的心跳间隔,默认30秒
|
||||||
@ -32,7 +43,7 @@ export class StompCli {
|
|||||||
private static connected = false;
|
private static connected = false;
|
||||||
static new(options: StompCliOption) {
|
static new(options: StompCliOption) {
|
||||||
if (StompCli.enabled) {
|
if (StompCli.enabled) {
|
||||||
// 以及启用
|
// 已经启用
|
||||||
return;
|
return;
|
||||||
// throw new Error('websocket 已连接,若确实需要重新连接,请先断开StompCli.close再重新StompCli.new')
|
// throw new Error('websocket 已连接,若确实需要重新连接,请先断开StompCli.close再重新StompCli.new')
|
||||||
}
|
}
|
||||||
@ -41,12 +52,8 @@ export class StompCli {
|
|||||||
StompCli.client = new StompClient({
|
StompCli.client = new StompClient({
|
||||||
brokerURL: StompCli.options.wsUrl,
|
brokerURL: StompCli.options.wsUrl,
|
||||||
connectHeaders: {
|
connectHeaders: {
|
||||||
Authorization: StompCli.options.token,
|
Authorization: StompCli.options.token ? StompCli.options.token : '',
|
||||||
// Authorization: ''
|
|
||||||
},
|
},
|
||||||
// debug: (str) => {
|
|
||||||
// console.log(str)
|
|
||||||
// }
|
|
||||||
reconnectDelay: StompCli.options.reconnectDelay,
|
reconnectDelay: StompCli.options.reconnectDelay,
|
||||||
heartbeatIncoming: StompCli.options.heartbeatIncoming,
|
heartbeatIncoming: StompCli.options.heartbeatIncoming,
|
||||||
heartbeatOutgoing: StompCli.options.heartbeatOutgoing,
|
heartbeatOutgoing: StompCli.options.heartbeatOutgoing,
|
||||||
@ -61,19 +68,21 @@ export class StompCli {
|
|||||||
};
|
};
|
||||||
|
|
||||||
StompCli.client.onStompError = (frame: Frame) => {
|
StompCli.client.onStompError = (frame: Frame) => {
|
||||||
console.error(
|
const errMsg = frame.headers['message'];
|
||||||
'Stomp收到error消息,可能是认证失败(暂时没有判断具体错误类型,后需添加判断),关闭Stomp客户端',
|
if (errMsg === '401') {
|
||||||
frame
|
console.warn('认证失败,断开WebSocket连接');
|
||||||
);
|
|
||||||
StompCli.close();
|
StompCli.close();
|
||||||
|
if (StompCli.options.onAuthenticationFailed) {
|
||||||
|
StompCli.options.onAuthenticationFailed();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('收到Stomp错误消息', frame);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
StompCli.client.onDisconnect = (frame: Frame) => {
|
StompCli.client.onDisconnect = (frame: Frame) => {
|
||||||
console.log('Stomp 断开连接', frame);
|
console.log('Stomp 断开连接', frame);
|
||||||
StompCli.connected = false;
|
StompCli.connected = false;
|
||||||
// StompCli.appMsgBroker.forEach(broker => {
|
|
||||||
// broker.close();
|
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
StompCli.client.onWebSocketClose = (evt: CloseEvent) => {
|
StompCli.client.onWebSocketClose = (evt: CloseEvent) => {
|
||||||
console.log('websocket 关闭', evt);
|
console.log('websocket 关闭', evt);
|
||||||
@ -82,9 +91,6 @@ export class StompCli {
|
|||||||
// websocket错误处理
|
// websocket错误处理
|
||||||
StompCli.client.onWebSocketError = (err: Event) => {
|
StompCli.client.onWebSocketError = (err: Event) => {
|
||||||
console.log('websocket错误', err);
|
console.log('websocket错误', err);
|
||||||
// StompCli.appMsgBroker.forEach(broker => {
|
|
||||||
// broker.unsbuscribeAll();
|
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StompCli.client.activate();
|
StompCli.client.activate();
|
||||||
@ -140,19 +146,10 @@ export class StompCli {
|
|||||||
// 状态订阅消息转换器
|
// 状态订阅消息转换器
|
||||||
export type MessageConverter = (message: Uint8Array) => GraphicState[];
|
export type MessageConverter = (message: Uint8Array) => GraphicState[];
|
||||||
// 图形app状态订阅
|
// 图形app状态订阅
|
||||||
export class AppStateSubscription {
|
export interface AppStateSubscription {
|
||||||
destination: string;
|
destination: string;
|
||||||
messageConverter: MessageConverter;
|
messageConverter: MessageConverter;
|
||||||
subscription?: StompSubscription; // 订阅成功对象,用于取消订阅
|
subscription?: StompSubscription; // 订阅成功对象,用于取消订阅
|
||||||
constructor(
|
|
||||||
destination: string,
|
|
||||||
messageConverter: MessageConverter,
|
|
||||||
subscription?: StompSubscription
|
|
||||||
) {
|
|
||||||
this.destination = destination;
|
|
||||||
this.messageConverter = messageConverter;
|
|
||||||
this.subscription = subscription;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,6 +109,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import DrawProperties from 'src/components/draw-app/DrawProperties.vue';
|
import DrawProperties from 'src/components/draw-app/DrawProperties.vue';
|
||||||
import { getDrawApp, loadDrawDatas } from 'src/examples/app';
|
import { getDrawApp, loadDrawDatas } from 'src/examples/app';
|
||||||
|
import { getWebsocketUrl } from 'src/examples/app/configs/UrlManage';
|
||||||
|
import { AppStateSubscription } from 'src/jlgraphic';
|
||||||
import { useDrawStore } from 'src/stores/draw-store';
|
import { useDrawStore } from 'src/stores/draw-store';
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { onMounted, onUnmounted, ref } from 'vue';
|
||||||
|
|
||||||
@ -134,6 +136,17 @@ onMounted(() => {
|
|||||||
const drawApp = drawStore.initDrawApp(dom);
|
const drawApp = drawStore.initDrawApp(dom);
|
||||||
loadDrawDatas(drawApp);
|
loadDrawDatas(drawApp);
|
||||||
onResize();
|
onResize();
|
||||||
|
drawApp.enableWsStomp({
|
||||||
|
wsUrl: getWebsocketUrl(),
|
||||||
|
token: '',
|
||||||
|
});
|
||||||
|
drawApp.subscribe({
|
||||||
|
destination: '/queue/line/2',
|
||||||
|
messageConverter: (msg) => {
|
||||||
|
console.log(msg);
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
47
yarn.lock
47
yarn.lock
@ -815,6 +815,11 @@ async@^3.2.3:
|
|||||||
resolved "https://registry.npmmirror.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
|
resolved "https://registry.npmmirror.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
|
||||||
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
|
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
|
||||||
|
|
||||||
|
asynckit@^0.4.0:
|
||||||
|
version "0.4.0"
|
||||||
|
resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
|
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||||
|
|
||||||
autoprefixer@^10.4.2:
|
autoprefixer@^10.4.2:
|
||||||
version "10.4.14"
|
version "10.4.14"
|
||||||
resolved "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d"
|
resolved "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d"
|
||||||
@ -827,6 +832,15 @@ autoprefixer@^10.4.2:
|
|||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
postcss-value-parser "^4.2.0"
|
postcss-value-parser "^4.2.0"
|
||||||
|
|
||||||
|
axios@^1.4.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.npmmirror.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f"
|
||||||
|
integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.15.0"
|
||||||
|
form-data "^4.0.0"
|
||||||
|
proxy-from-env "^1.1.0"
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
@ -1052,6 +1066,13 @@ colord@^2.9.3:
|
|||||||
resolved "https://registry.npmmirror.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
|
resolved "https://registry.npmmirror.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
|
||||||
integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==
|
integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==
|
||||||
|
|
||||||
|
combined-stream@^1.0.8:
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||||
|
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||||
|
dependencies:
|
||||||
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
commander@^2.19.0:
|
commander@^2.19.0:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
@ -1182,6 +1203,11 @@ define-lazy-prop@^2.0.0:
|
|||||||
resolved "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
|
resolved "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
|
||||||
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
|
integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
|
||||||
|
|
||||||
|
delayed-stream@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
|
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||||
|
|
||||||
depd@2.0.0:
|
depd@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||||
@ -1811,6 +1837,20 @@ flatted@^3.1.0:
|
|||||||
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
||||||
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
||||||
|
|
||||||
|
follow-redirects@^1.15.0:
|
||||||
|
version "1.15.2"
|
||||||
|
resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||||
|
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||||
|
|
||||||
|
form-data@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||||
|
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||||
|
dependencies:
|
||||||
|
asynckit "^0.4.0"
|
||||||
|
combined-stream "^1.0.8"
|
||||||
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
forwarded@0.2.0:
|
forwarded@0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
resolved "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||||
@ -2327,7 +2367,7 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
|
|||||||
resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||||
|
|
||||||
mime-types@~2.1.24, mime-types@~2.1.34:
|
mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34:
|
||||||
version "2.1.35"
|
version "2.1.35"
|
||||||
resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||||
@ -2686,6 +2726,11 @@ proxy-addr@~2.0.7:
|
|||||||
forwarded "0.2.0"
|
forwarded "0.2.0"
|
||||||
ipaddr.js "1.9.1"
|
ipaddr.js "1.9.1"
|
||||||
|
|
||||||
|
proxy-from-env@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||||
|
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||||
|
|
||||||
punycode@1.3.2:
|
punycode@1.3.2:
|
||||||
version "1.3.2"
|
version "1.3.2"
|
||||||
resolved "https://registry.npmmirror.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
resolved "https://registry.npmmirror.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
||||||
|
Loading…
Reference in New Issue
Block a user