mirror of https://github.com/veypi/OneAuth.git
init lib
parent
34520f36fd
commit
8f2bcc1591
@ -0,0 +1,23 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
@ -0,0 +1,11 @@
|
||||
# Vite starter
|
||||
|
||||
### Elements
|
||||
|
||||
- vue3
|
||||
- typescript
|
||||
- vite
|
||||
- tailwindcss
|
||||
- pinia
|
||||
- animate.css
|
||||
-
|
@ -0,0 +1,115 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>OA</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="v-msg"></div>
|
||||
<div id="loader-wrapper">
|
||||
<div class="lds-ripple">
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="load_title">Loading...
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 周围滑动留白 */
|
||||
html {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#loader-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 999999;
|
||||
background: #999;
|
||||
}
|
||||
|
||||
#loader-wrapper .load_title {
|
||||
font-family: 'Open Sans';
|
||||
color: #FFF;
|
||||
font-size: 19px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
z-index: 9999999999999;
|
||||
position: absolute;
|
||||
top: 70%;
|
||||
opacity: 1;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
#loader-wrapper .load_title span {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
color: #FFF;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.lds-ripple {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
left: calc(50% - 40px);
|
||||
top: calc(70% - 100px);
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.lds-ripple div {
|
||||
position: absolute;
|
||||
border: 4px solid #fff;
|
||||
opacity: 1;
|
||||
border-radius: 50%;
|
||||
animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
|
||||
}
|
||||
|
||||
.lds-ripple div:nth-child(2) {
|
||||
animation-delay: -0.5s;
|
||||
}
|
||||
|
||||
@keyframes lds-ripple {
|
||||
0% {
|
||||
top: 36px;
|
||||
left: 36px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</html>
|
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "vite-starter",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@veypi/one-icon": "2",
|
||||
"animate.css": "^4.1.1",
|
||||
"mitt": "^3.0.0",
|
||||
"pinia": "^2.0.13",
|
||||
"vue": "^3.2.25",
|
||||
"vue-router": "4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17.0.24",
|
||||
"@vitejs/plugin-vue": "^2.3.1",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"postcss": "^8.4.12",
|
||||
"tailwindcss": "^3.0.24",
|
||||
"typescript": "^4.6.2",
|
||||
"vite": "^2.9.2",
|
||||
"vue-tsc": "^0.34.6"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,36 @@
|
||||
<style>
|
||||
#app {
|
||||
@apply h-full w-full flex justify-center items-center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<Frame>
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition
|
||||
mode="out-in"
|
||||
enter-active-class="animate__fadeIn"
|
||||
leave-active-class="animate__fadeOut"
|
||||
>
|
||||
<component class="animate__animated animate__faster" :is="Component"></component>
|
||||
</transition>
|
||||
</router-view>
|
||||
</Frame>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Frame from '@/components/frame.vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { onBeforeMount } from 'vue'
|
||||
|
||||
let user = useUserStore()
|
||||
user.setUser()
|
||||
onBeforeMount(() => {
|
||||
let loader = document.getElementById('loader-wrapper')
|
||||
if (loader && loader.parentElement) {
|
||||
loader.parentElement.removeChild(loader)
|
||||
}
|
||||
// store.dispatch('fetchSelf')
|
||||
// store.dispatch('user/fetchUserData')
|
||||
})
|
||||
</script>
|
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,105 @@
|
||||
<!--
|
||||
* frame.vue
|
||||
* Copyright (C) 2022 veypi <i@veypi.com>
|
||||
* 2022-12-20 00:10
|
||||
* Distributed under terms of the Apache license.
|
||||
-->
|
||||
<template>
|
||||
<div class="font-sans select-none" style="height: 100vh; width: 100vw">
|
||||
<transition enter-active-class="animate__slideInDown" leave-active-class="animate__slideOutUp">
|
||||
<one-icon
|
||||
class="header-down animate__animated"
|
||||
@click="app.hideHeader = !app.hideHeader"
|
||||
v-if="app.hideHeader"
|
||||
>
|
||||
down
|
||||
</one-icon>
|
||||
</transition>
|
||||
<div style="height: calc(100vh - 24px)">
|
||||
<transition
|
||||
enter-active-class="animate__slideInDown"
|
||||
leave-active-class="animate__slideOutUp"
|
||||
>
|
||||
<div
|
||||
class="animate__animated"
|
||||
v-if="!app.hideHeader"
|
||||
bordered
|
||||
style="height: 64px; line-height: 64px"
|
||||
>
|
||||
<div class="flex h-full">
|
||||
<div class="h-full">
|
||||
<one-icon
|
||||
color="#000"
|
||||
class="inline-block"
|
||||
@click="$router.push('/')"
|
||||
style="font-size: 48px; margin: 8px; color: aqua"
|
||||
>
|
||||
glassdoor
|
||||
</one-icon>
|
||||
</div>
|
||||
<div class="h-full" style="margin-left: 10px">
|
||||
<span type="primary">统一认证系统</span>
|
||||
</div>
|
||||
<div class="flex-grow flex justify-center">
|
||||
<span class="text-2xl" style="line-height: 64px">{{ app.title }}</span>
|
||||
</div>
|
||||
<div class="h-full px-3">
|
||||
<fullscreen v-model="isFullScreen" class="header-icon">fullscreen</fullscreen>
|
||||
<div class="header-icon">
|
||||
<one-icon @click="">
|
||||
{{ app.isDark ? 'Daytimemode' : 'nightmode-fill' }}
|
||||
</one-icon>
|
||||
</div>
|
||||
<div class="header-icon" @click="app.hideHeader = true">
|
||||
<one-icon>up</one-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div vif="$store.state.user.ready" class="h-full flex justify-center items-center mr-5">
|
||||
<!-- <OAer @logout="$store.commit('user/logout')" :is-dark="IsDark"></OAer> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
bordered
|
||||
style="height: 24px; line-height: 24px"
|
||||
class="flex justify-around px-3 text-gray-500 text-xs"
|
||||
>
|
||||
<span class="hover:text-black cursor-pointer" @click="$router.push({ name: 'about' })">
|
||||
关于OA
|
||||
</span>
|
||||
<span class="hover:text-black cursor-pointer">使用须知</span>
|
||||
<span class="hover:text-black cursor-pointer" @click="util.goto('https://veypi.com')">
|
||||
©2021 veypi
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useAppStore } from '@/store/app'
|
||||
import fullscreen from './fullscreen'
|
||||
import util from '@/libs/util'
|
||||
|
||||
let app = useAppStore()
|
||||
let isFullScreen = false
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header-icon {
|
||||
display: inline-block;
|
||||
font-size: 24px;
|
||||
margin: 20px 10px 20px 10px;
|
||||
}
|
||||
.header-down {
|
||||
font-size: 24px;
|
||||
position: fixed;
|
||||
right: 76px;
|
||||
top: 5px;
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div @click="handleFullscreen">
|
||||
<one-icon>{{ props.modelValue ? 'fullscreen-exit' : 'fullscreen' }}</one-icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
let emit = defineEmits<{
|
||||
(e: 'update:modelValue', v: boolean): void
|
||||
}>()
|
||||
|
||||
let props = defineProps<{
|
||||
modelValue: boolean
|
||||
}>()
|
||||
|
||||
function handleFullscreen() {
|
||||
let main = document.body
|
||||
if (props.modelValue) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen()
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen()
|
||||
} else if (document.webkitCancelFullScreen) {
|
||||
document.webkitCancelFullScreen()
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen()
|
||||
}
|
||||
} else {
|
||||
if (main.requestFullscreen) {
|
||||
main.requestFullscreen()
|
||||
} else if (main.mozRequestFullScreen) {
|
||||
main.mozRequestFullScreen()
|
||||
} else if (main.webkitRequestFullScreen) {
|
||||
main.webkitRequestFullScreen()
|
||||
} else if (main.msRequestFullscreen) {
|
||||
main.msRequestFullscreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sync() {
|
||||
let isFullscreen =
|
||||
document.fullscreenElement ||
|
||||
document.mozFullScreenElement ||
|
||||
document.webkitFullscreenElement ||
|
||||
document.fullScreen ||
|
||||
document.mozFullScreen ||
|
||||
document.webkitIsFullScreen
|
||||
isFullscreen = !!isFullscreen
|
||||
emit('update:modelValue', isFullscreen)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('fullscreenchange', sync)
|
||||
document.addEventListener('mozfullscreenchange', sync)
|
||||
document.addEventListener('webkitfullscreenchange', sync)
|
||||
document.addEventListener('msfullscreenchange', sync)
|
||||
sync()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style></style>
|
@ -0,0 +1,2 @@
|
||||
import fullscreen from './fullscreen.vue'
|
||||
export default fullscreen
|
@ -0,0 +1,8 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
transition: all 0.2s linear;
|
||||
--base-color: #000;
|
||||
--base-bg: #fff;
|
||||
}
|
||||
|
||||
:root[theme=dark] {
|
||||
--base-color: #fff;
|
||||
--base-bg: #000;
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
import axios from 'axios'
|
||||
|
||||
function padLeftZero(str: string): string {
|
||||
return ('00' + str).substr(str.length)
|
||||
}
|
||||
|
||||
const util = {
|
||||
goto(url: string) {
|
||||
window.open(url, '_blank')
|
||||
},
|
||||
title: function (title: string) {
|
||||
window.document.title = title ? title + ' - oa' : 'veypi project'
|
||||
},
|
||||
getCookie(name: string) {
|
||||
const reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
|
||||
const arr = document.cookie.match(reg)
|
||||
if (arr) {
|
||||
return unescape(arr[2])
|
||||
} else return null
|
||||
},
|
||||
delCookie(name: string) {
|
||||
const exp = new Date()
|
||||
exp.setTime(exp.getTime() - 1)
|
||||
const cval = this.getCookie(name)
|
||||
if (cval !== null) {
|
||||
document.cookie = name + '=' + cval + ';expires=' + exp.toLocaleString()
|
||||
}
|
||||
},
|
||||
setCookie(name: string, value: string, time: number) {
|
||||
const exp = new Date()
|
||||
exp.setTime(exp.getTime() + time)
|
||||
document.cookie =
|
||||
name + '=' + escape(value) + ';expires=' + exp.toLocaleString()
|
||||
},
|
||||
getToken() {
|
||||
return localStorage.auth_token
|
||||
},
|
||||
addTokenOf(url: string) {
|
||||
return url + '?auth_token=' + encodeURIComponent(this.getToken())
|
||||
},
|
||||
checkLogin() {
|
||||
// return parseInt(this.getCookie('stat')) === 1
|
||||
return Boolean(localStorage.auth_token)
|
||||
},
|
||||
|
||||
formatDate(date: Date, fmt: string) {
|
||||
if (/(y+)/.test(fmt)) {
|
||||
fmt = fmt.replace(
|
||||
RegExp.$1,
|
||||
(date.getFullYear() + '').substr(4 - RegExp.$1.length),
|
||||
)
|
||||
}
|
||||
const o = {
|
||||
'M+': date.getMonth() + 1,
|
||||
'd+': date.getDate(),
|
||||
'h+': date.getHours(),
|
||||
'm+': date.getMinutes(),
|
||||
's+': date.getSeconds(),
|
||||
}
|
||||
for (const k in o) {
|
||||
if (new RegExp(`(${k})`).test(fmt)) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
||||
// @ts-ignore
|
||||
const str = o[k] + ''
|
||||
fmt = fmt.replace(
|
||||
RegExp.$1,
|
||||
RegExp.$1.length === 1 ? str : padLeftZero(str),
|
||||
)
|
||||
}
|
||||
}
|
||||
return fmt
|
||||
},
|
||||
}
|
||||
|
||||
export default util
|
@ -0,0 +1,7 @@
|
||||
import { toBase64 } from "../tools/encode";
|
||||
import { AuthHeader } from "../types";
|
||||
|
||||
export function generateBasicAuthHeader(username: string, password: string): AuthHeader {
|
||||
const encoded = toBase64(`${username}:${password}`);
|
||||
return `Basic ${encoded}`;
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
import md5 from "md5";
|
||||
import { ha1Compute } from "../tools/crypto";
|
||||
import { DigestContext, Response } from "../types";
|
||||
|
||||
const NONCE_CHARS = "abcdef0123456789";
|
||||
const NONCE_SIZE = 32;
|
||||
|
||||
export function createDigestContext(username: string, password: string): DigestContext {
|
||||
return { username, password, nc: 0, algorithm: "md5", hasDigestAuth: false };
|
||||
}
|
||||
|
||||
export function generateDigestAuthHeader(options, digest: DigestContext): string {
|
||||
const url = options.url.replace("//", "");
|
||||
const uri = url.indexOf("/") == -1 ? "/" : url.slice(url.indexOf("/"));
|
||||
const method = options.method ? options.method.toUpperCase() : "GET";
|
||||
const qop = /(^|,)\s*auth\s*($|,)/.test(digest.qop) ? "auth" : false;
|
||||
const ncString = `00000000${digest.nc}`.slice(-8);
|
||||
const ha1 = ha1Compute(
|
||||
digest.algorithm,
|
||||
digest.username,
|
||||
digest.realm,
|
||||
digest.password,
|
||||
digest.nonce,
|
||||
digest.cnonce
|
||||
);
|
||||
const ha2 = md5(`${method}:${uri}`);
|
||||
const digestResponse = qop
|
||||
? md5(`${ha1}:${digest.nonce}:${ncString}:${digest.cnonce}:${qop}:${ha2}`)
|
||||
: md5(`${ha1}:${digest.nonce}:${ha2}`);
|
||||
|
||||
const authValues = {
|
||||
username: digest.username,
|
||||
realm: digest.realm,
|
||||
nonce: digest.nonce,
|
||||
uri,
|
||||
qop,
|
||||
response: digestResponse,
|
||||
nc: ncString,
|
||||
cnonce: digest.cnonce,
|
||||
algorithm: digest.algorithm,
|
||||
opaque: digest.opaque
|
||||
};
|
||||
|
||||
const authHeader = [];
|
||||
for (const k in authValues) {
|
||||
if (authValues[k]) {
|
||||
if (k === "qop" || k === "nc" || k === "algorithm") {
|
||||
authHeader.push(`${k}=${authValues[k]}`);
|
||||
} else {
|
||||
authHeader.push(`${k}="${authValues[k]}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return `Digest ${authHeader.join(", ")}`;
|
||||
}
|
||||
|
||||
function makeNonce(): string {
|
||||
let uid = "";
|
||||
for (let i = 0; i < NONCE_SIZE; ++i) {
|
||||
uid = `${uid}${NONCE_CHARS[Math.floor(Math.random() * NONCE_CHARS.length)]}`;
|
||||
}
|
||||
return uid;
|
||||
}
|
||||
|
||||
export function parseDigestAuth(response: Response, _digest: DigestContext): boolean {
|
||||
const authHeader = response.headers["www-authenticate"] || "";
|
||||
if (authHeader.split(/\s/)[0].toLowerCase() !== "digest") {
|
||||
return false;
|
||||
}
|
||||
const re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi;
|
||||
for (;;) {
|
||||
const match = re.exec(authHeader);
|
||||
if (!match) {
|
||||
break;
|
||||
}
|
||||
_digest[match[1]] = match[2] || match[3];
|
||||
}
|
||||
_digest.nc += 1;
|
||||
_digest.cnonce = makeNonce();
|
||||
return true;
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import { Layerr } from "layerr";
|
||||
import { createDigestContext } from "./digest";
|
||||
import { generateBasicAuthHeader } from "./basic";
|
||||
import { generateTokenAuthHeader } from "./oauth";
|
||||
import { AuthType, ErrorCode, OAuthToken, WebDAVClientContext } from "../types";
|
||||
|
||||
export function setupAuth(
|
||||
context: WebDAVClientContext,
|
||||
username: string,
|
||||
password: string,
|
||||
oauthToken: OAuthToken
|
||||
): void {
|
||||
switch (context.authType) {
|
||||
case AuthType.Digest:
|
||||
context.digest = createDigestContext(username, password);
|
||||
break;
|
||||
case AuthType.None:
|
||||
// Do nothing
|
||||
break;
|
||||
case AuthType.Password:
|
||||
context.headers.Authorization = generateBasicAuthHeader(username, password);
|
||||
break;
|
||||
case AuthType.Token:
|
||||
context.headers.Authorization = generateTokenAuthHeader(oauthToken);
|
||||
break;
|
||||
default:
|
||||
throw new Layerr(
|
||||
{
|
||||
info: {
|
||||
code: ErrorCode.InvalidAuthType
|
||||
}
|
||||
},
|
||||
`Invalid auth type: ${context.authType}`
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { AuthHeader, OAuthToken } from "../types";
|
||||
|
||||
export function generateTokenAuthHeader(token: OAuthToken): AuthHeader {
|
||||
return `${token.token_type} ${token.access_token}`;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
const hasArrayBuffer = typeof ArrayBuffer === "function";
|
||||
const { toString: objToString } = Object.prototype;
|
||||
|
||||
// Taken from: https://github.com/fengyuanchen/is-array-buffer/blob/master/src/index.js
|
||||
export function isArrayBuffer(value: any): boolean {
|
||||
return (
|
||||
hasArrayBuffer &&
|
||||
(value instanceof ArrayBuffer || objToString.call(value) === "[object ArrayBuffer]")
|
||||
);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
export function isBuffer(value: any): boolean {
|
||||
return (
|
||||
value != null &&
|
||||
value.constructor != null &&
|
||||
typeof value.constructor.isBuffer === "function" &&
|
||||
value.constructor.isBuffer(value)
|
||||
);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import HotPatcher from "hot-patcher";
|
||||
|
||||
let __patcher: HotPatcher = null;
|
||||
|
||||
export function getPatcher(): HotPatcher {
|
||||
if (!__patcher) {
|
||||
__patcher = new HotPatcher();
|
||||
}
|
||||
return __patcher;
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
import Stream from "stream";
|
||||
import { extractURLPath } from "./tools/url";
|
||||
import { setupAuth } from "./auth/index";
|
||||
import { copyFile } from "./operations/copyFile";
|
||||
import { createDirectory } from "./operations/createDirectory";
|
||||
import { createReadStream, createWriteStream } from "./operations/createStream";
|
||||
import { customRequest } from "./operations/customRequest";
|
||||
import { deleteFile } from "./operations/deleteFile";
|
||||
import { exists } from "./operations/exists";
|
||||
import { getDirectoryContents } from "./operations/directoryContents";
|
||||
import { getFileContents, getFileDownloadLink } from "./operations/getFileContents";
|
||||
import { lock, unlock } from "./operations/lock";
|
||||
import { getQuota } from "./operations/getQuota";
|
||||
import { getStat } from "./operations/stat";
|
||||
import { moveFile } from "./operations/moveFile";
|
||||
import { getFileUploadLink, putFileContents } from "./operations/putFileContents";
|
||||
import {
|
||||
AuthType,
|
||||
BufferLike,
|
||||
CreateReadStreamOptions,
|
||||
CreateWriteStreamCallback,
|
||||
CreateWriteStreamOptions,
|
||||
GetDirectoryContentsOptions,
|
||||
GetFileContentsOptions,
|
||||
GetQuotaOptions,
|
||||
Headers,
|
||||
LockOptions,
|
||||
PutFileContentsOptions,
|
||||
RequestOptionsCustom,
|
||||
StatOptions,
|
||||
WebDAVClient,
|
||||
WebDAVClientContext,
|
||||
WebDAVClientOptions,
|
||||
WebDAVMethodOptions
|
||||
} from "./types";
|
||||
|
||||
const DEFAULT_CONTACT_HREF =
|
||||
"https://github.com/perry-mitchell/webdav-client/blob/master/LOCK_CONTACT.md";
|
||||
|
||||
export function createClient(remoteURL: string, options: WebDAVClientOptions = {}): WebDAVClient {
|
||||
const {
|
||||
authType: authTypeRaw = null,
|
||||
contactHref = DEFAULT_CONTACT_HREF,
|
||||
headers = {},
|
||||
httpAgent,
|
||||
httpsAgent,
|
||||
maxBodyLength,
|
||||
maxContentLength,
|
||||
password,
|
||||
token,
|
||||
username,
|
||||
withCredentials
|
||||
} = options;
|
||||
let authType = authTypeRaw;
|
||||
if (!authType) {
|
||||
authType = username || password ? AuthType.Password : AuthType.None;
|
||||
}
|
||||
const context: WebDAVClientContext = {
|
||||
authType,
|
||||
contactHref,
|
||||
headers: Object.assign({}, headers),
|
||||
httpAgent,
|
||||
httpsAgent,
|
||||
maxBodyLength,
|
||||
maxContentLength,
|
||||
remotePath: extractURLPath(remoteURL),
|
||||
remoteURL,
|
||||
password,
|
||||
token,
|
||||
username,
|
||||
withCredentials
|
||||
};
|
||||
setupAuth(context, username, password, token);
|
||||
return {
|
||||
copyFile: (filename: string, destination: string, options?: WebDAVMethodOptions) =>
|
||||
copyFile(context, filename, destination, options),
|
||||
createDirectory: (path: string, options?: WebDAVMethodOptions) =>
|
||||
createDirectory(context, path, options),
|
||||
createReadStream: (filename: string, options?: CreateReadStreamOptions) =>
|
||||
createReadStream(context, filename, options),
|
||||
createWriteStream: (
|
||||
filename: string,
|
||||
options?: CreateWriteStreamOptions,
|
||||
callback?: CreateWriteStreamCallback
|
||||
) => createWriteStream(context, filename, options, callback),
|
||||
customRequest: (path: string, requestOptions: RequestOptionsCustom) =>
|
||||
customRequest(context, path, requestOptions),
|
||||
deleteFile: (filename: string, options?: WebDAVMethodOptions) =>
|
||||
deleteFile(context, filename, options),
|
||||
exists: (path: string, options?: WebDAVMethodOptions) => exists(context, path, options),
|
||||
getDirectoryContents: (path: string, options?: GetDirectoryContentsOptions) =>
|
||||
getDirectoryContents(context, path, options),
|
||||
getFileContents: (filename: string, options?: GetFileContentsOptions) =>
|
||||
getFileContents(context, filename, options),
|
||||
getFileDownloadLink: (filename: string) => getFileDownloadLink(context, filename),
|
||||
getFileUploadLink: (filename: string) => getFileUploadLink(context, filename),
|
||||
getHeaders: () => Object.assign({}, context.headers),
|
||||
getQuota: (options?: GetQuotaOptions) => getQuota(context, options),
|
||||
lock: (path: string, options?: LockOptions) => lock(context, path, options),
|
||||
moveFile: (filename: string, destinationFilename: string, options?: WebDAVMethodOptions) =>
|
||||
moveFile(context, filename, destinationFilename, options),
|
||||
putFileContents: (
|
||||
filename: string,
|
||||
data: string | BufferLike | Stream.Readable,
|
||||
options?: PutFileContentsOptions
|
||||
) => putFileContents(context, filename, data, options),
|
||||
setHeaders: (headers: Headers) => {
|
||||
context.headers = Object.assign({}, headers);
|
||||
},
|
||||
stat: (path: string, options?: StatOptions) => getStat(context, path, options),
|
||||
unlock: (path: string, token: string, options?: WebDAVMethodOptions) =>
|
||||
unlock(context, path, token, options)
|
||||
};
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
export { createClient } from "./factory";
|
||||
export { getPatcher } from "./compat/patcher";
|
||||
export * from "./types";
|
||||
|
||||
export { parseStat, parseXML } from "./tools/dav";
|
@ -0,0 +1,26 @@
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode } from "../response";
|
||||
import { WebDAVClientContext, WebDAVMethodOptions } from "../types";
|
||||
|
||||
export async function copyFile(
|
||||
context: WebDAVClientContext,
|
||||
filename: string,
|
||||
destination: string,
|
||||
options: WebDAVMethodOptions = {}
|
||||
): Promise<void> {
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filename)),
|
||||
method: "COPY",
|
||||
headers: {
|
||||
Destination: joinURL(context.remoteURL, encodePath(destination))
|
||||
}
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath, getAllDirectories, normalisePath } from "../tools/path";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode } from "../response";
|
||||
import { getStat } from "./stat";
|
||||
import { CreateDirectoryOptions, FileStat, WebDAVClientContext, WebDAVClientError } from "../types";
|
||||
|
||||
export async function createDirectory(
|
||||
context: WebDAVClientContext,
|
||||
dirPath: string,
|
||||
options: CreateDirectoryOptions = {}
|
||||
): Promise<void> {
|
||||
if (options.recursive === true) return createDirectoryRecursively(context, dirPath, options);
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, ensureCollectionPath(encodePath(dirPath))),
|
||||
method: "MKCOL"
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the path is a proper "collection" path by ensuring it has a trailing "/".
|
||||
* The proper format of collection according to the specification does contain the trailing slash.
|
||||
* http://www.webdav.org/specs/rfc4918.html#rfc.section.5.2
|
||||
* @param path Path of the collection
|
||||
* @return string Path of the collection with appended trailing "/" in case the `path` does not have it.
|
||||
*/
|
||||
function ensureCollectionPath(path: string): string {
|
||||
if (!path.endsWith("/")) {
|
||||
return path + "/";
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
async function createDirectoryRecursively(
|
||||
context: WebDAVClientContext,
|
||||
dirPath: string,
|
||||
options: CreateDirectoryOptions = {}
|
||||
): Promise<void> {
|
||||
const paths = getAllDirectories(normalisePath(dirPath));
|
||||
paths.sort((a, b) => {
|
||||
if (a.length > b.length) {
|
||||
return 1;
|
||||
} else if (b.length > a.length) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
let creating: boolean = false;
|
||||
for (const testPath of paths) {
|
||||
if (creating) {
|
||||
await createDirectory(context, testPath, {
|
||||
...options,
|
||||
recursive: false
|
||||
});
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const testStat = (await getStat(context, testPath)) as FileStat;
|
||||
if (testStat.type !== "directory") {
|
||||
throw new Error(`Path includes a file: ${dirPath}`);
|
||||
}
|
||||
} catch (err) {
|
||||
const error = err as WebDAVClientError;
|
||||
if (error.status === 404) {
|
||||
creating = true;
|
||||
await createDirectory(context, testPath, {
|
||||
...options,
|
||||
recursive: false
|
||||
});
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
import Stream from "stream";
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode } from "../response";
|
||||
import {
|
||||
CreateReadStreamOptions,
|
||||
CreateWriteStreamCallback,
|
||||
CreateWriteStreamOptions,
|
||||
Headers,
|
||||
WebDAVClientContext,
|
||||
WebDAVClientError
|
||||
} from "../types";
|
||||
|
||||
const NOOP = () => {};
|
||||
|
||||
export function createReadStream(
|
||||
context: WebDAVClientContext,
|
||||
filePath: string,
|
||||
options: CreateReadStreamOptions = {}
|
||||
): Stream.Readable {
|
||||
const PassThroughStream = Stream.PassThrough;
|
||||
const outStream = new PassThroughStream();
|
||||
getFileStream(context, filePath, options)
|
||||
.then(stream => {
|
||||
stream.pipe(outStream);
|
||||
})
|
||||
.catch(err => {
|
||||
outStream.emit("error", err);
|
||||
});
|
||||
return outStream;
|
||||
}
|
||||
|
||||
export function createWriteStream(
|
||||
context: WebDAVClientContext,
|
||||
filePath: string,
|
||||
options: CreateWriteStreamOptions = {},
|
||||
callback: CreateWriteStreamCallback = NOOP
|
||||
): Stream.Writable {
|
||||
const PassThroughStream = Stream.PassThrough;
|
||||
const writeStream = new PassThroughStream();
|
||||
const headers = {};
|
||||
if (options.overwrite === false) {
|
||||
headers["If-None-Match"] = "*";
|
||||
}
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filePath)),
|
||||
method: "PUT",
|
||||
headers,
|
||||
data: writeStream,
|
||||
maxRedirects: 0
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
request(requestOptions)
|
||||
.then(response => handleResponseCode(context, response))
|
||||
.then(response => {
|
||||
// Fire callback asynchronously to avoid errors
|
||||
setTimeout(() => {
|
||||
callback(response);
|
||||
}, 0);
|
||||
})
|
||||
.catch(err => {
|
||||
writeStream.emit("error", err);
|
||||
});
|
||||
return writeStream;
|
||||
}
|
||||
|
||||
async function getFileStream(
|
||||
context: WebDAVClientContext,
|
||||
filePath: string,
|
||||
options: CreateReadStreamOptions = {}
|
||||
): Promise<Stream.Readable> {
|
||||
const headers: Headers = {};
|
||||
if (typeof options.range === "object" && typeof options.range.start === "number") {
|
||||
let rangeHeader = `bytes=${options.range.start}-`;
|
||||
if (typeof options.range.end === "number") {
|
||||
rangeHeader = `${rangeHeader}${options.range.end}`;
|
||||
}
|
||||
headers.Range = rangeHeader;
|
||||
}
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filePath)),
|
||||
method: "GET",
|
||||
headers,
|
||||
responseType: "stream"
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
if (headers.Range && response.status !== 206) {
|
||||
const responseError: WebDAVClientError = new Error(
|
||||
`Invalid response code for partial request: ${response.status}`
|
||||
);
|
||||
responseError.status = response.status;
|
||||
throw responseError;
|
||||
}
|
||||
if (options.callback) {
|
||||
setTimeout(() => {
|
||||
options.callback(response);
|
||||
}, 0);
|
||||
}
|
||||
return response.data as Stream.Readable;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode } from "../response";
|
||||
import { RequestOptionsCustom, Response, WebDAVClientContext } from "../types";
|
||||
|
||||
export async function customRequest(
|
||||
context: WebDAVClientContext,
|
||||
remotePath: string,
|
||||
requestOptions: RequestOptionsCustom
|
||||
): Promise<Response> {
|
||||
if (!requestOptions.url) {
|
||||
requestOptions.url = joinURL(context.remoteURL, encodePath(remotePath));
|
||||
}
|
||||
const finalOptions = prepareRequestOptions(requestOptions, context, {});
|
||||
const response = await request(finalOptions);
|
||||
handleResponseCode(context, response);
|
||||
return response;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode } from "../response";
|
||||
import { WebDAVClientContext, WebDAVMethodOptions } from "../types";
|
||||
|
||||
export async function deleteFile(
|
||||
context: WebDAVClientContext,
|
||||
filename: string,
|
||||
options: WebDAVMethodOptions = {}
|
||||
): Promise<void> {
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filename)),
|
||||
method: "DELETE"
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
import pathPosix from "path-posix";
|
||||
import { joinURL, normaliseHREF } from "../tools/url";
|
||||
import { encodePath, normalisePath } from "../tools/path";
|
||||
import { parseXML, prepareFileFromProps } from "../tools/dav";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode, processGlobFilter, processResponsePayload } from "../response";
|
||||
import {
|
||||
DAVResult,
|
||||
FileStat,
|
||||
GetDirectoryContentsOptions,
|
||||
ResponseDataDetailed,
|
||||
WebDAVClientContext
|
||||
} from "../types";
|
||||
|
||||
export async function getDirectoryContents(
|
||||
context: WebDAVClientContext,
|
||||
remotePath: string,
|
||||
options: GetDirectoryContentsOptions = {}
|
||||
): Promise<Array<FileStat> | ResponseDataDetailed<Array<FileStat>>> {
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(remotePath), "/"),
|
||||
method: "PROPFIND",
|
||||
headers: {
|
||||
Accept: "text/plain",
|
||||
Depth: options.deep ? "infinity" : "1"
|
||||
},
|
||||
responseType: "text"
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
const davResp = await parseXML(response.data as string);
|
||||
let files = getDirectoryFiles(davResp, context.remotePath, remotePath, options.details);
|
||||
if (options.glob) {
|
||||
files = processGlobFilter(files, options.glob);
|
||||
}
|
||||
return processResponsePayload(response, files, options.details);
|
||||
}
|
||||
|
||||
function getDirectoryFiles(
|
||||
result: DAVResult,
|
||||
serverBasePath: string,
|
||||
requestPath: string,
|
||||
isDetailed: boolean = false
|
||||
): Array<FileStat> {
|
||||
const serverBase = pathPosix.join(serverBasePath, "/");
|
||||
// Extract the response items (directory contents)
|
||||
const {
|
||||
multistatus: { response: responseItems }
|
||||
} = result;
|
||||
return (
|
||||
responseItems
|
||||
// Map all items to a consistent output structure (results)
|
||||
.map(item => {
|
||||
// HREF is the file path (in full)
|
||||
const href = normaliseHREF(item.href);
|
||||
// Each item should contain a stat object
|
||||
const {
|
||||
propstat: { prop: props }
|
||||
} = item;
|
||||
// Process the true full filename (minus the base server path)
|
||||
const filename =
|
||||
serverBase === "/"
|
||||
? decodeURIComponent(normalisePath(href))
|
||||
: decodeURIComponent(normalisePath(pathPosix.relative(serverBase, href)));
|
||||
return prepareFileFromProps(props, filename, isDetailed);
|
||||
})
|
||||
// Filter out the item pointing to the current directory (not needed)
|
||||
.filter(
|
||||
item =>
|
||||
item.basename &&
|
||||
(item.type === "file" || item.filename !== requestPath.replace(/\/$/, ""))
|
||||
)
|
||||
);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import { getStat } from "./stat";
|
||||
import { WebDAVClientContext, WebDAVMethodOptions } from "../types";
|
||||
|
||||
export async function exists(
|
||||
context: WebDAVClientContext,
|
||||
remotePath: string,
|
||||
options: WebDAVMethodOptions = {}
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
await getStat(context, remotePath, options);
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (err.status === 404) {
|
||||
return false;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
import { Layerr } from "layerr";
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { fromBase64 } from "../tools/encode";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode, processResponsePayload } from "../response";
|
||||
import {
|
||||
AuthType,
|
||||
BufferLike,
|
||||
ErrorCode,
|
||||
GetFileContentsOptions,
|
||||
ResponseDataDetailed,
|
||||
WebDAVClientContext
|
||||
} from "../types";
|
||||
|
||||
const TRANSFORM_RETAIN_FORMAT = (v: any) => v;
|
||||
|
||||
export async function getFileContents(
|
||||
context: WebDAVClientContext,
|
||||
filePath: string,
|
||||
options: GetFileContentsOptions = {}
|
||||
): Promise<BufferLike | string | ResponseDataDetailed<BufferLike | string>> {
|
||||
const { format = "binary" } = options;
|
||||
if (format !== "binary" && format !== "text") {
|
||||
throw new Layerr(
|
||||
{
|
||||
info: {
|
||||
code: ErrorCode.InvalidOutputFormat
|
||||
}
|
||||
},
|
||||
`Invalid output format: ${format}`
|
||||
);
|
||||
}
|
||||
return format === "text"
|
||||
? getFileContentsString(context, filePath, options)
|
||||
: getFileContentsBuffer(context, filePath, options);
|
||||
}
|
||||
|
||||
async function getFileContentsBuffer(
|
||||
context: WebDAVClientContext,
|
||||
filePath: string,
|
||||
options: GetFileContentsOptions = {}
|
||||
): Promise<BufferLike | ResponseDataDetailed<BufferLike>> {
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filePath)),
|
||||
method: "GET",
|
||||
responseType: "arraybuffer"
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
return processResponsePayload(response, response.data as BufferLike, options.details);
|
||||
}
|
||||
|
||||
async function getFileContentsString(
|
||||
context: WebDAVClientContext,
|
||||
filePath: string,
|
||||
options: GetFileContentsOptions = {}
|
||||
): Promise<string | ResponseDataDetailed<string>> {
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filePath)),
|
||||
method: "GET",
|
||||
responseType: "text",
|
||||
transformResponse: [TRANSFORM_RETAIN_FORMAT]
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
return processResponsePayload(response, response.data as string, options.details);
|
||||
}
|
||||
|
||||
export function getFileDownloadLink(context: WebDAVClientContext, filePath: string): string {
|
||||
let url = joinURL(context.remoteURL, encodePath(filePath));
|
||||
const protocol = /^https:/i.test(url) ? "https" : "http";
|
||||
switch (context.authType) {
|
||||
case AuthType.None:
|
||||
// Do nothing
|
||||
break;
|
||||
case AuthType.Password: {
|
||||
const authPart = context.headers.Authorization.replace(/^Basic /i, "").trim();
|
||||
const authContents = fromBase64(authPart);
|
||||
url = url.replace(/^https?:\/\//, `${protocol}://${authContents}@`);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Layerr(
|
||||
{
|
||||
info: {
|
||||
code: ErrorCode.LinkUnsupportedAuthType
|
||||
}
|
||||
},
|
||||
`Unsupported auth type for file link: ${context.authType}`
|
||||
);
|
||||
}
|
||||
return url;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
import { prepareRequestOptions, request } from "../request";
|
||||
import { handleResponseCode, processResponsePayload } from "../response";
|
||||
import { parseXML } from "../tools/dav";
|
||||
import { joinURL } from "../tools/url";
|
||||
import { parseQuota } from "../tools/quota";
|
||||
import { DiskQuota, GetQuotaOptions, ResponseDataDetailed, WebDAVClientContext } from "../types";
|
||||
|
||||
export async function getQuota(
|
||||
context: WebDAVClientContext,
|
||||
options: GetQuotaOptions = {}
|
||||
): Promise<DiskQuota | null | ResponseDataDetailed<DiskQuota | null>> {
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, "/"),
|
||||
method: "PROPFIND",
|
||||
headers: {
|
||||
Accept: "text/plain",
|
||||
Depth: "0"
|
||||
},
|
||||
responseType: "text"
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
const result = await parseXML(response.data as string);
|
||||
const quota = parseQuota(result);
|
||||
return processResponsePayload(response, quota, options.details);
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
import nestedProp from "nested-property";
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { generateLockXML, parseGenericResponse } from "../tools/xml";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { createErrorFromResponse, handleResponseCode } from "../response";
|
||||
import {
|
||||
Headers,
|
||||
LockOptions,
|
||||
LockResponse,
|
||||
WebDAVClientContext,
|
||||
WebDAVMethodOptions
|
||||
} from "../types";
|
||||
|
||||
const DEFAULT_TIMEOUT = "Infinite, Second-4100000000";
|
||||
|
||||
export async function lock(
|
||||
context: WebDAVClientContext,
|
||||
path: string,
|
||||
options: LockOptions = {}
|
||||
): Promise<LockResponse> {
|
||||
const { refreshToken, timeout = DEFAULT_TIMEOUT } = options;
|
||||
const headers: Headers = {
|
||||
Accept: "text/plain,application/xml",
|
||||
Timeout: timeout
|
||||
};
|
||||
if (refreshToken) {
|
||||
headers.If = refreshToken;
|
||||
}
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(path)),
|
||||
method: "LOCK",
|
||||
headers,
|
||||
data: generateLockXML(context.contactHref),
|
||||
responseType: "text"
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
const lockPayload = parseGenericResponse(response.data as string);
|
||||
const token = nestedProp.get(lockPayload, "prop.lockdiscovery.activelock.locktoken.href");
|
||||
const serverTimeout = nestedProp.get(lockPayload, "prop.lockdiscovery.activelock.timeout");
|
||||
if (!token) {
|
||||
const err = createErrorFromResponse(response, "No lock token received: ");
|
||||
throw err;
|
||||
}
|
||||
return {
|
||||
token,
|
||||
serverTimeout
|
||||
};
|
||||
}
|
||||
|
||||
export async function unlock(
|
||||
context: WebDAVClientContext,
|
||||
path: string,
|
||||
token: string,
|
||||
options: WebDAVMethodOptions = {}
|
||||
): Promise<void> {
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(path)),
|
||||
method: "UNLOCK",
|
||||
headers: {
|
||||
"Lock-Token": token
|
||||
}
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
if (response.status !== 204 && response.status !== 200) {
|
||||
const err = createErrorFromResponse(response);
|
||||
throw err;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode } from "../response";
|
||||
import { WebDAVClientContext, WebDAVMethodOptions } from "../types";
|
||||
|
||||
export async function moveFile(
|
||||
context: WebDAVClientContext,
|
||||
filename: string,
|
||||
destination: string,
|
||||
options: WebDAVMethodOptions = {}
|
||||
): Promise<void> {
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filename)),
|
||||
method: "MOVE",
|
||||
headers: {
|
||||
Destination: joinURL(context.remoteURL, encodePath(destination))
|
||||
}
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
import { Layerr } from "layerr";
|
||||
import Stream from "stream";
|
||||
import { fromBase64 } from "../tools/encode";
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode } from "../response";
|
||||
import { calculateDataLength } from "../tools/size";
|
||||
import {
|
||||
AuthType,
|
||||
BufferLike,
|
||||
ErrorCode,
|
||||
Headers,
|
||||
PutFileContentsOptions,
|
||||
WebDAVClientContext,
|
||||
WebDAVClientError
|
||||
} from "../types";
|
||||
|
||||
declare var WEB: boolean;
|
||||
|
||||
export async function putFileContents(
|
||||
context: WebDAVClientContext,
|
||||
filePath: string,
|
||||
data: string | BufferLike | Stream.Readable,
|
||||
options: PutFileContentsOptions = {}
|
||||
): Promise<boolean> {
|
||||
const { contentLength = true, overwrite = true } = options;
|
||||
const headers: Headers = {
|
||||
"Content-Type": "application/octet-stream"
|
||||
};
|
||||
if (typeof WEB === "undefined") {
|
||||
// Skip, no content-length
|
||||
} else if (contentLength === false) {
|
||||
// Skip, disabled
|
||||
} else if (typeof contentLength === "number") {
|
||||
headers["Content-Length"] = `${contentLength}`;
|
||||
} else {
|
||||
headers["Content-Length"] = `${calculateDataLength(data as string | BufferLike)}`;
|
||||
}
|
||||
if (!overwrite) {
|
||||
headers["If-None-Match"] = "*";
|
||||
}
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filePath)),
|
||||
method: "PUT",
|
||||
headers,
|
||||
data
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
try {
|
||||
handleResponseCode(context, response);
|
||||
} catch (err) {
|
||||
const error = err as WebDAVClientError;
|
||||
if (error.status === 412 && !overwrite) {
|
||||
return false;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function getFileUploadLink(context: WebDAVClientContext, filePath: string): string {
|
||||
let url: string = `${joinURL(
|
||||
context.remoteURL,
|
||||
encodePath(filePath)
|
||||
)}?Content-Type=application/octet-stream`;
|
||||
const protocol = /^https:/i.test(url) ? "https" : "http";
|
||||
switch (context.authType) {
|
||||
case AuthType.None:
|
||||
// Do nothing
|
||||
break;
|
||||
case AuthType.Password: {
|
||||
const authPart = context.headers.Authorization.replace(/^Basic /i, "").trim();
|
||||
const authContents = fromBase64(authPart);
|
||||
url = url.replace(/^https?:\/\//, `${protocol}://${authContents}@`);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Layerr(
|
||||
{
|
||||
info: {
|
||||
code: ErrorCode.LinkUnsupportedAuthType
|
||||
}
|
||||
},
|
||||
`Unsupported auth type for file link: ${context.authType}`
|
||||
);
|
||||
}
|
||||
return url;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
import { parseStat, parseXML } from "../tools/dav";
|
||||
import { joinURL } from "../tools/url";
|
||||
import { encodePath } from "../tools/path";
|
||||
import { request, prepareRequestOptions } from "../request";
|
||||
import { handleResponseCode, processResponsePayload } from "../response";
|
||||
import { FileStat, ResponseDataDetailed, StatOptions, WebDAVClientContext } from "../types";
|
||||
|
||||
export async function getStat(
|
||||
context: WebDAVClientContext,
|
||||
filename: string,
|
||||
options: StatOptions = {}
|
||||
): Promise<FileStat | ResponseDataDetailed<FileStat>> {
|
||||
const { details: isDetailed = false } = options;
|
||||
const requestOptions = prepareRequestOptions(
|
||||
{
|
||||
url: joinURL(context.remoteURL, encodePath(filename)),
|
||||
method: "PROPFIND",
|
||||
headers: {
|
||||
Accept: "text/plain,application/xml",
|
||||
Depth: "0"
|
||||
},
|
||||
responseType: "text"
|
||||
},
|
||||
context,
|
||||
options
|
||||
);
|
||||
const response = await request(requestOptions);
|
||||
handleResponseCode(context, response);
|
||||
const result = await parseXML(response.data as string);
|
||||
const stat = parseStat(result, filename, isDetailed);
|
||||
return processResponsePayload(response, stat, isDetailed);
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
import axios from "axios";
|
||||
import { getPatcher } from "./compat/patcher";
|
||||
import { generateDigestAuthHeader, parseDigestAuth } from "./auth/digest";
|
||||
import { cloneShallow, merge } from "./tools/merge";
|
||||
import { mergeHeaders } from "./tools/headers";
|
||||
import {
|
||||
RequestOptionsCustom,
|
||||
RequestOptionsWithState,
|
||||
RequestOptions,
|
||||
Response,
|
||||
WebDAVClientContext,
|
||||
WebDAVMethodOptions
|
||||
} from "./types";
|
||||
|
||||
function _request(requestOptions: RequestOptions) {
|
||||
return getPatcher().patchInline(
|
||||
"request",
|
||||
(options: RequestOptions) => axios(options as any),
|
||||
requestOptions
|
||||
);
|
||||
}
|
||||
|
||||
export function prepareRequestOptions(
|
||||
requestOptions: RequestOptionsCustom | RequestOptionsWithState,
|
||||
context: WebDAVClientContext,
|
||||
userOptions: WebDAVMethodOptions
|
||||
): RequestOptionsWithState {
|
||||
const finalOptions = cloneShallow(requestOptions) as RequestOptionsWithState;
|
||||
finalOptions.headers = mergeHeaders(
|
||||
context.headers,
|
||||
finalOptions.headers || {},
|
||||
userOptions.headers || {}
|
||||
);
|
||||
if (typeof userOptions.data !== "undefined") {
|
||||
finalOptions.data = userOptions.data;
|
||||
}
|
||||
if (context.httpAgent) {
|
||||
finalOptions.httpAgent = context.httpAgent;
|
||||
}
|
||||
if (context.httpsAgent) {
|
||||
finalOptions.httpsAgent = context.httpsAgent;
|
||||
}
|
||||
if (context.digest) {
|
||||
finalOptions._digest = context.digest;
|
||||
}
|
||||
if (typeof context.withCredentials === "boolean") {
|
||||
finalOptions.withCredentials = context.withCredentials;
|
||||
}
|
||||
if (context.maxContentLength) {
|
||||
finalOptions.maxContentLength = context.maxContentLength;
|
||||
}
|
||||
if (context.maxBodyLength) {
|
||||
finalOptions.maxBodyLength = context.maxBodyLength;
|
||||
}
|
||||
if (userOptions.hasOwnProperty("onUploadProgress")) {
|
||||
finalOptions.onUploadProgress = userOptions["onUploadProgress"];
|
||||
}
|
||||
// Take full control of all response status codes
|
||||
finalOptions.validateStatus = () => true;
|
||||
return finalOptions;
|
||||
}
|
||||
|
||||
export function request(requestOptions: RequestOptionsWithState): Promise<Response> {
|
||||
// Client not configured for digest authentication
|
||||
if (!requestOptions._digest) {
|
||||
return _request(requestOptions);
|
||||
}
|
||||
|
||||
// Remove client's digest authentication object from request options
|
||||
const _digest = requestOptions._digest;
|
||||
delete requestOptions._digest;
|
||||
|
||||
// If client is already using digest authentication, include the digest authorization header
|
||||
if (_digest.hasDigestAuth) {
|
||||
requestOptions = merge(requestOptions, {
|
||||
headers: {
|
||||
Authorization: generateDigestAuthHeader(requestOptions, _digest)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Perform the request and handle digest authentication
|
||||
return _request(requestOptions).then(function(response: Response) {
|
||||
if (response.status == 401) {
|
||||
_digest.hasDigestAuth = parseDigestAuth(response, _digest);
|
||||
|
||||
if (_digest.hasDigestAuth) {
|
||||
requestOptions = merge(requestOptions, {
|
||||
headers: {
|
||||
Authorization: generateDigestAuthHeader(requestOptions, _digest)
|
||||
}
|
||||
});
|
||||
|
||||
return _request(requestOptions).then(function(response2: Response) {
|
||||
if (response2.status == 401) {
|
||||
_digest.hasDigestAuth = false;
|
||||
} else {
|
||||
_digest.nc++;
|
||||
}
|
||||
return response2;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
_digest.nc++;
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import minimatch from "minimatch";
|
||||
import {
|
||||
FileStat,
|
||||
Response,
|
||||
ResponseDataDetailed,
|
||||
WebDAVClientContext,
|
||||
WebDAVClientError
|
||||
} from "./types";
|
||||
|
||||
export function createErrorFromResponse(response: Response, prefix: string = ""): Error {
|
||||
const err: WebDAVClientError = new Error(
|
||||
`${prefix}Invalid response: ${response.status} ${response.statusText}`
|
||||
) as WebDAVClientError;
|
||||
err.status = response.status;
|
||||
err.response = response;
|
||||
return err;
|
||||
}
|
||||
|
||||
export function handleResponseCode(context: WebDAVClientContext, response: Response): Response {
|
||||
const { status } = response;
|
||||
if (status === 401 && context.digest) return response;
|
||||
if (status >= 400) {
|
||||
const err = createErrorFromResponse(response);
|
||||
throw err;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
export function processGlobFilter(files: Array<FileStat>, glob: string): Array<FileStat> {
|
||||
return files.filter(file => minimatch(file.filename, glob, { matchBase: true }));
|
||||
}
|
||||
|
||||
export function processResponsePayload<T>(
|
||||
response: Response,
|
||||
data: T,
|
||||
isDetailed: boolean = false
|
||||
): ResponseDataDetailed<T> | T {
|
||||
return isDetailed
|
||||
? {
|
||||
data,
|
||||
headers: response.headers || {},
|
||||
status: response.status,
|
||||
statusText: response.statusText
|
||||
}
|
||||
: data;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import md5 from "md5";
|
||||
|
||||
export function ha1Compute(
|
||||
algorithm: string,
|
||||
user: string,
|
||||
realm: string,
|
||||
pass: string,
|
||||
nonce: string,
|
||||
cnonce: string
|
||||
): string {
|
||||
const ha1 = md5(`${user}:${realm}:${pass}`) as string;
|
||||
if (algorithm && algorithm.toLowerCase() === "md5-sess") {
|
||||
return md5(`${ha1}:${nonce}:${cnonce}`) as string;
|
||||
}
|
||||
return ha1;
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
import path from "path-posix";
|
||||
import xmlParser from "fast-xml-parser";
|
||||
import nestedProp from "nested-property";
|
||||
import { decodeHTMLEntities } from "./encode";
|
||||
import { normalisePath } from "./path";
|
||||
import {
|
||||
DAVResult,
|
||||
DAVResultRaw,
|
||||
DAVResultResponse,
|
||||
DAVResultResponseProps,
|
||||
DiskQuotaAvailable,
|
||||
FileStat,
|
||||
WebDAVClientError
|
||||
} from "../types";
|
||||
|
||||
enum PropertyType {
|
||||
Array = "array",
|
||||
Object = "object",
|
||||
Original = "original"
|
||||
}
|
||||
|
||||
function getPropertyOfType(
|
||||
obj: Object,
|
||||
prop: string,
|
||||
type: PropertyType = PropertyType.Original
|
||||
): any {
|
||||
const val = nestedProp.get(obj, prop);
|
||||
if (type === "array" && Array.isArray(val) === false) {
|
||||
return [val];
|
||||
} else if (type === "object" && Array.isArray(val)) {
|
||||
return val[0];
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
function normaliseResponse(response: any): DAVResultResponse {
|
||||
const output = Object.assign({}, response);
|
||||
nestedProp.set(output, "propstat", getPropertyOfType(output, "propstat", PropertyType.Object));
|
||||
nestedProp.set(
|
||||
output,
|
||||
"propstat.prop",
|
||||
getPropertyOfType(output, "propstat.prop", PropertyType.Object)
|
||||
);
|
||||
return output;
|
||||
}
|
||||
|
||||
function normaliseResult(result: DAVResultRaw): DAVResult {
|
||||
const { multistatus } = result;
|
||||
if (multistatus === "") {
|
||||
return {
|
||||
multistatus: {
|
||||
response: []
|
||||
}
|
||||
};
|
||||
}
|
||||
if (!multistatus) {
|
||||
throw new Error("Invalid response: No root multistatus found");
|
||||
}
|
||||
const output: any = {
|
||||
multistatus: Array.isArray(multistatus) ? multistatus[0] : multistatus
|
||||
};
|
||||
nestedProp.set(
|
||||
output,
|
||||
"multistatus.response",
|
||||
getPropertyOfType(output, "multistatus.response", PropertyType.Array)
|
||||
);
|
||||
nestedProp.set(
|
||||
output,
|
||||
"multistatus.response",
|
||||
nestedProp.get(output, "multistatus.response").map(response => normaliseResponse(response))
|
||||
);
|
||||
return output as DAVResult;
|
||||
}
|
||||
|
||||
export function parseXML(xml: string): Promise<DAVResult> {
|
||||
return new Promise(resolve => {
|
||||
const result = xmlParser.parse(xml, {
|
||||
arrayMode: false,
|
||||
ignoreNameSpace: true
|
||||
// // We don't use the processors here as decoding is done manually
|
||||
// // later on - decoding early would break some path checks.
|
||||
// attrValueProcessor: val => decodeHTMLEntities(decodeURIComponent(val)),
|
||||
// tagValueProcessor: val => decodeHTMLEntities(decodeURIComponent(val))
|
||||
});
|
||||
resolve(normaliseResult(result));
|
||||
});
|
||||
}
|
||||
|
||||
export function prepareFileFromProps(
|
||||
props: DAVResultResponseProps,
|
||||
rawFilename: string,
|
||||
isDetailed: boolean = false
|
||||
): FileStat {
|
||||
// Last modified time, raw size, item type and mime
|
||||
const {
|
||||
getlastmodified: lastMod = null,
|
||||
getcontentlength: rawSize = "0",
|
||||
resourcetype: resourceType = null,
|
||||
getcontenttype: mimeType = null,
|
||||
getetag: etag = null
|
||||
} = props;
|
||||
const type =
|
||||
resourceType &&
|
||||
typeof resourceType === "object" &&
|
||||
typeof resourceType.collection !== "undefined"
|
||||
? "directory"
|
||||
: "file";
|
||||
const filename = decodeHTMLEntities(rawFilename);
|
||||
const stat: FileStat = {
|
||||
filename,
|
||||
basename: path.basename(filename),
|
||||
lastmod: lastMod,
|
||||
size: parseInt(rawSize, 10),
|
||||
type,
|
||||
etag: typeof etag === "string" ? etag.replace(/"/g, "") : null
|
||||
};
|
||||
if (type === "file") {
|
||||
stat.mime = mimeType && typeof mimeType === "string" ? mimeType.split(";")[0] : "";
|
||||
}
|
||||
if (isDetailed) {
|
||||
stat.props = props;
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
export function parseStat(
|
||||
result: DAVResult,
|
||||
filename: string,
|
||||
isDetailed: boolean = false
|
||||
): FileStat {
|
||||
let responseItem: DAVResultResponse = null;
|
||||
try {
|
||||
responseItem = result.multistatus.response[0];
|
||||
} catch (e) {
|
||||
/* ignore */
|
||||
}
|
||||
if (!responseItem) {
|
||||
throw new Error("Failed getting item stat: bad response");
|
||||
}
|
||||
const {
|
||||
propstat: { prop: props, status: statusLine }
|
||||
} = responseItem;
|
||||
|
||||
// As defined in https://tools.ietf.org/html/rfc2068#section-6.1
|
||||
const [_, statusCodeStr, statusText] = statusLine.split(" ", 3);
|
||||
const statusCode = parseInt(statusCodeStr, 10);
|
||||
if (statusCode >= 400) {
|
||||
const err: WebDAVClientError = new Error(
|
||||
`Invalid response: ${statusCode} ${statusText}`
|
||||
) as WebDAVClientError;
|
||||
err.status = statusCode;
|
||||
throw err;
|
||||
}
|
||||
|
||||
const filePath = normalisePath(filename);
|
||||
return prepareFileFromProps(props, filePath, isDetailed);
|
||||
}
|
||||
|
||||
export function translateDiskSpace(value: string | number): DiskQuotaAvailable {
|
||||
switch (value.toString()) {
|
||||
case "-3":
|
||||
return "unlimited";
|
||||
case "-2":
|
||||
/* falls-through */
|
||||
case "-1":
|
||||
// -1 is non-computed
|
||||
return "unknown";
|
||||
default:
|
||||
return parseInt(value as string, 10);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { decode, encode } from "base-64";
|
||||
|
||||
declare var WEB: boolean;
|
||||
|
||||
export function decodeHTMLEntities(text: string): string {
|
||||
if (typeof WEB === "undefined") {
|
||||
// Node
|
||||
const he = require("he");
|
||||
return he.decode(text);
|
||||
} else {
|
||||
// Nasty browser way
|
||||
const txt = document.createElement("textarea");
|
||||
txt.innerHTML = text;
|
||||
return txt.value;
|
||||
}
|
||||
}
|
||||
|
||||
export function fromBase64(text: string): string {
|
||||
return decode(text);
|
||||
}
|
||||
|
||||
export function toBase64(text: string): string {
|
||||
return encode(text);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import { Headers } from "../types";
|
||||
|
||||
export function mergeHeaders(...headerPayloads: Headers[]): Headers {
|
||||
if (headerPayloads.length === 0) return {};
|
||||
const headerKeys = {};
|
||||
return headerPayloads.reduce((output: Headers, headers: Headers) => {
|
||||
Object.keys(headers).forEach(header => {
|
||||
const lowerHeader = header.toLowerCase();
|
||||
if (headerKeys.hasOwnProperty(lowerHeader)) {
|
||||
output[headerKeys[lowerHeader]] = headers[header];
|
||||
} else {
|
||||
headerKeys[lowerHeader] = header;
|
||||
output[header] = headers[header];
|
||||
}
|
||||
});
|
||||
return output;
|
||||
}, {});
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
export function cloneShallow<T extends Object>(obj: T): T {
|
||||
return isPlainObject(obj)
|
||||
? Object.assign({}, obj)
|
||||
: Object.setPrototypeOf(Object.assign({}, obj), Object.getPrototypeOf(obj));
|
||||
}
|
||||
|
||||
function isPlainObject(obj: Object | any): boolean {
|
||||
if (
|
||||
typeof obj !== "object" ||
|
||||
obj === null ||
|
||||
Object.prototype.toString.call(obj) != "[object Object]"
|
||||
) {
|
||||
// Not an object
|
||||
return false;
|
||||
}
|
||||
if (Object.getPrototypeOf(obj) === null) {
|
||||
return true;
|
||||
}
|
||||
let proto = obj;
|
||||
// Find the prototype
|
||||
while (Object.getPrototypeOf(proto) !== null) {
|
||||
proto = Object.getPrototypeOf(proto);
|
||||
}
|
||||
return Object.getPrototypeOf(obj) === proto;
|
||||
}
|
||||
|
||||
export function merge(...args: Object[]) {
|
||||
let output = null,
|
||||
items = [...args];
|
||||
while (items.length > 0) {
|
||||
const nextItem = items.shift();
|
||||
if (!output) {
|
||||
output = cloneShallow(nextItem);
|
||||
} else {
|
||||
output = mergeObjects(output, nextItem);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
function mergeObjects(obj1: Object, obj2: Object): Object {
|
||||
const output = cloneShallow(obj1);
|
||||
Object.keys(obj2).forEach(key => {
|
||||
if (!output.hasOwnProperty(key)) {
|
||||
output[key] = obj2[key];
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(obj2[key])) {
|
||||
output[key] = Array.isArray(output[key])
|
||||
? [...output[key], ...obj2[key]]
|
||||
: [...obj2[key]];
|
||||
} else if (typeof obj2[key] === "object" && !!obj2[key]) {
|
||||
output[key] =
|
||||
typeof output[key] === "object" && !!output[key]
|
||||
? mergeObjects(output[key], obj2[key])
|
||||
: cloneShallow(obj2[key]);
|
||||
} else {
|
||||
output[key] = obj2[key];
|
||||
}
|
||||
});
|
||||
return output;
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import { dirname } from "path-posix";
|
||||
|
||||
const SEP_PATH_POSIX = "__PATH_SEPARATOR_POSIX__";
|
||||
const SEP_PATH_WINDOWS = "__PATH_SEPARATOR_WINDOWS__";
|
||||
|
||||
export function encodePath(path) {
|
||||
const replaced = path.replace(/\//g, SEP_PATH_POSIX).replace(/\\\\/g, SEP_PATH_WINDOWS);
|
||||
const formatted = encodeURIComponent(replaced);
|
||||
return formatted
|
||||
.split(SEP_PATH_WINDOWS)
|
||||
.join("\\\\")
|
||||
.split(SEP_PATH_POSIX)
|
||||
.join("/");
|
||||
}
|
||||
|
||||
export function getAllDirectories(path: string): Array<string> {
|
||||
if (!path || path === "/") return [];
|
||||
let currentPath = path;
|
||||
const output: Array<string> = [];
|
||||
do {
|
||||
output.push(currentPath);
|
||||
currentPath = dirname(currentPath);
|
||||
} while (currentPath && currentPath !== "/");
|
||||
return output;
|
||||
}
|
||||
|
||||
export function normalisePath(pathStr: string): string {
|
||||
let normalisedPath = pathStr;
|
||||
if (normalisedPath[0] !== "/") {
|
||||
normalisedPath = "/" + normalisedPath;
|
||||
}
|
||||
if (/^.+\/$/.test(normalisedPath)) {
|
||||
normalisedPath = normalisedPath.substr(0, normalisedPath.length - 1);
|
||||
}
|
||||
return normalisedPath;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import { translateDiskSpace } from "./dav";
|
||||
import { DAVResult, DiskQuota } from "../types";
|
||||
|
||||
export function parseQuota(result: DAVResult): DiskQuota | null {
|
||||
try {
|
||||
const [responseItem] = result.multistatus.response;
|
||||
const {
|
||||
propstat: {
|
||||
prop: { "quota-used-bytes": quotaUsed, "quota-available-bytes": quotaAvail }
|
||||
}
|
||||
} = responseItem;
|
||||
return typeof quotaUsed !== "undefined" && typeof quotaAvail !== "undefined"
|
||||
? {
|
||||
used: parseInt(quotaUsed, 10),
|
||||
available: translateDiskSpace(quotaAvail)
|
||||
}
|
||||
: null;
|
||||
} catch (err) {
|
||||
/* ignore */
|
||||
}
|
||||
return null;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import { Layerr } from "layerr";
|
||||
import { isArrayBuffer } from "../compat/arrayBuffer";
|
||||
import { isBuffer } from "../compat/buffer";
|
||||
import { BufferLike, ErrorCode } from "../types";
|
||||
|
||||
export function calculateDataLength(data: string | BufferLike): number {
|
||||
if (isArrayBuffer(data)) {
|
||||
return (<ArrayBuffer>data).byteLength;
|
||||
} else if (isBuffer(data)) {
|
||||
return (<Buffer>data).length;
|
||||
} else if (typeof data === "string") {
|
||||
return (<string>data).length;
|
||||
}
|
||||
throw new Layerr(
|
||||
{
|
||||
info: {
|
||||
code: ErrorCode.DataTypeNoLength
|
||||
}
|
||||
},
|
||||
"Cannot calculate data length: Invalid type"
|
||||
);
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
import URL from "url-parse";
|
||||
import _joinURL from "url-join";
|
||||
import { normalisePath } from "./path";
|
||||
|
||||
export function extractURLPath(fullURL: string): string {
|
||||
const url = new URL(fullURL);
|
||||
let urlPath = url.pathname;
|
||||
if (urlPath.length <= 0) {
|
||||
urlPath = "/";
|
||||
}
|
||||
return normalisePath(urlPath);
|
||||
}
|
||||
|
||||
export function joinURL(...parts: Array<string>): string {
|
||||
return _joinURL(
|
||||
parts.reduce((output, nextPart, partIndex) => {
|
||||
if (
|
||||
partIndex === 0 ||
|
||||
nextPart !== "/" ||
|
||||
(nextPart === "/" && output[output.length - 1] !== "/")
|
||||
) {
|
||||
output.push(nextPart);
|
||||
}
|
||||
return output;
|
||||
}, [])
|
||||
);
|
||||
}
|
||||
|
||||
export function normaliseHREF(href: string): string {
|
||||
const normalisedHref = href.replace(/^https?:\/\/[^\/]+/, "");
|
||||
return normalisedHref;
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
import xmlParser, { j2xParser as XMLParser } from "fast-xml-parser";
|
||||
|
||||
export function generateLockXML(ownerHREF: string): string {
|
||||
return getParser().parse(
|
||||
namespace(
|
||||
{
|
||||
lockinfo: {
|
||||
"@_xmlns:d": "DAV:",
|
||||
lockscope: {
|
||||
exclusive: {}
|
||||
},
|
||||
locktype: {
|
||||
write: {}
|
||||
},
|
||||
owner: {
|
||||
href: ownerHREF
|
||||
}
|
||||
}
|
||||
},
|
||||
"d"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getParser(): XMLParser {
|
||||
return new XMLParser({
|
||||
attributeNamePrefix: "@_",
|
||||
format: true,
|
||||
ignoreAttributes: false,
|
||||
supressEmptyNode: true
|
||||
});
|
||||
}
|
||||
|
||||
function namespace<T extends Object>(obj: T, ns: string): T {
|
||||
const copy = { ...obj };
|
||||
for (const key in copy) {
|
||||
if (copy[key] && typeof copy[key] === "object" && key.indexOf(":") === -1) {
|
||||
copy[`${ns}:${key}`] = namespace(copy[key], ns);
|
||||
delete copy[key];
|
||||
} else if (/^@_/.test(key) === false) {
|
||||
copy[`${ns}:${key}`] = copy[key];
|
||||
delete copy[key];
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
export function parseGenericResponse(xml: string): Object {
|
||||
return xmlParser.parse(xml, {
|
||||
arrayMode: false,
|
||||
ignoreNameSpace: true,
|
||||
parseAttributeValue: true,
|
||||
parseNodeValue: true
|
||||
});
|
||||
}
|
@ -0,0 +1,288 @@
|
||||
import Stream from "stream";
|
||||
|
||||
export type AuthHeader = string;
|
||||
|
||||
export enum AuthType {
|
||||
Digest = "digest",
|
||||
None = "none",
|
||||
Password = "password",
|
||||
Token = "token"
|
||||
}
|
||||
|
||||
export type BufferLike = Buffer | ArrayBuffer;
|
||||
|
||||
export interface CreateDirectoryOptions extends WebDAVMethodOptions {
|
||||
recursive?: boolean;
|
||||
}
|
||||
|
||||
export interface CreateReadStreamOptions extends WebDAVMethodOptions {
|
||||
callback?: (response: Response) => void;
|
||||
range?: {
|
||||
start: number;
|
||||
end?: number;
|
||||
};
|
||||
}
|
||||
|
||||
export type CreateWriteStreamCallback = (response: Response) => void;
|
||||
|
||||
export interface CreateWriteStreamOptions extends WebDAVMethodOptions {
|
||||
overwrite?: boolean;
|
||||
}
|
||||
|
||||
export interface DAVResultResponse {
|
||||
href: string;
|
||||
propstat: {
|
||||
prop: DAVResultResponseProps;
|
||||
status: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DAVResultResponseProps {
|
||||
displayname: string;
|
||||
resourcetype: {
|
||||
collection?: boolean;
|
||||
};
|
||||
getlastmodified?: string;
|
||||
getetag?: string;
|
||||
getcontentlength?: string;
|
||||
getcontenttype?: string;
|
||||
"quota-available-bytes"?: any;
|
||||
"quota-used-bytes"?: string;
|
||||
}
|
||||
|
||||
export interface DAVResult {
|
||||
multistatus: {
|
||||
response: Array<DAVResultResponse>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DAVResultRawMultistatus {
|
||||
response: DAVResultResponse | [DAVResultResponse];
|
||||
}
|
||||
|
||||
export interface DAVResultRaw {
|
||||
multistatus: "" | DAVResultRawMultistatus | [DAVResultRawMultistatus];
|
||||
}
|
||||
|
||||
export interface DigestContext {
|
||||
username: string;
|
||||
password: string;
|
||||
nc: number;
|
||||
algorithm: string;
|
||||
hasDigestAuth: boolean;
|
||||
cnonce?: string;
|
||||
nonce?: string;
|
||||
realm?: string;
|
||||
qop?: string;
|
||||
opaque?: string;
|
||||
}
|
||||
|
||||
export interface DiskQuota {
|
||||
used: number;
|
||||
available: DiskQuotaAvailable;
|
||||
}
|
||||
|
||||
export type DiskQuotaAvailable = "unknown" | "unlimited" | number;
|
||||
|
||||
export enum ErrorCode {
|
||||
DataTypeNoLength = "data-type-no-length",
|
||||
InvalidAuthType = "invalid-auth-type",
|
||||
InvalidOutputFormat = "invalid-output-format",
|
||||
LinkUnsupportedAuthType = "link-unsupported-auth"
|
||||
}
|
||||
|
||||
export interface FileStat {
|
||||
filename: string;
|
||||
basename: string;
|
||||
lastmod: string;
|
||||
size: number;
|
||||
type: "file" | "directory";
|
||||
etag: string | null;
|
||||
mime?: string;
|
||||
props?: DAVResultResponseProps;
|
||||
}
|
||||
|
||||
export interface GetDirectoryContentsOptions extends WebDAVMethodOptions {
|
||||
deep?: boolean;
|
||||
details?: boolean;
|
||||
glob?: string;
|
||||
}
|
||||
|
||||
export interface GetFileContentsOptions extends WebDAVMethodOptions {
|
||||
details?: boolean;
|
||||
format?: "binary" | "text";
|
||||
}
|
||||
|
||||
export interface GetQuotaOptions extends WebDAVMethodOptions {
|
||||
details?: boolean;
|
||||
}
|
||||
|
||||
export interface Headers {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface LockOptions extends WebDAVMethodOptions {
|
||||
refreshToken?: string;
|
||||
timeout?: string;
|
||||
}
|
||||
|
||||
export interface LockResponse {
|
||||
serverTimeout: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface OAuthToken {
|
||||
access_token: string;
|
||||
token_type: string;
|
||||
refresh_token?: string;
|
||||
}
|
||||
|
||||
export interface PutFileContentsOptions extends WebDAVMethodOptions {
|
||||
contentLength?: boolean | number;
|
||||
overwrite?: boolean;
|
||||
onUploadProgress?: UploadProgressCallback;
|
||||
}
|
||||
|
||||
export type RequestDataPayload = string | Buffer | ArrayBuffer | { [key: string]: any };
|
||||
|
||||
interface RequestOptionsBase {
|
||||
data?: RequestDataPayload;
|
||||
headers?: Headers;
|
||||
httpAgent?: any;
|
||||
httpsAgent?: any;
|
||||
maxBodyLength?: number;
|
||||
maxContentLength?: number;
|
||||
maxRedirects?: number;
|
||||
method: string;
|
||||
onUploadProgress?: UploadProgressCallback;
|
||||
responseType?: string;
|
||||
transformResponse?: Array<(value: any) => any>;
|
||||
url?: string;
|
||||
validateStatus?: (status: number) => boolean;
|
||||
withCredentials?: boolean;
|
||||
}
|
||||
|
||||
export interface RequestOptionsCustom extends RequestOptionsBase {}
|
||||
|
||||
export interface RequestOptions extends RequestOptionsBase {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface RequestOptionsWithState extends RequestOptions {
|
||||
_digest?: DigestContext;
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
data: ResponseData;
|
||||
status: number;
|
||||
headers: Headers;
|
||||
statusText: string;
|
||||
}
|
||||
|
||||
export type ResponseData = string | Buffer | ArrayBuffer | Object | Array<any>;
|
||||
|
||||
export interface ResponseDataDetailed<T> {
|
||||
data: T;
|
||||
headers: Headers;
|
||||
status: number;
|
||||
statusText: string;
|
||||
}
|
||||
|
||||
export interface ResponseStatusValidator {
|
||||
(status: number): boolean;
|
||||
}
|
||||
|
||||
export interface StatOptions extends WebDAVMethodOptions {
|
||||
details?: boolean;
|
||||
}
|
||||
|
||||
export interface UploadProgress {
|
||||
loaded: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface UploadProgressCallback {
|
||||
(progress: UploadProgress): void;
|
||||
}
|
||||
|
||||
export interface WebDAVClient {
|
||||
copyFile: (filename: string, destination: string) => Promise<void>;
|
||||
createDirectory: (path: string, options?: CreateDirectoryOptions) => Promise<void>;
|
||||
createReadStream: (filename: string, options?: CreateReadStreamOptions) => Stream.Readable;
|
||||
createWriteStream: (
|
||||
filename: string,
|
||||
options?: CreateWriteStreamOptions,
|
||||
callback?: CreateWriteStreamCallback
|
||||
) => Stream.Writable;
|
||||
customRequest: (path: string, requestOptions: RequestOptionsCustom) => Promise<Response>;
|
||||
deleteFile: (filename: string) => Promise<void>;
|
||||
exists: (path: string) => Promise<boolean>;
|
||||
getDirectoryContents: (
|
||||
path: string,
|
||||
options?: GetDirectoryContentsOptions
|
||||
) => Promise<Array<FileStat> | ResponseDataDetailed<Array<FileStat>>>;
|
||||
getFileContents: (
|
||||
filename: string,
|
||||
options?: GetFileContentsOptions
|
||||
) => Promise<BufferLike | string | ResponseDataDetailed<BufferLike | string>>;
|
||||
getFileDownloadLink: (filename: string) => string;
|
||||
getFileUploadLink: (filename: string) => string;
|
||||
getHeaders: () => Headers;
|
||||
getQuota: (
|
||||
options?: GetQuotaOptions
|
||||
) => Promise<DiskQuota | null | ResponseDataDetailed<DiskQuota | null>>;
|
||||
lock: (path: string, options?: LockOptions) => Promise<LockResponse>;
|
||||
moveFile: (filename: string, destinationFilename: string) => Promise<void>;
|
||||
putFileContents: (
|
||||
filename: string,
|
||||
data: string | BufferLike | Stream.Readable,
|
||||
options?: PutFileContentsOptions
|
||||
) => Promise<boolean>;
|
||||
setHeaders: (headers: Headers) => void;
|
||||
stat: (
|
||||
path: string,
|
||||
options?: StatOptions
|
||||
) => Promise<FileStat | ResponseDataDetailed<FileStat>>;
|
||||
unlock: (path: string, token: string, options?: WebDAVMethodOptions) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface WebDAVClientContext {
|
||||
authType: AuthType;
|
||||
contactHref: string;
|
||||
digest?: DigestContext;
|
||||
headers: Headers;
|
||||
httpAgent?: any;
|
||||
httpsAgent?: any;
|
||||
maxBodyLength?: number;
|
||||
maxContentLength?: number;
|
||||
password?: string;
|
||||
remotePath: string;
|
||||
remoteURL: string;
|
||||
token?: OAuthToken;
|
||||
username?: string;
|
||||
withCredentials?: boolean;
|
||||
}
|
||||
|
||||
export interface WebDAVClientError extends Error {
|
||||
status?: number;
|
||||
response?: Response;
|
||||
}
|
||||
|
||||
export interface WebDAVClientOptions {
|
||||
authType?: AuthType;
|
||||
contactHref?: string;
|
||||
headers?: Headers;
|
||||
httpAgent?: any;
|
||||
httpsAgent?: any;
|
||||
maxBodyLength?: number;
|
||||
maxContentLength?: number;
|
||||
password?: string;
|
||||
token?: OAuthToken;
|
||||
username?: string;
|
||||
withCredentials?: boolean;
|
||||
}
|
||||
|
||||
export interface WebDAVMethodOptions {
|
||||
data?: RequestDataPayload;
|
||||
headers?: Headers;
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
!function(a,b,c){function d(c){var d=b.createElement("iframe"),e="https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid="+c.appid+"&agentid="+c.agentid+"&redirect_uri="+c.redirect_uri+"&state="+c.state+"&login_type=jssdk";e+=c.style?"&style="+c.style:"",e+=c.href?"&href="+c.href:"",d.src=e,d.frameBorder="0",d.allowTransparency="true",d.scrolling="no",d.width="300px",d.height="400px";var f=b.getElementById(c.id);f.innerHTML="",f.appendChild(d),d.onload=function(){d.contentWindow.postMessage&&a.addEventListener&&(a.addEventListener("message",function(b){
|
||||
b.data&&b.origin.indexOf("work.weixin.qq.com")>-1&&(a.location.href=b.data)}),d.contentWindow.postMessage("ask_usePostMessage","*"))}}a.WwLogin=d}(window,document);
|
@ -0,0 +1,14 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import OneIcon from '@veypi/one-icon'
|
||||
import router from '@/router'
|
||||
import { createPinia } from 'pinia'
|
||||
import 'animate.css'
|
||||
import './assets/icon.js'
|
||||
import './index.css'
|
||||
|
||||
let app = createApp(App)
|
||||
app.use(OneIcon)
|
||||
app.use(router)
|
||||
app.use(createPinia())
|
||||
app.mount('#app')
|
@ -0,0 +1,21 @@
|
||||
<style scoped>
|
||||
</style>
|
||||
<template>
|
||||
<div>404</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import {useRouter} from 'vue-router'
|
||||
import {onMounted, ref} from 'vue'
|
||||
|
||||
const router = useRouter()
|
||||
let count = ref(1)
|
||||
onMounted(() => {
|
||||
let timer = setInterval(() => {
|
||||
count.value--
|
||||
if (count.value === 0) {
|
||||
router.push('/')
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
</script>
|
@ -0,0 +1,6 @@
|
||||
<style scoped>
|
||||
</style>
|
||||
<template>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
</script>
|
@ -0,0 +1,7 @@
|
||||
<style scoped>
|
||||
</style>
|
||||
<template>
|
||||
<div @click="$router.push('/123')">home</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
</script>
|
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{vue,js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import {defineConfig} from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import {resolve} from 'path'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
host: '127.0.0.1',
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://127.0.0.1:4000/',
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
},
|
||||
'/media': {
|
||||
target: 'http://127.0.0.1:4000/',
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [vue()],
|
||||
build: {
|
||||
outDir: './dist/',
|
||||
assetsDir: './',
|
||||
rollupOptions: {
|
||||
output: {
|
||||
entryFileNames: `static/[name].[hash].js`,
|
||||
chunkFileNames: `static/[name].[hash].js`,
|
||||
assetFileNames: `static/[name].[hash].[ext]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
@ -0,0 +1,868 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/parser@^7.16.4":
|
||||
version "7.20.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8"
|
||||
integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==
|
||||
|
||||
"@esbuild/linux-loong64@0.14.54":
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028"
|
||||
integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
|
||||
"@nodelib/fs.walk@^1.2.3":
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
|
||||
integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
|
||||
dependencies:
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@types/node@^17.0.24":
|
||||
version "17.0.45"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
|
||||
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
|
||||
|
||||
"@veypi/one-icon@2":
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@veypi/one-icon/-/one-icon-2.0.6.tgz#158c692971848524cd59db1a61d88805d2e45646"
|
||||
integrity sha512-ldfRE8vDSqZEFk+94wqieWP4s1Mz1EDG1VhXmckWI0cat2RT/Kk9hcICImkLhsOmhNRX7nwxSU4UbUiJVix/Jw==
|
||||
dependencies:
|
||||
vue "^3.2.20"
|
||||
|
||||
"@vitejs/plugin-vue@^2.3.1":
|
||||
version "2.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz#966a6279060eb2d9d1a02ea1a331af071afdcf9e"
|
||||
integrity sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg==
|
||||
|
||||
"@volar/code-gen@0.34.17":
|
||||
version "0.34.17"
|
||||
resolved "https://registry.yarnpkg.com/@volar/code-gen/-/code-gen-0.34.17.tgz#fd46e369454e6bd9599b511500b4c43acb9730bd"
|
||||
integrity sha512-rHR7BA71BJ/4S7xUOPMPiB7uk6iU9oTWpEMZxFi5VGC9iJmDncE82WzU5iYpcbOBCVHsOjMh0+5CGMgdO6SaPA==
|
||||
dependencies:
|
||||
"@volar/source-map" "0.34.17"
|
||||
|
||||
"@volar/source-map@0.34.17":
|
||||
version "0.34.17"
|
||||
resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-0.34.17.tgz#79efc4d088e11f59fc857953185a1f852df70968"
|
||||
integrity sha512-3yn1IMXJGGWB/G817/VFlFMi8oh5pmE7VzUqvgMZMrppaZpKj6/juvJIEiXNxRsgWc0RxIO8OSp4htdPUg1Raw==
|
||||
|
||||
"@volar/vue-code-gen@0.34.17":
|
||||
version "0.34.17"
|
||||
resolved "https://registry.yarnpkg.com/@volar/vue-code-gen/-/vue-code-gen-0.34.17.tgz#55ca9c21b38c91bf362761b268a77b9f0ecae8bf"
|
||||
integrity sha512-17pzcK29fyFWUc+C82J3JYSnA+jy3QNrIldb9kPaP9Itbik05ZjEIyEue9FjhgIAuHeYSn4LDM5s6nGjxyfhsQ==
|
||||
dependencies:
|
||||
"@volar/code-gen" "0.34.17"
|
||||
"@volar/source-map" "0.34.17"
|
||||
"@vue/compiler-core" "^3.2.36"
|
||||
"@vue/compiler-dom" "^3.2.36"
|
||||
"@vue/shared" "^3.2.36"
|
||||
|
||||
"@volar/vue-typescript@0.34.17":
|
||||
version "0.34.17"
|
||||
resolved "https://registry.yarnpkg.com/@volar/vue-typescript/-/vue-typescript-0.34.17.tgz#497eb471ebac25ff61af04031b78ec71a34d470b"
|
||||
integrity sha512-U0YSVIBPRWVPmgJHNa4nrfq88+oS+tmyZNxmnfajIw9A/GOGZQiKXHC0k09SVvbYXlsjgJ6NIjhm9NuAhGRQjg==
|
||||
dependencies:
|
||||
"@volar/code-gen" "0.34.17"
|
||||
"@volar/source-map" "0.34.17"
|
||||
"@volar/vue-code-gen" "0.34.17"
|
||||
"@vue/compiler-sfc" "^3.2.36"
|
||||
"@vue/reactivity" "^3.2.36"
|
||||
|
||||
"@vue/compiler-core@3.2.45", "@vue/compiler-core@^3.2.36":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.45.tgz#d9311207d96f6ebd5f4660be129fb99f01ddb41b"
|
||||
integrity sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/shared" "3.2.45"
|
||||
estree-walker "^2.0.2"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-dom@3.2.45", "@vue/compiler-dom@^3.2.36":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz#c43cc15e50da62ecc16a42f2622d25dc5fd97dce"
|
||||
integrity sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==
|
||||
dependencies:
|
||||
"@vue/compiler-core" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/compiler-sfc@3.2.45", "@vue/compiler-sfc@^3.2.36":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz#7f7989cc04ec9e7c55acd406827a2c4e96872c70"
|
||||
integrity sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.45"
|
||||
"@vue/compiler-dom" "3.2.45"
|
||||
"@vue/compiler-ssr" "3.2.45"
|
||||
"@vue/reactivity-transform" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
postcss "^8.1.10"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-ssr@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz#bd20604b6e64ea15344d5b6278c4141191c983b2"
|
||||
integrity sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/devtools-api@^6.4.5":
|
||||
version "6.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.4.5.tgz#d54e844c1adbb1e677c81c665ecef1a2b4bb8380"
|
||||
integrity sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==
|
||||
|
||||
"@vue/reactivity-transform@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz#07ac83b8138550c83dfb50db43cde1e0e5e8124d"
|
||||
integrity sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
"@vue/reactivity@3.2.45", "@vue/reactivity@^3.2.36":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.45.tgz#412a45b574de601be5a4a5d9a8cbd4dee4662ff0"
|
||||
integrity sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==
|
||||
dependencies:
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/runtime-core@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.45.tgz#7ad7ef9b2519d41062a30c6fa001ec43ac549c7f"
|
||||
integrity sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==
|
||||
dependencies:
|
||||
"@vue/reactivity" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/runtime-dom@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz#1a2ef6ee2ad876206fbbe2a884554bba2d0faf59"
|
||||
integrity sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==
|
||||
dependencies:
|
||||
"@vue/runtime-core" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
csstype "^2.6.8"
|
||||
|
||||
"@vue/server-renderer@3.2.45":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.45.tgz#ca9306a0c12b0530a1a250e44f4a0abac6b81f3f"
|
||||
integrity sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==
|
||||
dependencies:
|
||||
"@vue/compiler-ssr" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
"@vue/shared@3.2.45", "@vue/shared@^3.2.36":
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.45.tgz#a3fffa7489eafff38d984e23d0236e230c818bc2"
|
||||
integrity sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==
|
||||
|
||||
acorn-node@^1.8.2:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
|
||||
integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
|
||||
dependencies:
|
||||
acorn "^7.0.0"
|
||||
acorn-walk "^7.0.0"
|
||||
xtend "^4.0.2"
|
||||
|
||||
acorn-walk@^7.0.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
||||
|
||||
acorn@^7.0.0:
|
||||
version "7.4.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
animate.css@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/animate.css/-/animate.css-4.1.1.tgz#614ec5a81131d7e4dc362a58143f7406abd68075"
|
||||
integrity sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==
|
||||
|
||||
anymatch@~3.1.2:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
|
||||
integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
|
||||
dependencies:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
arg@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
|
||||
integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
|
||||
|
||||
autoprefixer@^10.4.4:
|
||||
version "10.4.13"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8"
|
||||
integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==
|
||||
dependencies:
|
||||
browserslist "^4.21.4"
|
||||
caniuse-lite "^1.0.30001426"
|
||||
fraction.js "^4.2.0"
|
||||
normalize-range "^0.1.2"
|
||||
picocolors "^1.0.0"
|
||||
postcss-value-parser "^4.2.0"
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
braces@^3.0.2, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
browserslist@^4.21.4:
|
||||
version "4.21.4"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987"
|
||||
integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001400"
|
||||
electron-to-chromium "^1.4.251"
|
||||
node-releases "^2.0.6"
|
||||
update-browserslist-db "^1.0.9"
|
||||
|
||||
camelcase-css@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
|
||||
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
|
||||
|
||||
caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426:
|
||||
version "1.0.30001439"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz#ab7371faeb4adff4b74dad1718a6fd122e45d9cb"
|
||||
integrity sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==
|
||||
|
||||
chokidar@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
glob-parent "~5.1.2"
|
||||
is-binary-path "~2.1.0"
|
||||
is-glob "~4.0.1"
|
||||
normalize-path "~3.0.0"
|
||||
readdirp "~3.6.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
color-name@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
cssesc@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
||||
|
||||
csstype@^2.6.8:
|
||||
version "2.6.21"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
|
||||
integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
|
||||
|
||||
defined@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf"
|
||||
integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==
|
||||
|
||||
detective@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034"
|
||||
integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==
|
||||
dependencies:
|
||||
acorn-node "^1.8.2"
|
||||
defined "^1.0.0"
|
||||
minimist "^1.2.6"
|
||||
|
||||
didyoumean@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
|
||||
integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
|
||||
|
||||
dlv@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
|
||||
integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
|
||||
|
||||
electron-to-chromium@^1.4.251:
|
||||
version "1.4.284"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592"
|
||||
integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==
|
||||
|
||||
esbuild-android-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz#505f41832884313bbaffb27704b8bcaa2d8616be"
|
||||
integrity sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==
|
||||
|
||||
esbuild-android-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz#8ce69d7caba49646e009968fe5754a21a9871771"
|
||||
integrity sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==
|
||||
|
||||
esbuild-darwin-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz#24ba67b9a8cb890a3c08d9018f887cc221cdda25"
|
||||
integrity sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==
|
||||
|
||||
esbuild-darwin-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz#3f7cdb78888ee05e488d250a2bdaab1fa671bf73"
|
||||
integrity sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==
|
||||
|
||||
esbuild-freebsd-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz#09250f997a56ed4650f3e1979c905ffc40bbe94d"
|
||||
integrity sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==
|
||||
|
||||
esbuild-freebsd-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz#bafb46ed04fc5f97cbdb016d86947a79579f8e48"
|
||||
integrity sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==
|
||||
|
||||
esbuild-linux-32@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz#e2a8c4a8efdc355405325033fcebeb941f781fe5"
|
||||
integrity sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==
|
||||
|
||||
esbuild-linux-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz#de5fdba1c95666cf72369f52b40b03be71226652"
|
||||
integrity sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==
|
||||
|
||||
esbuild-linux-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz#dae4cd42ae9787468b6a5c158da4c84e83b0ce8b"
|
||||
integrity sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==
|
||||
|
||||
esbuild-linux-arm@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz#a2c1dff6d0f21dbe8fc6998a122675533ddfcd59"
|
||||
integrity sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==
|
||||
|
||||
esbuild-linux-mips64le@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz#d9918e9e4cb972f8d6dae8e8655bf9ee131eda34"
|
||||
integrity sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==
|
||||
|
||||
esbuild-linux-ppc64le@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz#3f9a0f6d41073fb1a640680845c7de52995f137e"
|
||||
integrity sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==
|
||||
|
||||
esbuild-linux-riscv64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz#618853c028178a61837bc799d2013d4695e451c8"
|
||||
integrity sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==
|
||||
|
||||
esbuild-linux-s390x@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz#d1885c4c5a76bbb5a0fe182e2c8c60eb9e29f2a6"
|
||||
integrity sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==
|
||||
|
||||
esbuild-netbsd-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz#69ae917a2ff241b7df1dbf22baf04bd330349e81"
|
||||
integrity sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==
|
||||
|
||||
esbuild-openbsd-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz#db4c8495287a350a6790de22edea247a57c5d47b"
|
||||
integrity sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==
|
||||
|
||||
esbuild-sunos-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz#54287ee3da73d3844b721c21bc80c1dc7e1bf7da"
|
||||
integrity sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==
|
||||
|
||||
esbuild-windows-32@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz#f8aaf9a5667630b40f0fb3aa37bf01bbd340ce31"
|
||||
integrity sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==
|
||||
|
||||
esbuild-windows-64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz#bf54b51bd3e9b0f1886ffdb224a4176031ea0af4"
|
||||
integrity sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==
|
||||
|
||||
esbuild-windows-arm64@0.14.54:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz#937d15675a15e4b0e4fafdbaa3a01a776a2be982"
|
||||
integrity sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==
|
||||
|
||||
esbuild@^0.14.27:
|
||||
version "0.14.54"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.54.tgz#8b44dcf2b0f1a66fc22459943dccf477535e9aa2"
|
||||
integrity sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==
|
||||
optionalDependencies:
|
||||
"@esbuild/linux-loong64" "0.14.54"
|
||||
esbuild-android-64 "0.14.54"
|
||||
esbuild-android-arm64 "0.14.54"
|
||||
esbuild-darwin-64 "0.14.54"
|
||||
esbuild-darwin-arm64 "0.14.54"
|
||||
esbuild-freebsd-64 "0.14.54"
|
||||
esbuild-freebsd-arm64 "0.14.54"
|
||||
esbuild-linux-32 "0.14.54"
|
||||
esbuild-linux-64 "0.14.54"
|
||||
esbuild-linux-arm "0.14.54"
|
||||
esbuild-linux-arm64 "0.14.54"
|
||||
esbuild-linux-mips64le "0.14.54"
|
||||
esbuild-linux-ppc64le "0.14.54"
|
||||
esbuild-linux-riscv64 "0.14.54"
|
||||
esbuild-linux-s390x "0.14.54"
|
||||
esbuild-netbsd-64 "0.14.54"
|
||||
esbuild-openbsd-64 "0.14.54"
|
||||
esbuild-sunos-64 "0.14.54"
|
||||
esbuild-windows-32 "0.14.54"
|
||||
esbuild-windows-64 "0.14.54"
|
||||
esbuild-windows-arm64 "0.14.54"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||
|
||||
estree-walker@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
|
||||
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
|
||||
|
||||
fast-glob@^3.2.12:
|
||||
version "3.2.12"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
|
||||
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
glob-parent "^5.1.2"
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.4"
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.14.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.14.0.tgz#107f69d7295b11e0fccc264e1fc6389f623731ce"
|
||||
integrity sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
fraction.js@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
|
||||
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob-parent@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
|
||||
integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
|
||||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
|
||||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-core-module@^2.9.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
|
||||
integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
||||
|
||||
is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
|
||||
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-number@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
lilconfig@^2.0.5, lilconfig@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4"
|
||||
integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==
|
||||
|
||||
magic-string@^0.25.7:
|
||||
version "0.25.9"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
|
||||
integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
|
||||
dependencies:
|
||||
sourcemap-codec "^1.4.8"
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
||||
dependencies:
|
||||
braces "^3.0.2"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
minimist@^1.2.6:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
|
||||
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
|
||||
|
||||
mitt@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd"
|
||||
integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==
|
||||
|
||||
nanoid@^3.3.4:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
||||
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
|
||||
|
||||
node-releases@^2.0.6:
|
||||
version "2.0.8"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.8.tgz#0f349cdc8fcfa39a92ac0be9bc48b7706292b9ae"
|
||||
integrity sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
normalize-range@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
||||
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
||||
|
||||
object-hash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
|
||||
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
|
||||
|
||||
path-parse@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
pify@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||
integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
|
||||
|
||||
pinia@^2.0.13:
|
||||
version "2.0.28"
|
||||
resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.28.tgz#887c982d854972042d9bdfd5bc4fad3b9d6ab02a"
|
||||
integrity sha512-YClq9DkqCblq9rlyUual7ezMu/iICWdBtfJrDt4oWU9Zxpijyz7xB2xTwx57DaBQ96UGvvTMORzALr+iO5PVMw==
|
||||
dependencies:
|
||||
"@vue/devtools-api" "^6.4.5"
|
||||
vue-demi "*"
|
||||
|
||||
postcss-import@^14.1.0:
|
||||
version "14.1.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0"
|
||||
integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==
|
||||
dependencies:
|
||||
postcss-value-parser "^4.0.0"
|
||||
read-cache "^1.0.0"
|
||||
resolve "^1.1.7"
|
||||
|
||||
postcss-js@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00"
|
||||
integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==
|
||||
dependencies:
|
||||
camelcase-css "^2.0.1"
|
||||
|
||||
postcss-load-config@^3.1.4:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
|
||||
integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
|
||||
dependencies:
|
||||
lilconfig "^2.0.5"
|
||||
yaml "^1.10.2"
|
||||
|
||||
postcss-nested@6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.0.tgz#1572f1984736578f360cffc7eb7dca69e30d1735"
|
||||
integrity sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==
|
||||
dependencies:
|
||||
postcss-selector-parser "^6.0.10"
|
||||
|
||||
postcss-selector-parser@^6.0.10:
|
||||
version "6.0.11"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc"
|
||||
integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.1.10, postcss@^8.4.12, postcss@^8.4.13, postcss@^8.4.18:
|
||||
version "8.4.20"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.20.tgz#64c52f509644cecad8567e949f4081d98349dc56"
|
||||
integrity sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==
|
||||
dependencies:
|
||||
nanoid "^3.3.4"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||
|
||||
quick-lru@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
|
||||
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
||||
|
||||
read-cache@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
|
||||
integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
|
||||
dependencies:
|
||||
pify "^2.3.0"
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
|
||||
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
resolve@^1.1.7, resolve@^1.22.0, resolve@^1.22.1:
|
||||
version "1.22.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
||||
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
||||
dependencies:
|
||||
is-core-module "^2.9.0"
|
||||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
reusify@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||
|
||||
"rollup@>=2.59.0 <2.78.0":
|
||||
version "2.77.3"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.77.3.tgz#8f00418d3a2740036e15deb653bed1a90ee0cc12"
|
||||
integrity sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
run-parallel@^1.1.9:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
|
||||
integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
source-map@^0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
sourcemap-codec@^1.4.8:
|
||||
version "1.4.8"
|
||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
|
||||
|
||||
supports-preserve-symlinks-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
tailwindcss@^3.0.24:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.2.4.tgz#afe3477e7a19f3ceafb48e4b083e292ce0dc0250"
|
||||
integrity sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==
|
||||
dependencies:
|
||||
arg "^5.0.2"
|
||||
chokidar "^3.5.3"
|
||||
color-name "^1.1.4"
|
||||
detective "^5.2.1"
|
||||
didyoumean "^1.2.2"
|
||||
dlv "^1.1.3"
|
||||
fast-glob "^3.2.12"
|
||||
glob-parent "^6.0.2"
|
||||
is-glob "^4.0.3"
|
||||
lilconfig "^2.0.6"
|
||||
micromatch "^4.0.5"
|
||||
normalize-path "^3.0.0"
|
||||
object-hash "^3.0.0"
|
||||
picocolors "^1.0.0"
|
||||
postcss "^8.4.18"
|
||||
postcss-import "^14.1.0"
|
||||
postcss-js "^4.0.0"
|
||||
postcss-load-config "^3.1.4"
|
||||
postcss-nested "6.0.0"
|
||||
postcss-selector-parser "^6.0.10"
|
||||
postcss-value-parser "^4.2.0"
|
||||
quick-lru "^5.1.1"
|
||||
resolve "^1.22.1"
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
typescript@^4.6.2:
|
||||
version "4.9.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78"
|
||||
integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==
|
||||
|
||||
update-browserslist-db@^1.0.9:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3"
|
||||
integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==
|
||||
dependencies:
|
||||
escalade "^3.1.1"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
util-deprecate@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
vite@^2.9.2:
|
||||
version "2.9.15"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.15.tgz#2858dd5b2be26aa394a283e62324281892546f0b"
|
||||
integrity sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ==
|
||||
dependencies:
|
||||
esbuild "^0.14.27"
|
||||
postcss "^8.4.13"
|
||||
resolve "^1.22.0"
|
||||
rollup ">=2.59.0 <2.78.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
vue-demi@*:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
|
||||
integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
|
||||
|
||||
vue-router@4:
|
||||
version "4.1.6"
|
||||
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.1.6.tgz#b70303737e12b4814578d21d68d21618469375a1"
|
||||
integrity sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==
|
||||
dependencies:
|
||||
"@vue/devtools-api" "^6.4.5"
|
||||
|
||||
vue-tsc@^0.34.6:
|
||||
version "0.34.17"
|
||||
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-0.34.17.tgz#332fc5c31d64bb9b74b0f26050f3ab067a9a7d6f"
|
||||
integrity sha512-jzUXky44ZLHC4daaJag7FQr3idlPYN719/K1eObGljz5KaS2UnVGTU/XSYCd7d6ampYYg4OsyalbHyJIxV0aEQ==
|
||||
dependencies:
|
||||
"@volar/vue-typescript" "0.34.17"
|
||||
|
||||
vue@^3.2.20, vue@^3.2.25:
|
||||
version "3.2.45"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.45.tgz#94a116784447eb7dbd892167784619fef379b3c8"
|
||||
integrity sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "3.2.45"
|
||||
"@vue/compiler-sfc" "3.2.45"
|
||||
"@vue/runtime-dom" "3.2.45"
|
||||
"@vue/server-renderer" "3.2.45"
|
||||
"@vue/shared" "3.2.45"
|
||||
|
||||
xtend@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
yaml@^1.10.2:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "oaflib",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "veypi",
|
||||
"license": "MIT"
|
||||
}
|
Loading…
Reference in New Issue