mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 18:24:36 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf0b2bcce8 | |||
| 3832020d50 | |||
| ee9b51ff8a |
@@ -2,7 +2,6 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Tauri + Vue + TS</title>
|
<title>Tauri + Vue + TS</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4",
|
"packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"build:deps": "pnpm --filter tauri-plugin-vpnservice-api build && pnpm --filter easytier-frontend-lib build",
|
||||||
"build": "vue-tsc --noEmit && vite build",
|
"dev": "pnpm run build:deps && vite",
|
||||||
|
"build": "pnpm run build:deps && vue-tsc --noEmit && vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"tauri": "tauri",
|
"tauri": "tauri",
|
||||||
"lint": "eslint . --ignore-pattern src-tauri",
|
"lint": "eslint . --ignore-pattern src-tauri",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const host = process.env.TAURI_DEV_HOST
|
|||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig(async () => ({
|
export default defineConfig(async () => ({
|
||||||
|
base: './',
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'~/': `${path.resolve(__dirname, 'src')}/`,
|
'~/': `${path.resolve(__dirname, 'src')}/`,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ edition.workspace = true
|
|||||||
description = "Config server for easytier. easytier-core gets config from this and web frontend use it as restful api server."
|
description = "Config server for easytier. easytier-core gets config from this and web frontend use it as restful api server."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
easytier = { path = "../easytier" }
|
easytier = { path = "../easytier", default-features = false, features = ["websocket"] }
|
||||||
tracing = { version = "0.1", features = ["log"] }
|
tracing = { version = "0.1", features = ["log"] }
|
||||||
anyhow = { version = "1.0" }
|
anyhow = { version = "1.0" }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc -b && vite build",
|
"build": "vue-tsc -b && vite build",
|
||||||
|
"test": "vitest run",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -43,10 +44,11 @@
|
|||||||
"typescript": "~5.6.3",
|
"typescript": "~5.6.3",
|
||||||
"vite": "^5.4.21",
|
"vite": "^5.4.21",
|
||||||
"vite-plugin-dts": "^4.3.0",
|
"vite-plugin-dts": "^4.3.0",
|
||||||
|
"vitest": "^2.1.9",
|
||||||
"vue-tsc": "^2.1.10"
|
"vue-tsc": "^2.1.10"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vue": "^3.5.12",
|
"vue": "^3.5.12",
|
||||||
"primevue": "^4.3.9"
|
"primevue": "^4.3.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import InputGroup from 'primevue/inputgroup'
|
|||||||
import InputGroupAddon from 'primevue/inputgroupaddon'
|
import InputGroupAddon from 'primevue/inputgroupaddon'
|
||||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { buildUrlInputValue, getHostInputValue, parseHostInputOnBlur, parseUrlInput } from '../modules/url-input'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
@@ -32,73 +33,11 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const parseUrl = (val: string | null | undefined): { proto: string; host: string; port: number | null } => {
|
const internalValue = ref(parseUrlInput(url.value, props.protos))
|
||||||
const getValidPort = (portStr: string, proto: string) => {
|
|
||||||
const p = parseInt(portStr)
|
|
||||||
return isNaN(p) ? (props.protos[proto] ?? 11010) : p
|
|
||||||
}
|
|
||||||
const parseByPattern = (input: string) => {
|
|
||||||
const trimmed = input.trim()
|
|
||||||
if (!trimmed) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const match = trimmed.match(/^(\w+):\/\/(.*)$/)
|
|
||||||
const proto = match ? match[1] : 'tcp'
|
|
||||||
const rest = match ? match[2] : trimmed
|
|
||||||
const authority = rest.split(/[/?#]/)[0]
|
|
||||||
if (!authority) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const hostAndMaybePort = authority.includes('@') ? authority.slice(authority.lastIndexOf('@') + 1) : authority
|
|
||||||
if (hostAndMaybePort.startsWith('[')) {
|
|
||||||
const ipv6End = hostAndMaybePort.indexOf(']')
|
|
||||||
if (ipv6End > 0) {
|
|
||||||
const host = hostAndMaybePort.slice(0, ipv6End + 1)
|
|
||||||
const remain = hostAndMaybePort.slice(ipv6End + 1)
|
|
||||||
// null = no explicit port in URL; do not fabricate a default
|
|
||||||
const port: number | null = remain.startsWith(':') ? getValidPort(remain.slice(1), proto) : null
|
|
||||||
return { proto, host, port }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const portMatch = hostAndMaybePort.match(/^(.*):(\d+)$/)
|
|
||||||
const host = portMatch ? portMatch[1] : hostAndMaybePort
|
|
||||||
// null = no explicit port in URL; buildUrlValue will omit the port entirely,
|
|
||||||
// preserving the protocol's implied standard port (e.g. 443 for wss://).
|
|
||||||
const port: number | null = portMatch ? parseInt(portMatch[2]) : null
|
|
||||||
return { proto, host, port }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!val) {
|
|
||||||
return { proto: 'tcp', host: '', port: props.protos['tcp'] ?? 11010 }
|
|
||||||
}
|
|
||||||
const parsedByPattern = parseByPattern(val)
|
|
||||||
if (parsedByPattern) {
|
|
||||||
return parsedByPattern
|
|
||||||
}
|
|
||||||
return { proto: 'tcp', host: '', port: null }
|
|
||||||
}
|
|
||||||
|
|
||||||
const internalValue = ref(parseUrl(url.value))
|
|
||||||
const defaultHost = '0.0.0.0'
|
const defaultHost = '0.0.0.0'
|
||||||
|
|
||||||
const buildUrlValue = (value: { proto: string, host: string, port: number | null }, forceDefaultHost = false) => {
|
|
||||||
const proto = value.proto || 'tcp'
|
|
||||||
const rawHost = (value.host ?? '').trim()
|
|
||||||
const host = rawHost || (forceDefaultHost ? defaultHost : '')
|
|
||||||
if (!host) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
// Omit port when the protocol uses no port (protos value = 0), or when the
|
|
||||||
// original URL had no explicit port (port === null) – avoids overwriting an
|
|
||||||
// implicit standard port (e.g. 443 for wss) with an EasyTier default (11012).
|
|
||||||
if (props.protos[proto] === 0 || value.port === null) {
|
|
||||||
return `${proto}://${host}`
|
|
||||||
}
|
|
||||||
return `${proto}://${host}:${value.port}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const syncUrlFromInternal = (forceDefaultHost = false) => {
|
const syncUrlFromInternal = (forceDefaultHost = false) => {
|
||||||
const nextUrl = buildUrlValue(internalValue.value, forceDefaultHost)
|
const nextUrl = buildUrlInputValue(internalValue.value, props.protos, forceDefaultHost)
|
||||||
if (!nextUrl || nextUrl === url.value) {
|
if (!nextUrl || nextUrl === url.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -107,6 +46,10 @@ const syncUrlFromInternal = (forceDefaultHost = false) => {
|
|||||||
|
|
||||||
const onHostBlur = () => {
|
const onHostBlur = () => {
|
||||||
hostFocused.value = false
|
hostFocused.value = false
|
||||||
|
const parsedHost = parseHostInputOnBlur(internalValue.value.host ?? '', internalValue.value.proto, props.protos)
|
||||||
|
if (parsedHost) {
|
||||||
|
internalValue.value = parsedHost
|
||||||
|
}
|
||||||
syncUrlFromInternal(true)
|
syncUrlFromInternal(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,12 +66,20 @@ const isNoPortProto = computed(() => {
|
|||||||
return props.protos[internalValue.value.proto] === 0
|
return props.protos[internalValue.value.proto] === 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const hostInputValue = computed({
|
||||||
|
get: () => getHostInputValue(internalValue.value),
|
||||||
|
set: (value: string) => {
|
||||||
|
internalValue.value.host = value
|
||||||
|
internalValue.value.suffix = undefined
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
// Sync from external
|
// Sync from external
|
||||||
watch(() => url.value, (newVal) => {
|
watch(() => url.value, (newVal) => {
|
||||||
if (hostFocused.value) {
|
if (hostFocused.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const parsed = parseUrl(newVal)
|
const parsed = parseUrlInput(newVal, props.protos)
|
||||||
const internalHost = internalValue.value.host ?? ''
|
const internalHost = internalValue.value.host ?? ''
|
||||||
const sameHost = parsed.host === internalHost || (!internalHost.trim() && parsed.host === defaultHost)
|
const sameHost = parsed.host === internalHost || (!internalHost.trim() && parsed.host === defaultHost)
|
||||||
if (parsed.proto !== internalValue.value.proto ||
|
if (parsed.proto !== internalValue.value.proto ||
|
||||||
@@ -140,6 +91,9 @@ watch(() => url.value, (newVal) => {
|
|||||||
|
|
||||||
// Sync to external
|
// Sync to external
|
||||||
watch(internalValue, () => {
|
watch(internalValue, () => {
|
||||||
|
if (hostFocused.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
syncUrlFromInternal(false)
|
syncUrlFromInternal(false)
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
@@ -165,6 +119,8 @@ const onProtoChange = (newProto: string) => {
|
|||||||
internalValue.value.port = newDefault
|
internalValue.value.port = newDefault
|
||||||
}
|
}
|
||||||
internalValue.value.proto = newProto
|
internalValue.value.proto = newProto
|
||||||
|
internalValue.value.suffix = undefined
|
||||||
|
internalValue.value.hasExplicitPort = true
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -174,7 +130,7 @@ const onProtoChange = (newProto: string) => {
|
|||||||
<AutoComplete :model-value="internalValue.proto" :suggestions="filteredProtos" dropdown
|
<AutoComplete :model-value="internalValue.proto" :suggestions="filteredProtos" dropdown
|
||||||
class="max-w-32 proto-autocomplete-in-group" @complete="searchProtos"
|
class="max-w-32 proto-autocomplete-in-group" @complete="searchProtos"
|
||||||
@update:model-value="onProtoChange" />
|
@update:model-value="onProtoChange" />
|
||||||
<InputText v-model="internalValue.host" :placeholder="placeholder || '0.0.0.0'" class="grow"
|
<InputText v-model="hostInputValue" :placeholder="placeholder || '0.0.0.0'" class="grow"
|
||||||
@focus="onHostFocus" @blur="onHostBlur" />
|
@focus="onHostFocus" @blur="onHostBlur" />
|
||||||
<template v-if="!isNoPortProto">
|
<template v-if="!isNoPortProto">
|
||||||
<InputGroupAddon>
|
<InputGroupAddon>
|
||||||
@@ -204,7 +160,7 @@ const onProtoChange = (newProto: string) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label>{{ t('web.common.address') || 'Address' }}</label>
|
<label>{{ t('web.common.address') || 'Address' }}</label>
|
||||||
<InputText v-model="internalValue.host" :placeholder="placeholder || '0.0.0.0'" class="w-full"
|
<InputText v-model="hostInputValue" :placeholder="placeholder || '0.0.0.0'" class="w-full"
|
||||||
@focus="onHostFocus" @blur="onHostBlur" />
|
@focus="onHostFocus" @blur="onHostBlur" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!isNoPortProto" class="flex flex-col gap-2">
|
<div v-if="!isNoPortProto" class="flex flex-col gap-2">
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { buildUrlInputValue, getHostInputValue, parseHostInputOnBlur, parseUrlInput, type ProtoPorts } from './url-input'
|
||||||
|
|
||||||
|
const protos: ProtoPorts = {
|
||||||
|
tcp: 11010,
|
||||||
|
udp: 11010,
|
||||||
|
wg: 11011,
|
||||||
|
ws: 11011,
|
||||||
|
wss: 11012,
|
||||||
|
quic: 11012,
|
||||||
|
faketcp: 11013,
|
||||||
|
http: 80,
|
||||||
|
https: 443,
|
||||||
|
txt: 0,
|
||||||
|
srv: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeUrl(input: string, defaultProto = 'tcp') {
|
||||||
|
return buildUrlInputValue(parseUrlInput(input, protos, defaultProto), protos, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('parseUrlInput', () => {
|
||||||
|
it.each([
|
||||||
|
['https://raw.githubusercontent.com/aaa/bb/cc.txt', {
|
||||||
|
proto: 'https',
|
||||||
|
host: 'raw.githubusercontent.com',
|
||||||
|
port: null,
|
||||||
|
suffix: '/aaa/bb/cc.txt',
|
||||||
|
hasExplicitPort: false,
|
||||||
|
}],
|
||||||
|
['https://host:4443/path?x=1#hash', {
|
||||||
|
proto: 'https',
|
||||||
|
host: 'host',
|
||||||
|
port: 4443,
|
||||||
|
suffix: '/path?x=1#hash',
|
||||||
|
hasExplicitPort: true,
|
||||||
|
}],
|
||||||
|
['[::1]:11010/path', {
|
||||||
|
proto: 'tcp',
|
||||||
|
host: '[::1]',
|
||||||
|
port: 11010,
|
||||||
|
suffix: '/path',
|
||||||
|
hasExplicitPort: true,
|
||||||
|
}],
|
||||||
|
[' http://host/path ', {
|
||||||
|
proto: 'http',
|
||||||
|
host: 'host',
|
||||||
|
port: null,
|
||||||
|
suffix: '/path',
|
||||||
|
hasExplicitPort: false,
|
||||||
|
}],
|
||||||
|
])('parses %s', (input, expected) => {
|
||||||
|
expect(parseUrlInput(input, protos)).toEqual(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('parses IPv6 host without an explicit port', () => {
|
||||||
|
expect(parseUrlInput('[::1]', protos)).toEqual({
|
||||||
|
proto: 'tcp',
|
||||||
|
host: '[::1]',
|
||||||
|
port: null,
|
||||||
|
suffix: '',
|
||||||
|
hasExplicitPort: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
['host:', 'host'],
|
||||||
|
['host:notaport', 'host'],
|
||||||
|
])('falls back to the default port for invalid port input %s', (input, host) => {
|
||||||
|
expect(parseUrlInput(input, protos)).toEqual({
|
||||||
|
proto: 'tcp',
|
||||||
|
host,
|
||||||
|
port: 11010,
|
||||||
|
suffix: '',
|
||||||
|
hasExplicitPort: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('keeps the explicit proto for an input without authority', () => {
|
||||||
|
expect(parseUrlInput('https://', protos)).toEqual({
|
||||||
|
proto: 'https',
|
||||||
|
host: '',
|
||||||
|
port: null,
|
||||||
|
suffix: '',
|
||||||
|
hasExplicitPort: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('buildUrlInputValue', () => {
|
||||||
|
it.each([
|
||||||
|
['https://host', 'https://host'],
|
||||||
|
['http://host', 'http://host'],
|
||||||
|
['https://host:4443/path', 'https://host:4443/path'],
|
||||||
|
['https://host:443/path', 'https://host:443/path'],
|
||||||
|
['tcp://host', 'tcp://host'],
|
||||||
|
['wss://host', 'wss://host'],
|
||||||
|
['http://host/path?x=1#hash', 'http://host/path?x=1#hash'],
|
||||||
|
['https://host?x=1', 'https://host?x=1'],
|
||||||
|
['https://host#hash', 'https://host#hash'],
|
||||||
|
['txt://example.com/path.txt', 'txt://example.com/path.txt'],
|
||||||
|
['srv://_easytier._tcp.example.com', 'srv://_easytier._tcp.example.com'],
|
||||||
|
['custom://host/path', 'custom://host/path'],
|
||||||
|
])('normalizes %s to %s', (input, expected) => {
|
||||||
|
expect(normalizeUrl(input)).toBe(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns null for empty host unless default host is forced', () => {
|
||||||
|
const parsed = parseUrlInput('', protos)
|
||||||
|
|
||||||
|
expect(buildUrlInputValue(parsed, protos, false)).toBeNull()
|
||||||
|
expect(buildUrlInputValue(parsed, protos, true)).toBe('tcp://0.0.0.0:11010')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not build a broken URL for a protocol without authority', () => {
|
||||||
|
const parsed = parseUrlInput('https://', protos)
|
||||||
|
|
||||||
|
expect(buildUrlInputValue(parsed, protos, false)).toBeNull()
|
||||||
|
expect(buildUrlInputValue(parsed, protos, true)).toBe('https://0.0.0.0')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('parseHostInputOnBlur', () => {
|
||||||
|
it('infers https for a pasted host:port/path when the current proto is tcp', () => {
|
||||||
|
const parsed = parseHostInputOnBlur('raw.githubusercontent.com:4443/aaa/bb/cc.txt', 'tcp', protos)
|
||||||
|
|
||||||
|
expect(parsed).toEqual({
|
||||||
|
proto: 'https',
|
||||||
|
host: 'raw.githubusercontent.com',
|
||||||
|
port: 4443,
|
||||||
|
suffix: '/aaa/bb/cc.txt',
|
||||||
|
hasExplicitPort: true,
|
||||||
|
})
|
||||||
|
expect(buildUrlInputValue(parsed!, protos, true)).toBe('https://raw.githubusercontent.com:4443/aaa/bb/cc.txt')
|
||||||
|
})
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
['raw.githubusercontent.com/aaa/bb/cc.txt', 'tcp', 'https://raw.githubusercontent.com/aaa/bb/cc.txt'],
|
||||||
|
['raw.githubusercontent.com:4443/aaa/bb/cc.txt', 'https', 'https://raw.githubusercontent.com:4443/aaa/bb/cc.txt'],
|
||||||
|
['https://raw.githubusercontent.com:4443/aaa/bb/cc.txt', 'tcp', 'https://raw.githubusercontent.com:4443/aaa/bb/cc.txt'],
|
||||||
|
[' https://raw.githubusercontent.com/aaa/bb/cc.txt ', 'tcp', 'https://raw.githubusercontent.com/aaa/bb/cc.txt'],
|
||||||
|
])('normalizes pasted host input %s with current proto %s', (input, currentProto, expected) => {
|
||||||
|
const parsed = parseHostInputOnBlur(input, currentProto, protos)
|
||||||
|
|
||||||
|
expect(buildUrlInputValue(parsed!, protos, true)).toBe(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('keeps ordinary host:port input on the current tcp protocol', () => {
|
||||||
|
const parsed = parseHostInputOnBlur('example.com:11010', 'tcp', protos)
|
||||||
|
|
||||||
|
expect(buildUrlInputValue(parsed!, protos, true)).toBe('tcp://example.com:11010')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns null for a simple host without port or suffix', () => {
|
||||||
|
expect(parseHostInputOnBlur('example.com', 'tcp', protos)).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('getHostInputValue', () => {
|
||||||
|
it('shows host and suffix while keeping the port in the port field', () => {
|
||||||
|
const parsed = parseUrlInput('https://raw.githubusercontent.com:4443/aaa/bb/cc.txt', protos)
|
||||||
|
|
||||||
|
expect(getHostInputValue(parsed)).toBe('raw.githubusercontent.com/aaa/bb/cc.txt')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows query and hash in the host input suffix', () => {
|
||||||
|
const parsed = parseUrlInput('https://host/path?x=1#hash', protos)
|
||||||
|
|
||||||
|
expect(getHostInputValue(parsed)).toBe('host/path?x=1#hash')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('round trip scenarios', () => {
|
||||||
|
it.each([
|
||||||
|
['https://raw.githubusercontent.com/aaa/bb/cc.txt'],
|
||||||
|
['https://raw.githubusercontent.com:4443/aaa/bb/cc.txt'],
|
||||||
|
['http://host/path?x=1#hash'],
|
||||||
|
['tcp://example.com:11010'],
|
||||||
|
['txt://example.com/path.txt'],
|
||||||
|
['srv://_easytier._tcp.example.com'],
|
||||||
|
])('keeps %s stable after parse and build', (input) => {
|
||||||
|
expect(normalizeUrl(input)).toBe(input)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
export interface UrlInputParts {
|
||||||
|
proto: string
|
||||||
|
host: string
|
||||||
|
port: number | null
|
||||||
|
suffix?: string
|
||||||
|
hasExplicitPort?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ProtoPorts = Record<string, number>
|
||||||
|
|
||||||
|
const fallbackProto = 'tcp'
|
||||||
|
const fallbackPort = 11010
|
||||||
|
const defaultHost = '0.0.0.0'
|
||||||
|
|
||||||
|
function defaultPortFor(protos: ProtoPorts, proto: string) {
|
||||||
|
return protos[proto] ?? fallbackPort
|
||||||
|
}
|
||||||
|
|
||||||
|
function getValidPort(portStr: string, protos: ProtoPorts, proto: string) {
|
||||||
|
const p = parseInt(portStr)
|
||||||
|
return isNaN(p) ? defaultPortFor(protos, proto) : p
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseUrlInput(val: string | null | undefined, protos: ProtoPorts, defaultProto = fallbackProto): UrlInputParts {
|
||||||
|
const parseByPattern = (input: string) => {
|
||||||
|
const trimmed = input.trim()
|
||||||
|
if (!trimmed) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = trimmed.match(/^(\w+):\/\/(.*)$/)
|
||||||
|
const proto = match ? match[1] : defaultProto
|
||||||
|
const rest = match ? match[2] : trimmed
|
||||||
|
const suffixStart = rest.search(/[/?#]/)
|
||||||
|
const authority = suffixStart >= 0 ? rest.slice(0, suffixStart) : rest
|
||||||
|
const suffix = suffixStart >= 0 ? rest.slice(suffixStart) : ''
|
||||||
|
if (!authority) {
|
||||||
|
return { proto, host: '', port: null, suffix, hasExplicitPort: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostAndMaybePort = authority.includes('@') ? authority.slice(authority.lastIndexOf('@') + 1) : authority
|
||||||
|
if (hostAndMaybePort.startsWith('[')) {
|
||||||
|
const ipv6End = hostAndMaybePort.indexOf(']')
|
||||||
|
if (ipv6End > 0) {
|
||||||
|
const host = hostAndMaybePort.slice(0, ipv6End + 1)
|
||||||
|
const remain = hostAndMaybePort.slice(ipv6End + 1)
|
||||||
|
const hasExplicitPort = remain.startsWith(':')
|
||||||
|
const port = hasExplicitPort ? getValidPort(remain.slice(1), protos, proto) : null
|
||||||
|
return { proto, host, port, suffix, hasExplicitPort }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const portMatch = hostAndMaybePort.match(/^(.*):(\d+)$/)
|
||||||
|
if (portMatch) {
|
||||||
|
return { proto, host: portMatch[1], port: parseInt(portMatch[2]), suffix, hasExplicitPort: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
const invalidPortMatch = hostAndMaybePort.match(/^([^:]+):[^:]*$/)
|
||||||
|
const host = invalidPortMatch ? invalidPortMatch[1] : hostAndMaybePort
|
||||||
|
const port = invalidPortMatch ? defaultPortFor(protos, proto) : null
|
||||||
|
return { proto, host, port, suffix, hasExplicitPort: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!val) {
|
||||||
|
return { proto: defaultProto, host: '', port: defaultPortFor(protos, defaultProto) }
|
||||||
|
}
|
||||||
|
const parsedByPattern = parseByPattern(val)
|
||||||
|
if (parsedByPattern) {
|
||||||
|
return parsedByPattern
|
||||||
|
}
|
||||||
|
return { proto: defaultProto, host: '', port: defaultPortFor(protos, defaultProto) }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildUrlInputValue(value: UrlInputParts, protos: ProtoPorts, forceDefaultHost = false) {
|
||||||
|
const proto = value.proto || fallbackProto
|
||||||
|
const rawHost = (value.host ?? '').trim()
|
||||||
|
const host = rawHost || (forceDefaultHost ? defaultHost : '')
|
||||||
|
if (!host) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protos[proto] === 0 || value.port === null) {
|
||||||
|
return `${proto}://${host}${value.suffix ?? ''}`
|
||||||
|
}
|
||||||
|
|
||||||
|
let port = value.port
|
||||||
|
if (isNaN(parseInt(port as any))) {
|
||||||
|
port = defaultPortFor(protos, proto)
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${proto}://${host}:${port}${value.suffix ?? ''}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseHostInputOnBlur(rawHost: string, currentProto: string, protos: ProtoPorts) {
|
||||||
|
const inferredProto = rawHost.includes('/') && currentProto === fallbackProto ? 'https' : currentProto
|
||||||
|
const parsedHost = parseUrlInput(rawHost, protos, inferredProto)
|
||||||
|
if (parsedHost.host && (parsedHost.proto !== currentProto || parsedHost.hasExplicitPort || parsedHost.suffix)) {
|
||||||
|
return parsedHost
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getHostInputValue(value: UrlInputParts) {
|
||||||
|
return `${value.host ?? ''}${value.suffix ?? ''}`
|
||||||
|
}
|
||||||
@@ -4,8 +4,9 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"build:deps": "pnpm --filter easytier-frontend-lib build",
|
||||||
"build": "vue-tsc -b && vite build",
|
"dev": "pnpm run build:deps && vite",
|
||||||
|
"build": "pnpm run build:deps && vue-tsc -b && vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -32,4 +33,4 @@
|
|||||||
"vite-plugin-singlefile": "^2.0.3",
|
"vite-plugin-singlefile": "^2.0.3",
|
||||||
"vue-tsc": "^2.1.10"
|
"vue-tsc": "^2.1.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
"caniuse-lite": "1.0.30001791",
|
||||||
"minimatch": "10.2.4"
|
"minimatch": "10.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+277
-9
@@ -5,6 +5,7 @@ settings:
|
|||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
overrides:
|
overrides:
|
||||||
|
caniuse-lite: 1.0.30001791
|
||||||
minimatch: 10.2.4
|
minimatch: 10.2.4
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
@@ -58,7 +59,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
'@antfu/eslint-config':
|
'@antfu/eslint-config':
|
||||||
specifier: ^3.7.3
|
specifier: ^3.7.3
|
||||||
version: 3.16.0(@typescript-eslint/utils@8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3))(@vue/compiler-sfc@3.5.21)(eslint-plugin-format@0.1.3(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
version: 3.16.0(@typescript-eslint/utils@8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3))(@vue/compiler-sfc@3.5.21)(eslint-plugin-format@0.1.3(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)(vitest@2.1.9(@types/node@22.18.1))
|
||||||
'@intlify/unplugin-vue-i18n':
|
'@intlify/unplugin-vue-i18n':
|
||||||
specifier: ^5.2.0
|
specifier: ^5.2.0
|
||||||
version: 5.3.1(@vue/compiler-dom@3.5.21)(eslint@9.35.0(jiti@2.5.1))(rollup@4.50.1)(typescript@5.6.3)(vue-i18n@10.0.8(vue@3.5.21(typescript@5.6.3)))(vue@3.5.21(typescript@5.6.3))
|
version: 5.3.1(@vue/compiler-dom@3.5.21)(eslint@9.35.0(jiti@2.5.1))(rollup@4.50.1)(typescript@5.6.3)(vue-i18n@10.0.8(vue@3.5.21(typescript@5.6.3)))(vue@3.5.21(typescript@5.6.3))
|
||||||
@@ -286,6 +287,9 @@ importers:
|
|||||||
vite-plugin-dts:
|
vite-plugin-dts:
|
||||||
specifier: ^4.3.0
|
specifier: ^4.3.0
|
||||||
version: 4.5.4(@types/node@22.18.1)(rollup@4.50.1)(typescript@5.6.3)(vite@5.4.21(@types/node@22.18.1))
|
version: 4.5.4(@types/node@22.18.1)(rollup@4.50.1)(typescript@5.6.3)(vite@5.4.21(@types/node@22.18.1))
|
||||||
|
vitest:
|
||||||
|
specifier: ^2.1.9
|
||||||
|
version: 2.1.9(@types/node@22.18.1)
|
||||||
vue-tsc:
|
vue-tsc:
|
||||||
specifier: ^2.1.10
|
specifier: ^2.1.10
|
||||||
version: 2.2.12(typescript@5.6.3)
|
version: 2.2.12(typescript@5.6.3)
|
||||||
@@ -1673,6 +1677,35 @@ packages:
|
|||||||
vitest:
|
vitest:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@vitest/expect@2.1.9':
|
||||||
|
resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==}
|
||||||
|
|
||||||
|
'@vitest/mocker@2.1.9':
|
||||||
|
resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==}
|
||||||
|
peerDependencies:
|
||||||
|
msw: ^2.4.9
|
||||||
|
vite: ^5.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
msw:
|
||||||
|
optional: true
|
||||||
|
vite:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@vitest/pretty-format@2.1.9':
|
||||||
|
resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==}
|
||||||
|
|
||||||
|
'@vitest/runner@2.1.9':
|
||||||
|
resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==}
|
||||||
|
|
||||||
|
'@vitest/snapshot@2.1.9':
|
||||||
|
resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==}
|
||||||
|
|
||||||
|
'@vitest/spy@2.1.9':
|
||||||
|
resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==}
|
||||||
|
|
||||||
|
'@vitest/utils@2.1.9':
|
||||||
|
resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==}
|
||||||
|
|
||||||
'@volar/language-core@2.4.15':
|
'@volar/language-core@2.4.15':
|
||||||
resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==}
|
resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==}
|
||||||
|
|
||||||
@@ -2072,6 +2105,10 @@ packages:
|
|||||||
argparse@2.0.1:
|
argparse@2.0.1:
|
||||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||||
|
|
||||||
|
assertion-error@2.0.1:
|
||||||
|
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
ast-kit@1.4.3:
|
ast-kit@1.4.3:
|
||||||
resolution: {integrity: sha512-MdJqjpodkS5J149zN0Po+HPshkTdUyrvF7CKTafUgv69vBSPtncrj+3IiUgqdd7ElIEkbeXCsEouBUwLrw9Ilg==}
|
resolution: {integrity: sha512-MdJqjpodkS5J149zN0Po+HPshkTdUyrvF7CKTafUgv69vBSPtncrj+3IiUgqdd7ElIEkbeXCsEouBUwLrw9Ilg==}
|
||||||
engines: {node: '>=16.14.0'}
|
engines: {node: '>=16.14.0'}
|
||||||
@@ -2134,6 +2171,10 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
esbuild: '>=0.18'
|
esbuild: '>=0.18'
|
||||||
|
|
||||||
|
cac@6.7.14:
|
||||||
|
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
call-bind-apply-helpers@1.0.2:
|
call-bind-apply-helpers@1.0.2:
|
||||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -2146,12 +2187,16 @@ packages:
|
|||||||
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
|
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
caniuse-lite@1.0.30001741:
|
caniuse-lite@1.0.30001791:
|
||||||
resolution: {integrity: sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==}
|
resolution: {integrity: sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==}
|
||||||
|
|
||||||
ccount@2.0.1:
|
ccount@2.0.1:
|
||||||
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
|
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
|
||||||
|
|
||||||
|
chai@5.3.3:
|
||||||
|
resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
chalk@4.1.2:
|
chalk@4.1.2:
|
||||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -2163,6 +2208,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==}
|
resolution: {integrity: sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==}
|
||||||
engines: {pnpm: '>=8'}
|
engines: {pnpm: '>=8'}
|
||||||
|
|
||||||
|
check-error@2.1.3:
|
||||||
|
resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
|
||||||
|
engines: {node: '>= 16'}
|
||||||
|
|
||||||
chokidar@3.6.0:
|
chokidar@3.6.0:
|
||||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||||
engines: {node: '>= 8.10.0'}
|
engines: {node: '>= 8.10.0'}
|
||||||
@@ -2251,6 +2300,10 @@ packages:
|
|||||||
decode-named-character-reference@1.2.0:
|
decode-named-character-reference@1.2.0:
|
||||||
resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==}
|
resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==}
|
||||||
|
|
||||||
|
deep-eql@5.0.2:
|
||||||
|
resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
deep-is@0.1.4:
|
deep-is@0.1.4:
|
||||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||||
|
|
||||||
@@ -2328,6 +2381,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
es-module-lexer@1.7.0:
|
||||||
|
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
|
||||||
|
|
||||||
es-object-atoms@1.1.1:
|
es-object-atoms@1.1.1:
|
||||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -2596,6 +2652,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
|
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
|
||||||
engines: {node: '>=16.17'}
|
engines: {node: '>=16.17'}
|
||||||
|
|
||||||
|
expect-type@1.3.0:
|
||||||
|
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
exsolve@1.0.7:
|
exsolve@1.0.7:
|
||||||
resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
|
resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
|
||||||
|
|
||||||
@@ -3017,6 +3077,9 @@ packages:
|
|||||||
longest-streak@3.1.0:
|
longest-streak@3.1.0:
|
||||||
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
||||||
|
|
||||||
|
loupe@3.2.1:
|
||||||
|
resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
|
||||||
|
|
||||||
lru-cache@10.4.3:
|
lru-cache@10.4.3:
|
||||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
||||||
|
|
||||||
@@ -3370,6 +3433,10 @@ packages:
|
|||||||
pathe@2.0.3:
|
pathe@2.0.3:
|
||||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||||
|
|
||||||
|
pathval@2.0.1:
|
||||||
|
resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
|
||||||
|
engines: {node: '>= 14.16'}
|
||||||
|
|
||||||
perfect-debounce@1.0.0:
|
perfect-debounce@1.0.0:
|
||||||
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
|
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
|
||||||
|
|
||||||
@@ -3612,6 +3679,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
siginfo@2.0.0:
|
||||||
|
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||||
|
|
||||||
signal-exit@3.0.7:
|
signal-exit@3.0.7:
|
||||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||||
|
|
||||||
@@ -3664,6 +3734,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==}
|
resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
|
stackback@0.0.2:
|
||||||
|
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||||
|
|
||||||
|
std-env@3.10.0:
|
||||||
|
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
|
||||||
|
|
||||||
string-argv@0.3.2:
|
string-argv@0.3.2:
|
||||||
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
|
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
|
||||||
engines: {node: '>=0.6.19'}
|
engines: {node: '>=0.6.19'}
|
||||||
@@ -3753,9 +3829,27 @@ packages:
|
|||||||
thenify@3.3.1:
|
thenify@3.3.1:
|
||||||
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
||||||
|
|
||||||
|
tinybench@2.9.0:
|
||||||
|
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||||
|
|
||||||
|
tinyexec@0.3.2:
|
||||||
|
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
|
||||||
|
|
||||||
tinyexec@1.0.1:
|
tinyexec@1.0.1:
|
||||||
resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
|
resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
|
||||||
|
|
||||||
|
tinypool@1.1.1:
|
||||||
|
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
|
||||||
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
|
||||||
|
tinyrainbow@1.2.0:
|
||||||
|
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
|
tinyspy@3.0.2:
|
||||||
|
resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
to-regex-range@5.0.1:
|
to-regex-range@5.0.1:
|
||||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||||
engines: {node: '>=8.0'}
|
engines: {node: '>=8.0'}
|
||||||
@@ -3975,6 +4069,11 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0
|
vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0
|
||||||
|
|
||||||
|
vite-node@2.1.9:
|
||||||
|
resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==}
|
||||||
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
vite-plugin-dts@4.5.4:
|
vite-plugin-dts@4.5.4:
|
||||||
resolution: {integrity: sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg==}
|
resolution: {integrity: sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -4050,6 +4149,31 @@ packages:
|
|||||||
terser:
|
terser:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
vitest@2.1.9:
|
||||||
|
resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==}
|
||||||
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@edge-runtime/vm': '*'
|
||||||
|
'@types/node': ^18.0.0 || >=20.0.0
|
||||||
|
'@vitest/browser': 2.1.9
|
||||||
|
'@vitest/ui': 2.1.9
|
||||||
|
happy-dom: '*'
|
||||||
|
jsdom: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@edge-runtime/vm':
|
||||||
|
optional: true
|
||||||
|
'@types/node':
|
||||||
|
optional: true
|
||||||
|
'@vitest/browser':
|
||||||
|
optional: true
|
||||||
|
'@vitest/ui':
|
||||||
|
optional: true
|
||||||
|
happy-dom:
|
||||||
|
optional: true
|
||||||
|
jsdom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
vscode-uri@3.1.0:
|
vscode-uri@3.1.0:
|
||||||
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
|
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
|
||||||
|
|
||||||
@@ -4122,6 +4246,11 @@ packages:
|
|||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
why-is-node-running@2.3.0:
|
||||||
|
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
word-wrap@1.2.5:
|
word-wrap@1.2.5:
|
||||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -4180,7 +4309,7 @@ snapshots:
|
|||||||
|
|
||||||
'@alloc/quick-lru@5.2.0': {}
|
'@alloc/quick-lru@5.2.0': {}
|
||||||
|
|
||||||
'@antfu/eslint-config@3.16.0(@typescript-eslint/utils@8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3))(@vue/compiler-sfc@3.5.21)(eslint-plugin-format@0.1.3(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)':
|
'@antfu/eslint-config@3.16.0(@typescript-eslint/utils@8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3))(@vue/compiler-sfc@3.5.21)(eslint-plugin-format@0.1.3(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)(vitest@2.1.9(@types/node@22.18.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@antfu/install-pkg': 1.1.0
|
'@antfu/install-pkg': 1.1.0
|
||||||
'@clack/prompts': 0.9.1
|
'@clack/prompts': 0.9.1
|
||||||
@@ -4189,7 +4318,7 @@ snapshots:
|
|||||||
'@stylistic/eslint-plugin': 2.13.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
'@stylistic/eslint-plugin': 2.13.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
||||||
'@typescript-eslint/eslint-plugin': 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3))(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
'@typescript-eslint/eslint-plugin': 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3))(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
||||||
'@typescript-eslint/parser': 8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
'@typescript-eslint/parser': 8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
||||||
'@vitest/eslint-plugin': 1.3.9(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
'@vitest/eslint-plugin': 1.3.9(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)(vitest@2.1.9(@types/node@22.18.1))
|
||||||
eslint: 9.35.0(jiti@2.5.1)
|
eslint: 9.35.0(jiti@2.5.1)
|
||||||
eslint-config-flat-gitignore: 1.0.1(eslint@9.35.0(jiti@2.5.1))
|
eslint-config-flat-gitignore: 1.0.1(eslint@9.35.0(jiti@2.5.1))
|
||||||
eslint-flat-config-utils: 1.1.0
|
eslint-flat-config-utils: 1.1.0
|
||||||
@@ -5386,16 +5515,57 @@ snapshots:
|
|||||||
vite: 5.4.21(@types/node@22.18.1)
|
vite: 5.4.21(@types/node@22.18.1)
|
||||||
vue: 3.5.21(typescript@5.6.3)
|
vue: 3.5.21(typescript@5.6.3)
|
||||||
|
|
||||||
'@vitest/eslint-plugin@1.3.9(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)':
|
'@vitest/eslint-plugin@1.3.9(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)(vitest@2.1.9(@types/node@22.18.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 8.42.0
|
'@typescript-eslint/scope-manager': 8.42.0
|
||||||
'@typescript-eslint/utils': 8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
'@typescript-eslint/utils': 8.42.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.6.3)
|
||||||
eslint: 9.35.0(jiti@2.5.1)
|
eslint: 9.35.0(jiti@2.5.1)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.6.3
|
typescript: 5.6.3
|
||||||
|
vitest: 2.1.9(@types/node@22.18.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@vitest/expect@2.1.9':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/spy': 2.1.9
|
||||||
|
'@vitest/utils': 2.1.9
|
||||||
|
chai: 5.3.3
|
||||||
|
tinyrainbow: 1.2.0
|
||||||
|
|
||||||
|
'@vitest/mocker@2.1.9(vite@5.4.21(@types/node@22.18.1))':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/spy': 2.1.9
|
||||||
|
estree-walker: 3.0.3
|
||||||
|
magic-string: 0.30.18
|
||||||
|
optionalDependencies:
|
||||||
|
vite: 5.4.21(@types/node@22.18.1)
|
||||||
|
|
||||||
|
'@vitest/pretty-format@2.1.9':
|
||||||
|
dependencies:
|
||||||
|
tinyrainbow: 1.2.0
|
||||||
|
|
||||||
|
'@vitest/runner@2.1.9':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/utils': 2.1.9
|
||||||
|
pathe: 1.1.2
|
||||||
|
|
||||||
|
'@vitest/snapshot@2.1.9':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/pretty-format': 2.1.9
|
||||||
|
magic-string: 0.30.18
|
||||||
|
pathe: 1.1.2
|
||||||
|
|
||||||
|
'@vitest/spy@2.1.9':
|
||||||
|
dependencies:
|
||||||
|
tinyspy: 3.0.2
|
||||||
|
|
||||||
|
'@vitest/utils@2.1.9':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/pretty-format': 2.1.9
|
||||||
|
loupe: 3.2.1
|
||||||
|
tinyrainbow: 1.2.0
|
||||||
|
|
||||||
'@volar/language-core@2.4.15':
|
'@volar/language-core@2.4.15':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@volar/source-map': 2.4.15
|
'@volar/source-map': 2.4.15
|
||||||
@@ -5970,6 +6140,8 @@ snapshots:
|
|||||||
|
|
||||||
argparse@2.0.1: {}
|
argparse@2.0.1: {}
|
||||||
|
|
||||||
|
assertion-error@2.0.1: {}
|
||||||
|
|
||||||
ast-kit@1.4.3:
|
ast-kit@1.4.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.28.4
|
'@babel/parser': 7.28.4
|
||||||
@@ -5985,7 +6157,7 @@ snapshots:
|
|||||||
autoprefixer@10.4.21(postcss@8.5.6):
|
autoprefixer@10.4.21(postcss@8.5.6):
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist: 4.25.4
|
browserslist: 4.25.4
|
||||||
caniuse-lite: 1.0.30001741
|
caniuse-lite: 1.0.30001791
|
||||||
fraction.js: 4.3.7
|
fraction.js: 4.3.7
|
||||||
normalize-range: 0.1.2
|
normalize-range: 0.1.2
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
@@ -6018,7 +6190,7 @@ snapshots:
|
|||||||
|
|
||||||
browserslist@4.25.4:
|
browserslist@4.25.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite: 1.0.30001741
|
caniuse-lite: 1.0.30001791
|
||||||
electron-to-chromium: 1.5.214
|
electron-to-chromium: 1.5.214
|
||||||
node-releases: 2.0.20
|
node-releases: 2.0.20
|
||||||
update-browserslist-db: 1.1.3(browserslist@4.25.4)
|
update-browserslist-db: 1.1.3(browserslist@4.25.4)
|
||||||
@@ -6034,6 +6206,8 @@ snapshots:
|
|||||||
esbuild: 0.25.9
|
esbuild: 0.25.9
|
||||||
load-tsconfig: 0.2.5
|
load-tsconfig: 0.2.5
|
||||||
|
|
||||||
|
cac@6.7.14: {}
|
||||||
|
|
||||||
call-bind-apply-helpers@1.0.2:
|
call-bind-apply-helpers@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
@@ -6043,10 +6217,18 @@ snapshots:
|
|||||||
|
|
||||||
camelcase-css@2.0.1: {}
|
camelcase-css@2.0.1: {}
|
||||||
|
|
||||||
caniuse-lite@1.0.30001741: {}
|
caniuse-lite@1.0.30001791: {}
|
||||||
|
|
||||||
ccount@2.0.1: {}
|
ccount@2.0.1: {}
|
||||||
|
|
||||||
|
chai@5.3.3:
|
||||||
|
dependencies:
|
||||||
|
assertion-error: 2.0.1
|
||||||
|
check-error: 2.1.3
|
||||||
|
deep-eql: 5.0.2
|
||||||
|
loupe: 3.2.1
|
||||||
|
pathval: 2.0.1
|
||||||
|
|
||||||
chalk@4.1.2:
|
chalk@4.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
@@ -6058,6 +6240,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@kurkle/color': 0.3.4
|
'@kurkle/color': 0.3.4
|
||||||
|
|
||||||
|
check-error@2.1.3: {}
|
||||||
|
|
||||||
chokidar@3.6.0:
|
chokidar@3.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
anymatch: 3.1.3
|
anymatch: 3.1.3
|
||||||
@@ -6138,6 +6322,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
character-entities: 2.0.2
|
character-entities: 2.0.2
|
||||||
|
|
||||||
|
deep-eql@5.0.2: {}
|
||||||
|
|
||||||
deep-is@0.1.4: {}
|
deep-is@0.1.4: {}
|
||||||
|
|
||||||
default-browser-id@5.0.0: {}
|
default-browser-id@5.0.0: {}
|
||||||
@@ -6198,6 +6384,8 @@ snapshots:
|
|||||||
|
|
||||||
es-errors@1.3.0: {}
|
es-errors@1.3.0: {}
|
||||||
|
|
||||||
|
es-module-lexer@1.7.0: {}
|
||||||
|
|
||||||
es-object-atoms@1.1.1:
|
es-object-atoms@1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
@@ -6614,6 +6802,8 @@ snapshots:
|
|||||||
signal-exit: 4.1.0
|
signal-exit: 4.1.0
|
||||||
strip-final-newline: 3.0.0
|
strip-final-newline: 3.0.0
|
||||||
|
|
||||||
|
expect-type@1.3.0: {}
|
||||||
|
|
||||||
exsolve@1.0.7: {}
|
exsolve@1.0.7: {}
|
||||||
|
|
||||||
extend-shallow@2.0.1:
|
extend-shallow@2.0.1:
|
||||||
@@ -6977,6 +7167,8 @@ snapshots:
|
|||||||
|
|
||||||
longest-streak@3.1.0: {}
|
longest-streak@3.1.0: {}
|
||||||
|
|
||||||
|
loupe@3.2.1: {}
|
||||||
|
|
||||||
lru-cache@10.4.3: {}
|
lru-cache@10.4.3: {}
|
||||||
|
|
||||||
lru-cache@5.1.1:
|
lru-cache@5.1.1:
|
||||||
@@ -7502,6 +7694,8 @@ snapshots:
|
|||||||
|
|
||||||
pathe@2.0.3: {}
|
pathe@2.0.3: {}
|
||||||
|
|
||||||
|
pathval@2.0.1: {}
|
||||||
|
|
||||||
perfect-debounce@1.0.0: {}
|
perfect-debounce@1.0.0: {}
|
||||||
|
|
||||||
picocolors@1.1.1: {}
|
picocolors@1.1.1: {}
|
||||||
@@ -7738,6 +7932,8 @@ snapshots:
|
|||||||
|
|
||||||
shebang-regex@3.0.0: {}
|
shebang-regex@3.0.0: {}
|
||||||
|
|
||||||
|
siginfo@2.0.0: {}
|
||||||
|
|
||||||
signal-exit@3.0.7: {}
|
signal-exit@3.0.7: {}
|
||||||
|
|
||||||
signal-exit@4.1.0: {}
|
signal-exit@4.1.0: {}
|
||||||
@@ -7785,6 +7981,10 @@ snapshots:
|
|||||||
|
|
||||||
stable-hash-x@0.2.0: {}
|
stable-hash-x@0.2.0: {}
|
||||||
|
|
||||||
|
stackback@0.0.2: {}
|
||||||
|
|
||||||
|
std-env@3.10.0: {}
|
||||||
|
|
||||||
string-argv@0.3.2: {}
|
string-argv@0.3.2: {}
|
||||||
|
|
||||||
string-width@4.2.3:
|
string-width@4.2.3:
|
||||||
@@ -7895,8 +8095,18 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
any-promise: 1.3.0
|
any-promise: 1.3.0
|
||||||
|
|
||||||
|
tinybench@2.9.0: {}
|
||||||
|
|
||||||
|
tinyexec@0.3.2: {}
|
||||||
|
|
||||||
tinyexec@1.0.1: {}
|
tinyexec@1.0.1: {}
|
||||||
|
|
||||||
|
tinypool@1.1.1: {}
|
||||||
|
|
||||||
|
tinyrainbow@1.2.0: {}
|
||||||
|
|
||||||
|
tinyspy@3.0.2: {}
|
||||||
|
|
||||||
to-regex-range@5.0.1:
|
to-regex-range@5.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-number: 7.0.0
|
is-number: 7.0.0
|
||||||
@@ -8199,6 +8409,24 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
vite: 5.4.21(@types/node@22.18.1)
|
vite: 5.4.21(@types/node@22.18.1)
|
||||||
|
|
||||||
|
vite-node@2.1.9(@types/node@22.18.1):
|
||||||
|
dependencies:
|
||||||
|
cac: 6.7.14
|
||||||
|
debug: 4.4.1
|
||||||
|
es-module-lexer: 1.7.0
|
||||||
|
pathe: 1.1.2
|
||||||
|
vite: 5.4.21(@types/node@22.18.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/node'
|
||||||
|
- less
|
||||||
|
- lightningcss
|
||||||
|
- sass
|
||||||
|
- sass-embedded
|
||||||
|
- stylus
|
||||||
|
- sugarss
|
||||||
|
- supports-color
|
||||||
|
- terser
|
||||||
|
|
||||||
vite-plugin-dts@4.5.4(@types/node@22.18.1)(rollup@4.50.1)(typescript@5.6.3)(vite@5.4.21(@types/node@22.18.1)):
|
vite-plugin-dts@4.5.4(@types/node@22.18.1)(rollup@4.50.1)(typescript@5.6.3)(vite@5.4.21(@types/node@22.18.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@microsoft/api-extractor': 7.52.11(@types/node@22.18.1)
|
'@microsoft/api-extractor': 7.52.11(@types/node@22.18.1)
|
||||||
@@ -8290,6 +8518,41 @@ snapshots:
|
|||||||
'@types/node': 22.18.1
|
'@types/node': 22.18.1
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
|
vitest@2.1.9(@types/node@22.18.1):
|
||||||
|
dependencies:
|
||||||
|
'@vitest/expect': 2.1.9
|
||||||
|
'@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.18.1))
|
||||||
|
'@vitest/pretty-format': 2.1.9
|
||||||
|
'@vitest/runner': 2.1.9
|
||||||
|
'@vitest/snapshot': 2.1.9
|
||||||
|
'@vitest/spy': 2.1.9
|
||||||
|
'@vitest/utils': 2.1.9
|
||||||
|
chai: 5.3.3
|
||||||
|
debug: 4.4.1
|
||||||
|
expect-type: 1.3.0
|
||||||
|
magic-string: 0.30.18
|
||||||
|
pathe: 1.1.2
|
||||||
|
std-env: 3.10.0
|
||||||
|
tinybench: 2.9.0
|
||||||
|
tinyexec: 0.3.2
|
||||||
|
tinypool: 1.1.1
|
||||||
|
tinyrainbow: 1.2.0
|
||||||
|
vite: 5.4.21(@types/node@22.18.1)
|
||||||
|
vite-node: 2.1.9(@types/node@22.18.1)
|
||||||
|
why-is-node-running: 2.3.0
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/node': 22.18.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- less
|
||||||
|
- lightningcss
|
||||||
|
- msw
|
||||||
|
- sass
|
||||||
|
- sass-embedded
|
||||||
|
- stylus
|
||||||
|
- sugarss
|
||||||
|
- supports-color
|
||||||
|
- terser
|
||||||
|
|
||||||
vscode-uri@3.1.0: {}
|
vscode-uri@3.1.0: {}
|
||||||
|
|
||||||
vue-chartjs@5.3.2(chart.js@4.5.0)(vue@3.5.21(typescript@5.6.3)):
|
vue-chartjs@5.3.2(chart.js@4.5.0)(vue@3.5.21(typescript@5.6.3)):
|
||||||
@@ -8359,6 +8622,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
|
|
||||||
|
why-is-node-running@2.3.0:
|
||||||
|
dependencies:
|
||||||
|
siginfo: 2.0.0
|
||||||
|
stackback: 0.0.2
|
||||||
|
|
||||||
word-wrap@1.2.5: {}
|
word-wrap@1.2.5: {}
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
wrap-ansi@7.0.0:
|
||||||
|
|||||||
Reference in New Issue
Block a user