Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
429f38d0
Commit
429f38d0
authored
Dec 26, 2025
by
shaw
Browse files
Merge PR #37: Add Gemini OAuth and Messages Compat Support
parents
2d89f366
2714be99
Changes
165
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/openai_gateway_service.go
View file @
429f38d0
...
...
@@ -170,9 +170,18 @@ func (s *OpenAIGatewayService) SelectAccountForModel(ctx context.Context, groupI
if
acc
.
Priority
<
selected
.
Priority
{
selected
=
acc
}
else
if
acc
.
Priority
==
selected
.
Priority
{
// Same priority, select least recently used
if
acc
.
LastUsedAt
==
nil
||
(
selected
.
LastUsedAt
!=
nil
&&
acc
.
LastUsedAt
.
Before
(
*
selected
.
LastUsedAt
))
{
switch
{
case
acc
.
LastUsedAt
==
nil
&&
selected
.
LastUsedAt
!=
nil
:
selected
=
acc
case
acc
.
LastUsedAt
!=
nil
&&
selected
.
LastUsedAt
==
nil
:
// keep selected (never used is preferred)
case
acc
.
LastUsedAt
==
nil
&&
selected
.
LastUsedAt
==
nil
:
// keep selected (both never used)
default
:
// Same priority, select least recently used
if
acc
.
LastUsedAt
.
Before
(
*
selected
.
LastUsedAt
)
{
selected
=
acc
}
}
}
}
...
...
backend/internal/service/pricing_service.go
View file @
429f38d0
...
...
@@ -393,27 +393,32 @@ func (s *PricingService) GetModelPricing(modelName string) *LiteLLMModelPricing
return
nil
}
// 标准化模型名称
modelLower
:=
strings
.
ToLower
(
modelName
)
// 标准化模型名称(同时兼容 "models/xxx"、VertexAI 资源名等前缀)
modelLower
:=
strings
.
ToLower
(
strings
.
TrimSpace
(
modelName
))
lookupCandidates
:=
s
.
buildModelLookupCandidates
(
modelLower
)
// 1. 精确匹配
if
pricing
,
ok
:=
s
.
pricingData
[
modelLower
];
ok
{
return
pricing
}
if
pricing
,
ok
:=
s
.
pricingData
[
modelName
];
ok
{
return
pricing
for
_
,
candidate
:=
range
lookupCandidates
{
if
candidate
==
""
{
continue
}
if
pricing
,
ok
:=
s
.
pricingData
[
candidate
];
ok
{
return
pricing
}
}
// 2. 处理常见的模型名称变体
// claude-opus-4-5-20251101 -> claude-opus-4.5-20251101
normalized
:=
strings
.
ReplaceAll
(
modelLower
,
"-4-5-"
,
"-4.5-"
)
if
pricing
,
ok
:=
s
.
pricingData
[
normalized
];
ok
{
return
pricing
for
_
,
candidate
:=
range
lookupCandidates
{
normalized
:=
strings
.
ReplaceAll
(
candidate
,
"-4-5-"
,
"-4.5-"
)
if
pricing
,
ok
:=
s
.
pricingData
[
normalized
];
ok
{
return
pricing
}
}
// 3. 尝试模糊匹配(去掉版本号后缀)
// claude-opus-4-5-20251101 -> claude-opus-4.5
baseName
:=
s
.
extractBaseName
(
modelLower
)
baseName
:=
s
.
extractBaseName
(
lookupCandidates
[
0
]
)
for
key
,
pricing
:=
range
s
.
pricingData
{
keyBase
:=
s
.
extractBaseName
(
strings
.
ToLower
(
key
))
if
keyBase
==
baseName
{
...
...
@@ -422,18 +427,77 @@ func (s *PricingService) GetModelPricing(modelName string) *LiteLLMModelPricing
}
// 4. 基于模型系列匹配(Claude)
if
pricing
:=
s
.
matchByModelFamily
(
modelLower
);
pricing
!=
nil
{
if
pricing
:=
s
.
matchByModelFamily
(
lookupCandidates
[
0
]
);
pricing
!=
nil
{
return
pricing
}
// 5. OpenAI 模型回退策略
if
strings
.
HasPrefix
(
modelLower
,
"gpt-"
)
{
return
s
.
matchOpenAIModel
(
modelLower
)
if
strings
.
HasPrefix
(
lookupCandidates
[
0
]
,
"gpt-"
)
{
return
s
.
matchOpenAIModel
(
lookupCandidates
[
0
]
)
}
return
nil
}
func
(
s
*
PricingService
)
buildModelLookupCandidates
(
modelLower
string
)
[]
string
{
// Prefer canonical model name first (this also improves billing compatibility with "models/xxx").
candidates
:=
[]
string
{
normalizeModelNameForPricing
(
modelLower
),
modelLower
,
}
candidates
=
append
(
candidates
,
strings
.
TrimPrefix
(
modelLower
,
"models/"
),
lastSegment
(
modelLower
),
lastSegment
(
strings
.
TrimPrefix
(
modelLower
,
"models/"
)),
)
seen
:=
make
(
map
[
string
]
struct
{},
len
(
candidates
))
out
:=
make
([]
string
,
0
,
len
(
candidates
))
for
_
,
c
:=
range
candidates
{
c
=
strings
.
TrimSpace
(
c
)
if
c
==
""
{
continue
}
if
_
,
ok
:=
seen
[
c
];
ok
{
continue
}
seen
[
c
]
=
struct
{}{}
out
=
append
(
out
,
c
)
}
if
len
(
out
)
==
0
{
return
[]
string
{
modelLower
}
}
return
out
}
func
normalizeModelNameForPricing
(
model
string
)
string
{
// Common Gemini/VertexAI forms:
// - models/gemini-2.0-flash-exp
// - publishers/google/models/gemini-1.5-pro
// - projects/.../locations/.../publishers/google/models/gemini-1.5-pro
model
=
strings
.
TrimSpace
(
model
)
model
=
strings
.
TrimLeft
(
model
,
"/"
)
model
=
strings
.
TrimPrefix
(
model
,
"models/"
)
model
=
strings
.
TrimPrefix
(
model
,
"publishers/google/models/"
)
if
idx
:=
strings
.
LastIndex
(
model
,
"/publishers/google/models/"
);
idx
!=
-
1
{
model
=
model
[
idx
+
len
(
"/publishers/google/models/"
)
:
]
}
if
idx
:=
strings
.
LastIndex
(
model
,
"/models/"
);
idx
!=
-
1
{
model
=
model
[
idx
+
len
(
"/models/"
)
:
]
}
model
=
strings
.
TrimLeft
(
model
,
"/"
)
return
model
}
func
lastSegment
(
model
string
)
string
{
if
idx
:=
strings
.
LastIndex
(
model
,
"/"
);
idx
!=
-
1
{
return
model
[
idx
+
1
:
]
}
return
model
}
// extractBaseName 提取基础模型名称(去掉日期版本号)
func
(
s
*
PricingService
)
extractBaseName
(
model
string
)
string
{
// 移除日期后缀 (如 -20251101, -20241022)
...
...
backend/internal/service/token_refresh_service.go
View file @
429f38d0
...
...
@@ -26,6 +26,7 @@ func NewTokenRefreshService(
accountRepo
AccountRepository
,
oauthService
*
OAuthService
,
openaiOAuthService
*
OpenAIOAuthService
,
geminiOAuthService
*
GeminiOAuthService
,
cfg
*
config
.
Config
,
)
*
TokenRefreshService
{
s
:=
&
TokenRefreshService
{
...
...
@@ -38,6 +39,7 @@ func NewTokenRefreshService(
s
.
refreshers
=
[]
TokenRefresher
{
NewClaudeTokenRefresher
(
oauthService
),
NewOpenAITokenRefresher
(
openaiOAuthService
),
NewGeminiTokenRefresher
(
geminiOAuthService
),
}
return
s
...
...
backend/internal/service/wire.go
View file @
429f38d0
...
...
@@ -36,9 +36,10 @@ func ProvideTokenRefreshService(
accountRepo
AccountRepository
,
oauthService
*
OAuthService
,
openaiOAuthService
*
OpenAIOAuthService
,
geminiOAuthService
*
GeminiOAuthService
,
cfg
*
config
.
Config
,
)
*
TokenRefreshService
{
svc
:=
NewTokenRefreshService
(
accountRepo
,
oauthService
,
openaiOAuthService
,
cfg
)
svc
:=
NewTokenRefreshService
(
accountRepo
,
oauthService
,
openaiOAuthService
,
geminiOAuthService
,
cfg
)
svc
.
Start
()
return
svc
}
...
...
@@ -63,6 +64,9 @@ var ProviderSet = wire.NewSet(
NewOpenAIGatewayService
,
NewOAuthService
,
NewOpenAIOAuthService
,
NewGeminiOAuthService
,
NewGeminiTokenProvider
,
NewGeminiMessagesCompatService
,
NewRateLimitService
,
NewAccountUsageService
,
NewAccountTestService
,
...
...
backend/internal/web/embed_on.go
View file @
429f38d0
...
...
@@ -27,6 +27,7 @@ func ServeEmbeddedFrontend() gin.HandlerFunc {
if
strings
.
HasPrefix
(
path
,
"/api/"
)
||
strings
.
HasPrefix
(
path
,
"/v1/"
)
||
strings
.
HasPrefix
(
path
,
"/v1beta/"
)
||
strings
.
HasPrefix
(
path
,
"/setup/"
)
||
path
==
"/health"
{
c
.
Next
()
...
...
deploy/.env.example
View file @
429f38d0
...
...
@@ -53,3 +53,32 @@ ADMIN_PASSWORD=
# Leave empty to auto-generate (recommended)
JWT_SECRET=
JWT_EXPIRE_HOUR=24
# -----------------------------------------------------------------------------
# Gemini OAuth (OPTIONAL, required only for Gemini OAuth accounts)
# -----------------------------------------------------------------------------
# Sub2API supports TWO Gemini OAuth modes:
#
# 1. Code Assist OAuth (需要 GCP project_id)
# - Uses: cloudcode-pa.googleapis.com (Code Assist API)
# - Auto scopes: cloud-platform + userinfo.email + userinfo.profile
# - OAuth Client: Can use built-in Gemini CLI client (留空即可)
# - Requires: Google Cloud Platform project with Code Assist enabled
#
# 2. AI Studio OAuth (不需要 project_id)
# - Uses: generativelanguage.googleapis.com (AI Studio API)
# - Default scopes: generative-language
# - OAuth Client: Requires your own OAuth 2.0 Client (内置 Gemini CLI client 不能申请 generative-language scope)
# - Requires: Create OAuth 2.0 Client in GCP Console + OAuth consent screen
# - Setup Guide: https://ai.google.dev/gemini-api/docs/oauth
# - ⚠️ IMPORTANT: OAuth Client 必须发布为正式版本 (Production)
# Testing 模式限制: 只能添加 100 个测试用户, refresh token 7 天后过期
# 发布步骤: GCP Console → OAuth consent screen → PUBLISH APP
#
# Configuration:
# Leave empty to use the built-in Gemini CLI OAuth client (Code Assist OAuth only).
# To enable AI Studio OAuth, set your own OAuth client ID/secret here.
GEMINI_OAUTH_CLIENT_ID=
GEMINI_OAUTH_CLIENT_SECRET=
# Optional; leave empty to auto-select scopes based on oauth_type
GEMINI_OAUTH_SCOPES=
deploy/README.md
View file @
429f38d0
...
...
@@ -96,11 +96,107 @@ docker-compose down -v
|
`ADMIN_PASSWORD`
| No |
*(auto-generated)*
| Admin password |
|
`JWT_SECRET`
| No |
*(auto-generated)*
| JWT secret |
|
`TZ`
| No |
`Asia/Shanghai`
| Timezone |
|
`GEMINI_OAUTH_CLIENT_ID`
| No |
*(builtin)*
| Google OAuth client ID (Gemini OAuth). Leave empty to use the built-in Gemini CLI client. |
|
`GEMINI_OAUTH_CLIENT_SECRET`
| No |
*(builtin)*
| Google OAuth client secret (Gemini OAuth). Leave empty to use the built-in Gemini CLI client. |
|
`GEMINI_OAUTH_SCOPES`
| No |
*(default)*
| OAuth scopes (Gemini OAuth) |
See
`.env.example`
for all available options.
---
## Gemini OAuth Configuration
Sub2API supports three methods to connect to Gemini:
### Method 1: Code Assist OAuth (Recommended for GCP Users)
**No configuration needed**
- always uses the built-in Gemini CLI OAuth client (public).
1.
Leave
`GEMINI_OAUTH_CLIENT_ID`
and
`GEMINI_OAUTH_CLIENT_SECRET`
empty
2.
In the Admin UI, create a Gemini OAuth account and select
**"Code Assist"**
type
3.
Complete the OAuth flow in your browser
> Note: Even if you configure `GEMINI_OAUTH_CLIENT_ID` / `GEMINI_OAUTH_CLIENT_SECRET` for AI Studio OAuth,
> Code Assist OAuth will still use the built-in Gemini CLI client.
**Requirements:**
-
Google account with access to Google Cloud Platform
-
A GCP project (auto-detected or manually specified)
**How to get Project ID (if auto-detection fails):**
1.
Go to
[
Google Cloud Console
](
https://console.cloud.google.com/
)
2.
Click the project dropdown at the top of the page
3.
Copy the Project ID (not the project name) from the list
4.
Common formats:
`my-project-123456`
or
`cloud-ai-companion-xxxxx`
### Method 2: AI Studio OAuth (For Regular Google Accounts)
Requires your own OAuth client credentials.
**Step 1: Create OAuth Client in Google Cloud Console**
1.
Go to
[
Google Cloud Console - Credentials
](
https://console.cloud.google.com/apis/credentials
)
2.
Create a new project or select an existing one
3.
**Enable the Generative Language API:**
-
Go to "APIs & Services" → "Library"
-
Search for "Generative Language API"
-
Click "Enable"
4.
**Configure OAuth Consent Screen**
(if not done):
-
Go to "APIs & Services" → "OAuth consent screen"
-
Choose "External" user type
-
Fill in app name, user support email, developer contact
-
Add scopes:
`https://www.googleapis.com/auth/generative-language.retriever`
(and optionally
`https://www.googleapis.com/auth/cloud-platform`
)
-
Add test users (your Google account email)
5.
**Create OAuth 2.0 credentials:**
-
Go to "APIs & Services" → "Credentials"
-
Click "Create Credentials" → "OAuth client ID"
-
Application type:
**Web application**
(or
**Desktop app**
)
-
Name: e.g., "Sub2API Gemini"
-
Authorized redirect URIs: Add
`http://localhost:1455/auth/callback`
6.
Copy the
**Client ID**
and
**Client Secret**
7.
**⚠️ Publish to Production (IMPORTANT):**
-
Go to "APIs & Services" → "OAuth consent screen"
-
Click "PUBLISH APP" to move from Testing to Production
-
**Testing mode limitations:**
-
Only manually added test users can authenticate (max 100 users)
-
Refresh tokens expire after 7 days
-
Users must be re-added periodically
-
**Production mode:**
Any Google user can authenticate, tokens don't expire
-
Note: For sensitive scopes, Google may require verification (demo video, privacy policy)
**Step 2: Configure Environment Variables**
```
bash
GEMINI_OAUTH_CLIENT_ID
=
your-client-id.apps.googleusercontent.com
GEMINI_OAUTH_CLIENT_SECRET
=
GOCSPX-your-client-secret
```
**Step 3: Create Account in Admin UI**
1.
Create a Gemini OAuth account and select
**"AI Studio"**
type
2.
Complete the OAuth flow
-
After consent, your browser will be redirected to
`http://localhost:1455/auth/callback?code=...&state=...`
-
Copy the full callback URL (recommended) or just the
`code`
and paste it back into the Admin UI
### Method 3: API Key (Simplest)
1.
Go to
[
Google AI Studio
](
https://aistudio.google.com/app/apikey
)
2.
Click "Create API key"
3.
In Admin UI, create a Gemini
**API Key**
account
4.
Paste your API key (starts with
`AIza...`
)
### Comparison Table
| Feature | Code Assist OAuth | AI Studio OAuth | API Key |
|---------|-------------------|-----------------|---------|
| Setup Complexity | Easy (no config) | Medium (OAuth client) | Easy |
| GCP Project Required | Yes | No | No |
| Custom OAuth Client | No (built-in) | Yes (required) | N/A |
| Rate Limits | GCP quota | Standard | Standard |
| Best For | GCP developers | Regular users needing OAuth | Quick testing |
---
## Binary Installation
For production servers using systemd.
...
...
deploy/config.example.yaml
View file @
429f38d0
...
...
@@ -87,3 +87,23 @@ pricing:
update_interval_hours
:
24
# Hash check interval in minutes
hash_check_interval_minutes
:
10
# =============================================================================
# Gemini OAuth (Required for Gemini accounts)
# =============================================================================
# Sub2API supports TWO Gemini OAuth modes:
#
# 1. Code Assist OAuth (需要 GCP project_id)
# - Uses: cloudcode-pa.googleapis.com (Code Assist API)
#
# 2. AI Studio OAuth (不需要 project_id)
# - Uses: generativelanguage.googleapis.com (AI Studio API)
#
# Default: Uses Gemini CLI's public OAuth credentials (same as Google's official CLI tool)
gemini
:
oauth
:
# Gemini CLI public OAuth credentials (works for both Code Assist and AI Studio)
client_id
:
"
681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com"
client_secret
:
"
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"
# Optional scopes (space-separated). Leave empty to auto-select based on oauth_type.
scopes
:
"
"
deploy/docker-compose.yml
View file @
429f38d0
...
...
@@ -78,6 +78,13 @@ services:
# Common values: Asia/Shanghai, America/New_York, Europe/London, UTC
# =======================================================================
-
TZ=${TZ:-Asia/Shanghai}
# =======================================================================
# Gemini OAuth Configuration (for Gemini accounts)
# =======================================================================
-
GEMINI_OAUTH_CLIENT_ID=${GEMINI_OAUTH_CLIENT_ID:-}
-
GEMINI_OAUTH_CLIENT_SECRET=${GEMINI_OAUTH_CLIENT_SECRET:-}
-
GEMINI_OAUTH_SCOPES=${GEMINI_OAUTH_SCOPES:-}
depends_on
:
postgres
:
condition
:
service_healthy
...
...
deploy/install.sh
View file @
429f38d0
...
...
@@ -122,6 +122,10 @@ declare -A MSG_ZH=(
[
"removing_user"
]=
"正在移除用户..."
[
"config_not_removed"
]=
"配置目录未被移除"
[
"remove_manually"
]=
"如不再需要,请手动删除"
[
"removing_install_lock"
]=
"正在移除安装锁文件..."
[
"install_lock_removed"
]=
"安装锁文件已移除,重新安装时将进入设置向导"
[
"purge_prompt"
]=
"是否同时删除配置目录?这将清除所有配置和数据 [y/N]: "
[
"removing_config_dir"
]=
"正在移除配置目录..."
[
"uninstall_complete"
]=
"Sub2API 已卸载"
# Help
...
...
@@ -243,6 +247,10 @@ declare -A MSG_EN=(
[
"removing_user"
]=
"Removing user..."
[
"config_not_removed"
]=
"Config directory was NOT removed."
[
"remove_manually"
]=
"Remove it manually if you no longer need it."
[
"removing_install_lock"
]=
"Removing install lock file..."
[
"install_lock_removed"
]=
"Install lock removed. Setup wizard will appear on next install."
[
"purge_prompt"
]=
"Also remove config directory? This will delete all config and data [y/N]: "
[
"removing_config_dir"
]=
"Removing config directory..."
[
"uninstall_complete"
]=
"Sub2API has been uninstalled"
# Help
...
...
@@ -926,8 +934,31 @@ uninstall() {
print_info
"
$(
msg
'removing_user'
)
"
userdel
"
$SERVICE_USER
"
2>/dev/null
||
true
print_warning
"
$(
msg
'config_not_removed'
)
:
$CONFIG_DIR
"
print_warning
"
$(
msg
'remove_manually'
)
"
# Remove install lock file (.installed) to allow fresh setup on reinstall
print_info
"
$(
msg
'removing_install_lock'
)
"
rm
-f
"
$CONFIG_DIR
/.installed"
2>/dev/null
||
true
rm
-f
"
$INSTALL_DIR
/.installed"
2>/dev/null
||
true
print_success
"
$(
msg
'install_lock_removed'
)
"
# Ask about config directory removal (interactive mode only)
local
remove_config
=
false
if
[
"
${
PURGE
:-}
"
=
"true"
]
;
then
remove_config
=
true
elif
is_interactive
;
then
read
-p
"
$(
msg
'purge_prompt'
)
"
-n
1
-r
< /dev/tty
echo
if
[[
$REPLY
=
~ ^[Yy]
$
]]
;
then
remove_config
=
true
fi
fi
if
[
"
$remove_config
"
=
true
]
;
then
print_info
"
$(
msg
'removing_config_dir'
)
"
rm
-rf
"
$CONFIG_DIR
"
else
print_warning
"
$(
msg
'config_not_removed'
)
:
$CONFIG_DIR
"
print_warning
"
$(
msg
'remove_manually'
)
"
fi
print_success
"
$(
msg
'uninstall_complete'
)
"
}
...
...
@@ -944,6 +975,10 @@ main() {
FORCE_YES
=
"true"
shift
;;
--purge
)
PURGE
=
"true"
shift
;;
-v
|
--version
)
if
[
-n
"
${
2
:-}
"
]
&&
[[
!
"
$2
"
=
~ ^-
]]
;
then
target_version
=
"
$2
"
...
...
frontend/index.html
View file @
429f38d0
<!
DOCTYPE
html>
<!
doctype
html>
<html
lang=
"zh-CN"
>
<head>
<meta
charset=
"UTF-8"
/>
...
...
frontend/package-lock.json
View file @
429f38d0
...
...
@@ -494,6 +494,180 @@
"node"
:
">=12"
}
},
"node_modules/@eslint-community/eslint-utils"
:
{
"version"
:
"4.9.0"
,
"resolved"
:
"https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz"
,
"integrity"
:
"sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"eslint-visitor-keys"
:
"^3.4.3"
},
"engines"
:
{
"node"
:
"^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding"
:
{
"url"
:
"https://opencollective.com/eslint"
},
"peerDependencies"
:
{
"eslint"
:
"^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
"node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys"
:
{
"version"
:
"3.4.3"
,
"resolved"
:
"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
,
"integrity"
:
"sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="
,
"dev"
:
true
,
"license"
:
"Apache-2.0"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
"^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding"
:
{
"url"
:
"https://opencollective.com/eslint"
}
},
"node_modules/@eslint-community/regexpp"
:
{
"version"
:
"4.12.2"
,
"resolved"
:
"https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz"
,
"integrity"
:
"sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
"^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
"node_modules/@eslint/eslintrc"
:
{
"version"
:
"2.1.4"
,
"resolved"
:
"https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz"
,
"integrity"
:
"sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"ajv"
:
"^6.12.4"
,
"debug"
:
"^4.3.2"
,
"espree"
:
"^9.6.0"
,
"globals"
:
"^13.19.0"
,
"ignore"
:
"^5.2.0"
,
"import-fresh"
:
"^3.2.1"
,
"js-yaml"
:
"^4.1.0"
,
"minimatch"
:
"^3.1.2"
,
"strip-json-comments"
:
"^3.1.1"
},
"engines"
:
{
"node"
:
"^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding"
:
{
"url"
:
"https://opencollective.com/eslint"
}
},
"node_modules/@eslint/eslintrc/node_modules/brace-expansion"
:
{
"version"
:
"1.1.12"
,
"resolved"
:
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz"
,
"integrity"
:
"sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"balanced-match"
:
"^1.0.0"
,
"concat-map"
:
"0.0.1"
}
},
"node_modules/@eslint/eslintrc/node_modules/minimatch"
:
{
"version"
:
"3.1.2"
,
"resolved"
:
"https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
,
"integrity"
:
"sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
,
"dependencies"
:
{
"brace-expansion"
:
"^1.1.7"
},
"engines"
:
{
"node"
:
"*"
}
},
"node_modules/@eslint/js"
:
{
"version"
:
"8.57.1"
,
"resolved"
:
"https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz"
,
"integrity"
:
"sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
"^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@humanwhocodes/config-array"
:
{
"version"
:
"0.13.0"
,
"resolved"
:
"https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz"
,
"integrity"
:
"sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw=="
,
"deprecated"
:
"Use @eslint/config-array instead"
,
"dev"
:
true
,
"license"
:
"Apache-2.0"
,
"optional"
:
true
,
"dependencies"
:
{
"@humanwhocodes/object-schema"
:
"^2.0.3"
,
"debug"
:
"^4.3.1"
,
"minimatch"
:
"^3.0.5"
},
"engines"
:
{
"node"
:
">=10.10.0"
}
},
"node_modules/@humanwhocodes/config-array/node_modules/brace-expansion"
:
{
"version"
:
"1.1.12"
,
"resolved"
:
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz"
,
"integrity"
:
"sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"balanced-match"
:
"^1.0.0"
,
"concat-map"
:
"0.0.1"
}
},
"node_modules/@humanwhocodes/config-array/node_modules/minimatch"
:
{
"version"
:
"3.1.2"
,
"resolved"
:
"https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
,
"integrity"
:
"sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
,
"dependencies"
:
{
"brace-expansion"
:
"^1.1.7"
},
"engines"
:
{
"node"
:
"*"
}
},
"node_modules/@humanwhocodes/module-importer"
:
{
"version"
:
"1.0.1"
,
"resolved"
:
"https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz"
,
"integrity"
:
"sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="
,
"dev"
:
true
,
"license"
:
"Apache-2.0"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=12.22"
},
"funding"
:
{
"type"
:
"github"
,
"url"
:
"https://github.com/sponsors/nzakas"
}
},
"node_modules/@humanwhocodes/object-schema"
:
{
"version"
:
"2.0.3"
,
"resolved"
:
"https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz"
,
"integrity"
:
"sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA=="
,
"deprecated"
:
"Use @eslint/object-schema instead"
,
"dev"
:
true
,
"license"
:
"BSD-3-Clause"
,
"optional"
:
true
},
"node_modules/@intlify/core-base"
:
{
"version"
:
"9.14.5"
,
"resolved"
:
"https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.14.5.tgz"
,
...
...
@@ -941,6 +1115,7 @@
"integrity"
:
"sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"undici-types"
:
"~6.21.0"
}
...
...
@@ -951,6 +1126,14 @@
"integrity"
:
"sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
,
"license"
:
"MIT"
},
"node_modules/@ungap/structured-clone"
:
{
"version"
:
"1.3.0"
,
"resolved"
:
"https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz"
,
"integrity"
:
"sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
},
"node_modules/@vitejs/plugin-vue"
:
{
"version"
:
"5.2.4"
,
"resolved"
:
"https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz"
,
...
...
@@ -1172,6 +1355,35 @@
"url"
:
"https://github.com/sponsors/antfu"
}
},
"node_modules/acorn-jsx"
:
{
"version"
:
"5.3.2"
,
"resolved"
:
"https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
,
"integrity"
:
"sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"peerDependencies"
:
{
"acorn"
:
"^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/ajv"
:
{
"version"
:
"6.12.6"
,
"resolved"
:
"https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
,
"integrity"
:
"sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"fast-deep-equal"
:
"^3.1.1"
,
"fast-json-stable-stringify"
:
"^2.0.0"
,
"json-schema-traverse"
:
"^0.4.1"
,
"uri-js"
:
"^4.2.2"
},
"funding"
:
{
"type"
:
"github"
,
"url"
:
"https://github.com/sponsors/epoberezkin"
}
},
"node_modules/alien-signals"
:
{
"version"
:
"1.0.13"
,
"resolved"
:
"https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz"
,
...
...
@@ -1192,6 +1404,23 @@
"url"
:
"https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ansi-styles"
:
{
"version"
:
"4.3.0"
,
"resolved"
:
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz"
,
"integrity"
:
"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"color-convert"
:
"^2.0.1"
},
"engines"
:
{
"node"
:
">=8"
},
"funding"
:
{
"url"
:
"https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/any-promise"
:
{
"version"
:
"1.3.0"
,
"resolved"
:
"https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz"
,
...
...
@@ -1220,6 +1449,14 @@
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/argparse"
:
{
"version"
:
"2.0.1"
,
"resolved"
:
"https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
,
"integrity"
:
"sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
,
"dev"
:
true
,
"license"
:
"Python-2.0"
,
"optional"
:
true
},
"node_modules/asynckit"
:
{
"version"
:
"0.4.0"
,
"resolved"
:
"https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz"
,
...
...
@@ -1347,6 +1584,7 @@
}
],
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"baseline-browser-mapping"
:
"^2.9.0"
,
"caniuse-lite"
:
"^1.0.30001759"
,
...
...
@@ -1374,6 +1612,17 @@
"node"
:
">= 0.4"
}
},
"node_modules/callsites"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
,
"integrity"
:
"sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=6"
}
},
"node_modules/camelcase-css"
:
{
"version"
:
"2.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz"
,
...
...
@@ -1405,11 +1654,30 @@
],
"license"
:
"CC-BY-4.0"
},
"node_modules/chalk"
:
{
"version"
:
"4.1.2"
,
"resolved"
:
"https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
,
"integrity"
:
"sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"ansi-styles"
:
"^4.1.0"
,
"supports-color"
:
"^7.1.0"
},
"engines"
:
{
"node"
:
">=10"
},
"funding"
:
{
"url"
:
"https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/chart.js"
:
{
"version"
:
"4.5.1"
,
"resolved"
:
"https://registry.npmmirror.com/chart.js/-/chart.js-4.5.1.tgz"
,
"integrity"
:
"sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw=="
,
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"@kurkle/color"
:
"^0.3.0"
},
...
...
@@ -1455,6 +1723,28 @@
"node"
:
">= 6"
}
},
"node_modules/color-convert"
:
{
"version"
:
"2.0.1"
,
"resolved"
:
"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
,
"integrity"
:
"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"color-name"
:
"~1.1.4"
},
"engines"
:
{
"node"
:
">=7.0.0"
}
},
"node_modules/color-name"
:
{
"version"
:
"1.1.4"
,
"resolved"
:
"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
,
"integrity"
:
"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/combined-stream"
:
{
"version"
:
"1.0.8"
,
"resolved"
:
"https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz"
,
...
...
@@ -1477,6 +1767,41 @@
"node"
:
">= 6"
}
},
"node_modules/concat-map"
:
{
"version"
:
"0.0.1"
,
"resolved"
:
"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
,
"integrity"
:
"sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/cross-spawn"
:
{
"version"
:
"7.0.6"
,
"resolved"
:
"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz"
,
"integrity"
:
"sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"path-key"
:
"^3.1.0"
,
"shebang-command"
:
"^2.0.0"
,
"which"
:
"^2.0.1"
},
"engines"
:
{
"node"
:
">= 8"
}
},
"node_modules/cross-spawn/node_modules/path-key"
:
{
"version"
:
"3.1.1"
,
"resolved"
:
"https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
,
"integrity"
:
"sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=8"
}
},
"node_modules/cssesc"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz"
,
...
...
@@ -1503,6 +1828,33 @@
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/debug"
:
{
"version"
:
"4.4.3"
,
"resolved"
:
"https://registry.npmjs.org/debug/-/debug-4.4.3.tgz"
,
"integrity"
:
"sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"ms"
:
"^2.1.3"
},
"engines"
:
{
"node"
:
">=6.0"
},
"peerDependenciesMeta"
:
{
"supports-color"
:
{
"optional"
:
true
}
}
},
"node_modules/deep-is"
:
{
"version"
:
"0.1.4"
,
"resolved"
:
"https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
,
"integrity"
:
"sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/delayed-stream"
:
{
"version"
:
"1.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz"
,
...
...
@@ -1526,6 +1878,20 @@
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/doctrine"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz"
,
"integrity"
:
"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="
,
"dev"
:
true
,
"license"
:
"Apache-2.0"
,
"optional"
:
true
,
"dependencies"
:
{
"esutils"
:
"^2.0.2"
},
"engines"
:
{
"node"
:
">=6.0.0"
}
},
"node_modules/dunder-proto"
:
{
"version"
:
"1.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz"
,
...
...
@@ -1653,58 +2019,211 @@
"node"
:
">=6"
}
},
"node_modules/estree-walker"
:
{
"version"
:
"2.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz"
,
"integrity"
:
"sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
,
"license"
:
"MIT"
},
"node_modules/fast-glob"
:
{
"version"
:
"3.3.3"
,
"resolved"
:
"https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz"
,
"integrity"
:
"sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="
,
"node_modules/escape-string-regexp"
:
{
"version"
:
"4.0.0"
,
"resolved"
:
"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
,
"integrity"
:
"sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"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.8"
},
"optional"
:
true
,
"engines"
:
{
"node"
:
">=8.6.0"
"node"
:
">=10"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/
fast-glob/node_modules/glob-parent
"
:
{
"version"
:
"
5.1
.2"
,
"resolved"
:
"https://registry.npm
mirror.com/glob-parent/-/glob-parent-5.1
.2.tgz"
,
"integrity"
:
"sha512-
AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow
=="
,
"node_modules/
eslint-scope
"
:
{
"version"
:
"
7.2
.2"
,
"resolved"
:
"https://registry.npm
js.org/eslint-scope/-/eslint-scope-7.2
.2.tgz"
,
"integrity"
:
"sha512-
dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg
=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"BSD-2-Clause"
,
"optional"
:
true
,
"dependencies"
:
{
"is-glob"
:
"^4.0.1"
"esrecurse"
:
"^4.3.0"
,
"estraverse"
:
"^5.2.0"
},
"engines"
:
{
"node"
:
">= 6"
"node"
:
"^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding"
:
{
"url"
:
"https://opencollective.com/eslint"
}
},
"node_modules/
fastq
"
:
{
"version"
:
"
1.19
.1"
,
"resolved"
:
"https://registry.npm
mirror.com/fastq/-/fastq-1.19
.1.tgz"
,
"integrity"
:
"sha512-
GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vv
Q=="
,
"node_modules/
espree
"
:
{
"version"
:
"
9.6
.1"
,
"resolved"
:
"https://registry.npm
js.org/espree/-/espree-9.6
.1.tgz"
,
"integrity"
:
"sha512-
oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdw
Q=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"license"
:
"BSD-2-Clause"
,
"optional"
:
true
,
"dependencies"
:
{
"reusify"
:
"^1.0.4"
"acorn"
:
"^8.9.0"
,
"acorn-jsx"
:
"^5.3.2"
,
"eslint-visitor-keys"
:
"^3.4.1"
},
"engines"
:
{
"node"
:
"^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding"
:
{
"url"
:
"https://opencollective.com/eslint"
}
},
"node_modules/
fill-range
"
:
{
"version"
:
"
7.1.1
"
,
"resolved"
:
"https://registry.npm
mirror.com/fill-range/-/fill-range-7.1.1
.tgz"
,
"integrity"
:
"sha512-
YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0y
g=="
,
"node_modules/
espree/node_modules/eslint-visitor-keys
"
:
{
"version"
:
"
3.4.3
"
,
"resolved"
:
"https://registry.npm
js.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3
.tgz"
,
"integrity"
:
"sha512-
wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+ia
g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"license"
:
"Apache-2.0"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
"^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding"
:
{
"url"
:
"https://opencollective.com/eslint"
}
},
"node_modules/esquery"
:
{
"version"
:
"1.6.0"
,
"resolved"
:
"https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz"
,
"integrity"
:
"sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="
,
"dev"
:
true
,
"license"
:
"BSD-3-Clause"
,
"optional"
:
true
,
"dependencies"
:
{
"estraverse"
:
"^5.1.0"
},
"engines"
:
{
"node"
:
">=0.10"
}
},
"node_modules/esrecurse"
:
{
"version"
:
"4.3.0"
,
"resolved"
:
"https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz"
,
"integrity"
:
"sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="
,
"dev"
:
true
,
"license"
:
"BSD-2-Clause"
,
"optional"
:
true
,
"dependencies"
:
{
"estraverse"
:
"^5.2.0"
},
"engines"
:
{
"node"
:
">=4.0"
}
},
"node_modules/estraverse"
:
{
"version"
:
"5.3.0"
,
"resolved"
:
"https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
,
"integrity"
:
"sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
,
"dev"
:
true
,
"license"
:
"BSD-2-Clause"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=4.0"
}
},
"node_modules/estree-walker"
:
{
"version"
:
"2.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz"
,
"integrity"
:
"sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
,
"license"
:
"MIT"
},
"node_modules/esutils"
:
{
"version"
:
"2.0.3"
,
"resolved"
:
"https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz"
,
"integrity"
:
"sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
,
"dev"
:
true
,
"license"
:
"BSD-2-Clause"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/fast-deep-equal"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
,
"integrity"
:
"sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/fast-glob"
:
{
"version"
:
"3.3.3"
,
"resolved"
:
"https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz"
,
"integrity"
:
"sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"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.8"
},
"engines"
:
{
"node"
:
">=8.6.0"
}
},
"node_modules/fast-glob/node_modules/glob-parent"
:
{
"version"
:
"5.1.2"
,
"resolved"
:
"https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz"
,
"integrity"
:
"sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"dependencies"
:
{
"is-glob"
:
"^4.0.1"
},
"engines"
:
{
"node"
:
">= 6"
}
},
"node_modules/fast-json-stable-stringify"
:
{
"version"
:
"2.1.0"
,
"resolved"
:
"https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz"
,
"integrity"
:
"sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/fast-levenshtein"
:
{
"version"
:
"2.0.6"
,
"resolved"
:
"https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
,
"integrity"
:
"sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/fastq"
:
{
"version"
:
"1.19.1"
,
"resolved"
:
"https://registry.npmmirror.com/fastq/-/fastq-1.19.1.tgz"
,
"integrity"
:
"sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"dependencies"
:
{
"reusify"
:
"^1.0.4"
}
},
"node_modules/file-entry-cache"
:
{
"version"
:
"6.0.1"
,
"resolved"
:
"https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
,
"integrity"
:
"sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"flat-cache"
:
"^3.0.4"
},
"engines"
:
{
"node"
:
"^10.12.0 || >=12.0.0"
}
},
"node_modules/fill-range"
:
{
"version"
:
"7.1.1"
,
"resolved"
:
"https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz"
,
"integrity"
:
"sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"dependencies"
:
{
"to-regex-range"
:
"^5.0.1"
},
...
...
@@ -1712,6 +2231,48 @@
"node"
:
">=8"
}
},
"node_modules/find-up"
:
{
"version"
:
"5.0.0"
,
"resolved"
:
"https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz"
,
"integrity"
:
"sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"locate-path"
:
"^6.0.0"
,
"path-exists"
:
"^4.0.0"
},
"engines"
:
{
"node"
:
">=10"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/flat-cache"
:
{
"version"
:
"3.2.0"
,
"resolved"
:
"https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz"
,
"integrity"
:
"sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"flatted"
:
"^3.2.9"
,
"keyv"
:
"^4.5.3"
,
"rimraf"
:
"^3.0.2"
},
"engines"
:
{
"node"
:
"^10.12.0 || >=12.0.0"
}
},
"node_modules/flatted"
:
{
"version"
:
"3.3.3"
,
"resolved"
:
"https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz"
,
"integrity"
:
"sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
},
"node_modules/follow-redirects"
:
{
"version"
:
"1.15.11"
,
"resolved"
:
"https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz"
,
...
...
@@ -1762,6 +2323,14 @@
"url"
:
"https://github.com/sponsors/rawify"
}
},
"node_modules/fs.realpath"
:
{
"version"
:
"1.0.0"
,
"resolved"
:
"https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
,
"integrity"
:
"sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
},
"node_modules/fsevents"
:
{
"version"
:
"2.3.3"
,
"resolved"
:
"https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz"
,
...
...
@@ -1823,6 +2392,29 @@
"node"
:
">= 0.4"
}
},
"node_modules/glob"
:
{
"version"
:
"7.2.3"
,
"resolved"
:
"https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
,
"integrity"
:
"sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="
,
"deprecated"
:
"Glob versions prior to v9 are no longer supported"
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
,
"dependencies"
:
{
"fs.realpath"
:
"^1.0.0"
,
"inflight"
:
"^1.0.4"
,
"inherits"
:
"2"
,
"minimatch"
:
"^3.1.1"
,
"once"
:
"^1.3.0"
,
"path-is-absolute"
:
"^1.0.0"
},
"engines"
:
{
"node"
:
"*"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/isaacs"
}
},
"node_modules/glob-parent"
:
{
"version"
:
"6.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz"
,
...
...
@@ -1836,6 +2428,49 @@
"node"
:
">=10.13.0"
}
},
"node_modules/glob/node_modules/brace-expansion"
:
{
"version"
:
"1.1.12"
,
"resolved"
:
"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz"
,
"integrity"
:
"sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"balanced-match"
:
"^1.0.0"
,
"concat-map"
:
"0.0.1"
}
},
"node_modules/glob/node_modules/minimatch"
:
{
"version"
:
"3.1.2"
,
"resolved"
:
"https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
,
"integrity"
:
"sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
,
"dependencies"
:
{
"brace-expansion"
:
"^1.1.7"
},
"engines"
:
{
"node"
:
"*"
}
},
"node_modules/globals"
:
{
"version"
:
"13.24.0"
,
"resolved"
:
"https://registry.npmjs.org/globals/-/globals-13.24.0.tgz"
,
"integrity"
:
"sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"type-fest"
:
"^0.20.2"
},
"engines"
:
{
"node"
:
">=8"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/gopd"
:
{
"version"
:
"1.2.0"
,
"resolved"
:
"https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz"
,
...
...
@@ -1848,6 +2483,25 @@
"url"
:
"https://github.com/sponsors/ljharb"
}
},
"node_modules/graphemer"
:
{
"version"
:
"1.4.0"
,
"resolved"
:
"https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz"
,
"integrity"
:
"sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/has-flag"
:
{
"version"
:
"4.0.0"
,
"resolved"
:
"https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
,
"integrity"
:
"sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=8"
}
},
"node_modules/has-symbols"
:
{
"version"
:
"1.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz"
,
...
...
@@ -1897,6 +2551,67 @@
"he"
:
"bin/he"
}
},
"node_modules/ignore"
:
{
"version"
:
"5.3.2"
,
"resolved"
:
"https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
,
"integrity"
:
"sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">= 4"
}
},
"node_modules/import-fresh"
:
{
"version"
:
"3.3.1"
,
"resolved"
:
"https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz"
,
"integrity"
:
"sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"parent-module"
:
"^1.0.0"
,
"resolve-from"
:
"^4.0.0"
},
"engines"
:
{
"node"
:
">=6"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/imurmurhash"
:
{
"version"
:
"0.1.4"
,
"resolved"
:
"https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz"
,
"integrity"
:
"sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=0.8.19"
}
},
"node_modules/inflight"
:
{
"version"
:
"1.0.6"
,
"resolved"
:
"https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
,
"integrity"
:
"sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="
,
"deprecated"
:
"This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful."
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
,
"dependencies"
:
{
"once"
:
"^1.3.0"
,
"wrappy"
:
"1"
}
},
"node_modules/inherits"
:
{
"version"
:
"2.0.4"
,
"resolved"
:
"https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
,
"integrity"
:
"sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
},
"node_modules/is-binary-path"
:
{
"version"
:
"2.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz"
,
...
...
@@ -1959,12 +2674,32 @@
"node"
:
">=0.12.0"
}
},
"node_modules/is-path-inside"
:
{
"version"
:
"3.0.3"
,
"resolved"
:
"https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz"
,
"integrity"
:
"sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=8"
}
},
"node_modules/isexe"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
,
"integrity"
:
"sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
},
"node_modules/jiti"
:
{
"version"
:
"1.21.7"
,
"resolved"
:
"https://registry.npmmirror.com/jiti/-/jiti-1.21.7.tgz"
,
"integrity"
:
"sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"peer"
:
true
,
"bin"
:
{
"jiti"
:
"bin/jiti.js"
}
...
...
@@ -1976,6 +2711,70 @@
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/js-yaml"
:
{
"version"
:
"4.1.1"
,
"resolved"
:
"https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz"
,
"integrity"
:
"sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"argparse"
:
"^2.0.1"
},
"bin"
:
{
"js-yaml"
:
"bin/js-yaml.js"
}
},
"node_modules/json-buffer"
:
{
"version"
:
"3.0.1"
,
"resolved"
:
"https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz"
,
"integrity"
:
"sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/json-schema-traverse"
:
{
"version"
:
"0.4.1"
,
"resolved"
:
"https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz"
,
"integrity"
:
"sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/json-stable-stringify-without-jsonify"
:
{
"version"
:
"1.0.1"
,
"resolved"
:
"https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz"
,
"integrity"
:
"sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/keyv"
:
{
"version"
:
"4.5.4"
,
"resolved"
:
"https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz"
,
"integrity"
:
"sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"json-buffer"
:
"3.0.1"
}
},
"node_modules/levn"
:
{
"version"
:
"0.4.1"
,
"resolved"
:
"https://registry.npmjs.org/levn/-/levn-0.4.1.tgz"
,
"integrity"
:
"sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"prelude-ls"
:
"^1.2.1"
,
"type-check"
:
"~0.4.0"
},
"engines"
:
{
"node"
:
">= 0.8.0"
}
},
"node_modules/lilconfig"
:
{
"version"
:
"3.1.3"
,
"resolved"
:
"https://registry.npmmirror.com/lilconfig/-/lilconfig-3.1.3.tgz"
,
...
...
@@ -1996,6 +2795,31 @@
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/locate-path"
:
{
"version"
:
"6.0.0"
,
"resolved"
:
"https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz"
,
"integrity"
:
"sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"p-locate"
:
"^5.0.0"
},
"engines"
:
{
"node"
:
">=10"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lodash.merge"
:
{
"version"
:
"4.6.2"
,
"resolved"
:
"https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
,
"integrity"
:
"sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/magic-string"
:
{
"version"
:
"0.30.21"
,
"resolved"
:
"https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz"
,
...
...
@@ -2075,6 +2899,14 @@
"url"
:
"https://github.com/sponsors/isaacs"
}
},
"node_modules/ms"
:
{
"version"
:
"2.1.3"
,
"resolved"
:
"https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
,
"integrity"
:
"sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/muggle-string"
:
{
"version"
:
"0.4.1"
,
"resolved"
:
"https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz"
,
...
...
@@ -2112,6 +2944,14 @@
"node"
:
"^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/natural-compare"
:
{
"version"
:
"1.4.0"
,
"resolved"
:
"https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
,
"integrity"
:
"sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/node-releases"
:
{
"version"
:
"2.0.27"
,
"resolved"
:
"https://registry.npmmirror.com/node-releases/-/node-releases-2.0.27.tgz"
,
...
...
@@ -2166,6 +3006,84 @@
"node"
:
">= 6"
}
},
"node_modules/once"
:
{
"version"
:
"1.4.0"
,
"resolved"
:
"https://registry.npmjs.org/once/-/once-1.4.0.tgz"
,
"integrity"
:
"sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
,
"dependencies"
:
{
"wrappy"
:
"1"
}
},
"node_modules/optionator"
:
{
"version"
:
"0.9.4"
,
"resolved"
:
"https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz"
,
"integrity"
:
"sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"deep-is"
:
"^0.1.3"
,
"fast-levenshtein"
:
"^2.0.6"
,
"levn"
:
"^0.4.1"
,
"prelude-ls"
:
"^1.2.1"
,
"type-check"
:
"^0.4.0"
,
"word-wrap"
:
"^1.2.5"
},
"engines"
:
{
"node"
:
">= 0.8.0"
}
},
"node_modules/p-limit"
:
{
"version"
:
"3.1.0"
,
"resolved"
:
"https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz"
,
"integrity"
:
"sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"yocto-queue"
:
"^0.1.0"
},
"engines"
:
{
"node"
:
">=10"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate"
:
{
"version"
:
"5.0.0"
,
"resolved"
:
"https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz"
,
"integrity"
:
"sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"p-limit"
:
"^3.0.2"
},
"engines"
:
{
"node"
:
">=10"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parent-module"
:
{
"version"
:
"1.0.1"
,
"resolved"
:
"https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
,
"integrity"
:
"sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"callsites"
:
"^3.0.0"
},
"engines"
:
{
"node"
:
">=6"
}
},
"node_modules/path-browserify"
:
{
"version"
:
"1.0.1"
,
"resolved"
:
"https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz"
,
...
...
@@ -2173,6 +3091,28 @@
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/path-exists"
:
{
"version"
:
"4.0.0"
,
"resolved"
:
"https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz"
,
"integrity"
:
"sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=8"
}
},
"node_modules/path-is-absolute"
:
{
"version"
:
"1.0.1"
,
"resolved"
:
"https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
,
"integrity"
:
"sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/path-key"
:
{
"version"
:
"4.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz"
,
...
...
@@ -2273,6 +3213,7 @@
}
],
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"nanoid"
:
"^3.3.11"
,
"picocolors"
:
"^1.1.1"
,
...
...
@@ -2416,12 +3357,34 @@
"dev"
:
true
,
"license"
:
"MIT"
},
"node_modules/prelude-ls"
:
{
"version"
:
"1.2.1"
,
"resolved"
:
"https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
,
"integrity"
:
"sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">= 0.8.0"
}
},
"node_modules/proxy-from-env"
:
{
"version"
:
"1.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz"
,
"integrity"
:
"sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
,
"license"
:
"MIT"
},
"node_modules/punycode"
:
{
"version"
:
"2.3.1"
,
"resolved"
:
"https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz"
,
"integrity"
:
"sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=6"
}
},
"node_modules/queue-microtask"
:
{
"version"
:
"1.2.3"
,
"resolved"
:
"https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz"
,
...
...
@@ -2487,6 +3450,17 @@
"url"
:
"https://github.com/sponsors/ljharb"
}
},
"node_modules/resolve-from"
:
{
"version"
:
"4.0.0"
,
"resolved"
:
"https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
,
"integrity"
:
"sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=4"
}
},
"node_modules/reusify"
:
{
"version"
:
"1.1.0"
,
"resolved"
:
"https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz"
,
...
...
@@ -2498,6 +3472,24 @@
"node"
:
">=0.10.0"
}
},
"node_modules/rimraf"
:
{
"version"
:
"3.0.2"
,
"resolved"
:
"https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz"
,
"integrity"
:
"sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="
,
"deprecated"
:
"Rimraf versions prior to v4 are no longer supported"
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
,
"dependencies"
:
{
"glob"
:
"^7.1.3"
},
"bin"
:
{
"rimraf"
:
"bin.js"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/isaacs"
}
},
"node_modules/rollup"
:
{
"version"
:
"4.53.5"
,
"resolved"
:
"https://registry.npmmirror.com/rollup/-/rollup-4.53.5.tgz"
,
...
...
@@ -2564,6 +3556,31 @@
"queue-microtask"
:
"^1.2.2"
}
},
"node_modules/shebang-command"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
,
"integrity"
:
"sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"shebang-regex"
:
"^3.0.0"
},
"engines"
:
{
"node"
:
">=8"
}
},
"node_modules/shebang-regex"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
,
"integrity"
:
"sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=8"
}
},
"node_modules/source-map-js"
:
{
"version"
:
"1.2.1"
,
"resolved"
:
"https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz"
,
...
...
@@ -2589,6 +3606,20 @@
"url"
:
"https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/strip-json-comments"
:
{
"version"
:
"3.1.1"
,
"resolved"
:
"https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
,
"integrity"
:
"sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=8"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/sucrase"
:
{
"version"
:
"3.35.1"
,
"resolved"
:
"https://registry.npmmirror.com/sucrase/-/sucrase-3.35.1.tgz"
,
...
...
@@ -2612,6 +3643,20 @@
"node"
:
">=16 || 14 >=14.17"
}
},
"node_modules/supports-color"
:
{
"version"
:
"7.2.0"
,
"resolved"
:
"https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
,
"integrity"
:
"sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"has-flag"
:
"^4.0.0"
},
"engines"
:
{
"node"
:
">=8"
}
},
"node_modules/supports-preserve-symlinks-flag"
:
{
"version"
:
"1.0.0"
,
"resolved"
:
"https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
,
...
...
@@ -2663,6 +3708,14 @@
"node"
:
">=14.0.0"
}
},
"node_modules/text-table"
:
{
"version"
:
"0.2.0"
,
"resolved"
:
"https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
,
"integrity"
:
"sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
},
"node_modules/thenify"
:
{
"version"
:
"3.3.1"
,
"resolved"
:
"https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz"
,
...
...
@@ -2734,6 +3787,7 @@
"integrity"
:
"sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"peer"
:
true
,
"engines"
:
{
"node"
:
">=12"
},
...
...
@@ -2761,12 +3815,41 @@
"dev"
:
true
,
"license"
:
"Apache-2.0"
},
"node_modules/type-check"
:
{
"version"
:
"0.4.0"
,
"resolved"
:
"https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz"
,
"integrity"
:
"sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"dependencies"
:
{
"prelude-ls"
:
"^1.2.1"
},
"engines"
:
{
"node"
:
">= 0.8.0"
}
},
"node_modules/type-fest"
:
{
"version"
:
"0.20.2"
,
"resolved"
:
"https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
,
"integrity"
:
"sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="
,
"dev"
:
true
,
"license"
:
"(MIT OR CC0-1.0)"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=10"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typescript"
:
{
"version"
:
"5.6.3"
,
"resolved"
:
"https://registry.npmmirror.com/typescript/-/typescript-5.6.3.tgz"
,
"integrity"
:
"sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="
,
"devOptional"
:
true
,
"license"
:
"Apache-2.0"
,
"peer"
:
true
,
"bin"
:
{
"tsc"
:
"bin/tsc"
,
"tsserver"
:
"bin/tsserver"
...
...
@@ -2826,6 +3909,17 @@
"browserslist"
:
">= 4.21.0"
}
},
"node_modules/uri-js"
:
{
"version"
:
"4.4.1"
,
"resolved"
:
"https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz"
,
"integrity"
:
"sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="
,
"dev"
:
true
,
"license"
:
"BSD-2-Clause"
,
"optional"
:
true
,
"dependencies"
:
{
"punycode"
:
"^2.1.0"
}
},
"node_modules/util-deprecate"
:
{
"version"
:
"1.0.2"
,
"resolved"
:
"https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz"
,
...
...
@@ -2839,6 +3933,7 @@
"integrity"
:
"sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"esbuild"
:
"^0.21.3"
,
"postcss"
:
"^8.4.43"
,
...
...
@@ -3010,6 +4105,7 @@
"resolved"
:
"https://registry.npmmirror.com/vue/-/vue-3.5.25.tgz"
,
"integrity"
:
"sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g=="
,
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"@vue/compiler-dom"
:
"3.5.25"
,
"@vue/compiler-sfc"
:
"3.5.25"
,
...
...
@@ -3103,6 +4199,7 @@
"integrity"
:
"sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"peer"
:
true
,
"dependencies"
:
{
"@volar/typescript"
:
"2.4.15"
,
"@vue/language-core"
:
"2.2.12"
...
...
@@ -3113,6 +4210,56 @@
"peerDependencies"
:
{
"typescript"
:
">=5.0.0"
}
},
"node_modules/which"
:
{
"version"
:
"2.0.2"
,
"resolved"
:
"https://registry.npmjs.org/which/-/which-2.0.2.tgz"
,
"integrity"
:
"sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
,
"dependencies"
:
{
"isexe"
:
"^2.0.0"
},
"bin"
:
{
"node-which"
:
"bin/node-which"
},
"engines"
:
{
"node"
:
">= 8"
}
},
"node_modules/word-wrap"
:
{
"version"
:
"1.2.5"
,
"resolved"
:
"https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz"
,
"integrity"
:
"sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=0.10.0"
}
},
"node_modules/wrappy"
:
{
"version"
:
"1.0.2"
,
"resolved"
:
"https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
,
"integrity"
:
"sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
,
"dev"
:
true
,
"license"
:
"ISC"
,
"optional"
:
true
},
"node_modules/yocto-queue"
:
{
"version"
:
"0.1.0"
,
"resolved"
:
"https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
,
"integrity"
:
"sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
,
"dev"
:
true
,
"license"
:
"MIT"
,
"optional"
:
true
,
"engines"
:
{
"node"
:
">=10"
},
"funding"
:
{
"url"
:
"https://github.com/sponsors/sindresorhus"
}
}
}
}
frontend/postcss.config.js
View file @
429f38d0
export
default
{
plugins
:
{
tailwindcss
:
{},
autoprefixer
:
{}
,
}
,
autoprefixer
:
{}
}
}
frontend/src/App.vue
View file @
429f38d0
...
...
@@ -26,17 +26,25 @@ function updateFavicon(logoUrl: string) {
}
// Watch for site settings changes and update favicon/title
watch
(()
=>
appStore
.
siteLogo
,
(
newLogo
)
=>
{
if
(
newLogo
)
{
updateFavicon
(
newLogo
)
}
},
{
immediate
:
true
})
watch
(
()
=>
appStore
.
siteLogo
,
(
newLogo
)
=>
{
if
(
newLogo
)
{
updateFavicon
(
newLogo
)
}
},
{
immediate
:
true
}
)
watch
(()
=>
appStore
.
siteName
,
(
newName
)
=>
{
if
(
newName
)
{
document
.
title
=
`
${
newName
}
- AI API Gateway`
}
},
{
immediate
:
true
})
watch
(
()
=>
appStore
.
siteName
,
(
newName
)
=>
{
if
(
newName
)
{
document
.
title
=
`
${
newName
}
- AI API Gateway`
}
},
{
immediate
:
true
}
)
onMounted
(
async
()
=>
{
// Check if setup is needed
...
...
frontend/src/api/admin/accounts.ts
View file @
429f38d0
...
...
@@ -12,7 +12,7 @@ import type {
AccountUsageInfo
,
WindowStats
,
ClaudeModel
,
AccountUsageStatsResponse
,
AccountUsageStatsResponse
}
from
'
@/types
'
/**
...
...
@@ -36,8 +36,8 @@ export async function list(
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
}
,
...
filters
}
})
return
data
}
...
...
@@ -129,7 +129,7 @@ export async function refreshCredentials(id: number): Promise<Account> {
*/
export
async
function
getStats
(
id
:
number
,
days
:
number
=
30
):
Promise
<
AccountUsageStatsResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
AccountUsageStatsResponse
>
(
`/admin/accounts/
${
id
}
/stats`
,
{
params
:
{
days
}
,
params
:
{
days
}
})
return
data
}
...
...
@@ -254,7 +254,7 @@ export async function bulkUpdate(
results
:
Array
<
{
account_id
:
number
;
success
:
boolean
;
error
?:
string
}
>
}
>
(
'
/admin/accounts/bulk-update
'
,
{
account_ids
:
accountIds
,
...
updates
,
...
updates
})
return
data
}
...
...
@@ -277,7 +277,7 @@ export async function getTodayStats(id: number): Promise<WindowStats> {
*/
export
async
function
setSchedulable
(
id
:
number
,
schedulable
:
boolean
):
Promise
<
Account
>
{
const
{
data
}
=
await
apiClient
.
post
<
Account
>
(
`/admin/accounts/
${
id
}
/schedulable`
,
{
schedulable
,
schedulable
})
return
data
}
...
...
@@ -335,7 +335,7 @@ export const accountsAPI = {
batchCreate
,
batchUpdateCredentials
,
bulkUpdate
,
syncFromCrs
,
syncFromCrs
}
export
default
accountsAPI
frontend/src/api/admin/dashboard.ts
View file @
429f38d0
...
...
@@ -3,16 +3,22 @@
* Provides system-wide statistics and metrics
*/
import
{
apiClient
}
from
'
../client
'
;
import
type
{
DashboardStats
,
TrendDataPoint
,
ModelStat
,
ApiKeyUsageTrendPoint
,
UserUsageTrendPoint
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
DashboardStats
,
TrendDataPoint
,
ModelStat
,
ApiKeyUsageTrendPoint
,
UserUsageTrendPoint
}
from
'
@/types
'
/**
* Get dashboard statistics
* @returns Dashboard statistics including users, keys, accounts, and token usage
*/
export
async
function
getStats
():
Promise
<
DashboardStats
>
{
const
{
data
}
=
await
apiClient
.
get
<
DashboardStats
>
(
'
/admin/dashboard/stats
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
DashboardStats
>
(
'
/admin/dashboard/stats
'
)
return
data
}
/**
...
...
@@ -20,33 +26,33 @@ export async function getStats(): Promise<DashboardStats> {
* @returns Real-time system metrics
*/
export
async
function
getRealtimeMetrics
():
Promise
<
{
active_requests
:
number
;
requests_per_minute
:
number
;
average_response_time
:
number
;
error_rate
:
number
;
active_requests
:
number
requests_per_minute
:
number
average_response_time
:
number
error_rate
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
active_requests
:
number
;
requests_per_minute
:
number
;
average_response_time
:
number
;
error_rate
:
number
;
}
>
(
'
/admin/dashboard/realtime
'
)
;
return
data
;
active_requests
:
number
requests_per_minute
:
number
average_response_time
:
number
error_rate
:
number
}
>
(
'
/admin/dashboard/realtime
'
)
return
data
}
export
interface
TrendParams
{
start_date
?:
string
;
end_date
?:
string
;
granularity
?:
'
day
'
|
'
hour
'
;
user_id
?:
number
;
api_key_id
?:
number
;
start_date
?:
string
end_date
?:
string
granularity
?:
'
day
'
|
'
hour
'
user_id
?:
number
api_key_id
?:
number
}
export
interface
TrendResponse
{
trend
:
TrendDataPoint
[]
;
start_date
:
string
;
end_date
:
string
;
granularity
:
string
;
trend
:
TrendDataPoint
[]
start_date
:
string
end_date
:
string
granularity
:
string
}
/**
...
...
@@ -55,21 +61,21 @@ export interface TrendResponse {
* @returns Usage trend data
*/
export
async
function
getUsageTrend
(
params
?:
TrendParams
):
Promise
<
TrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
TrendResponse
>
(
'
/admin/dashboard/trend
'
,
{
params
})
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
TrendResponse
>
(
'
/admin/dashboard/trend
'
,
{
params
})
return
data
}
export
interface
ModelStatsParams
{
start_date
?:
string
;
end_date
?:
string
;
user_id
?:
number
;
api_key_id
?:
number
;
start_date
?:
string
end_date
?:
string
user_id
?:
number
api_key_id
?:
number
}
export
interface
ModelStatsResponse
{
models
:
ModelStat
[]
;
start_date
:
string
;
end_date
:
string
;
models
:
ModelStat
[]
start_date
:
string
end_date
:
string
}
/**
...
...
@@ -78,19 +84,19 @@ export interface ModelStatsResponse {
* @returns Model usage statistics
*/
export
async
function
getModelStats
(
params
?:
ModelStatsParams
):
Promise
<
ModelStatsResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
ModelStatsResponse
>
(
'
/admin/dashboard/models
'
,
{
params
})
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
ModelStatsResponse
>
(
'
/admin/dashboard/models
'
,
{
params
})
return
data
}
export
interface
ApiKeyTrendParams
extends
TrendParams
{
limit
?:
number
;
limit
?:
number
}
export
interface
ApiKeyTrendResponse
{
trend
:
ApiKeyUsageTrendPoint
[]
;
start_date
:
string
;
end_date
:
string
;
granularity
:
string
;
trend
:
ApiKeyUsageTrendPoint
[]
start_date
:
string
end_date
:
string
granularity
:
string
}
/**
...
...
@@ -98,20 +104,24 @@ export interface ApiKeyTrendResponse {
* @param params - Query parameters for filtering
* @returns API key usage trend data
*/
export
async
function
getApiKeyUsageTrend
(
params
?:
ApiKeyTrendParams
):
Promise
<
ApiKeyTrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
ApiKeyTrendResponse
>
(
'
/admin/dashboard/api-keys-trend
'
,
{
params
});
return
data
;
export
async
function
getApiKeyUsageTrend
(
params
?:
ApiKeyTrendParams
):
Promise
<
ApiKeyTrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
ApiKeyTrendResponse
>
(
'
/admin/dashboard/api-keys-trend
'
,
{
params
})
return
data
}
export
interface
UserTrendParams
extends
TrendParams
{
limit
?:
number
;
limit
?:
number
}
export
interface
UserTrendResponse
{
trend
:
UserUsageTrendPoint
[]
;
start_date
:
string
;
end_date
:
string
;
granularity
:
string
;
trend
:
UserUsageTrendPoint
[]
start_date
:
string
end_date
:
string
granularity
:
string
}
/**
...
...
@@ -120,18 +130,20 @@ export interface UserTrendResponse {
* @returns User usage trend data
*/
export
async
function
getUserUsageTrend
(
params
?:
UserTrendParams
):
Promise
<
UserTrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
UserTrendResponse
>
(
'
/admin/dashboard/users-trend
'
,
{
params
});
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
UserTrendResponse
>
(
'
/admin/dashboard/users-trend
'
,
{
params
})
return
data
}
export
interface
BatchUserUsageStats
{
user_id
:
number
;
today_actual_cost
:
number
;
total_actual_cost
:
number
;
user_id
:
number
today_actual_cost
:
number
total_actual_cost
:
number
}
export
interface
BatchUsersUsageResponse
{
stats
:
Record
<
string
,
BatchUserUsageStats
>
;
stats
:
Record
<
string
,
BatchUserUsageStats
>
}
/**
...
...
@@ -141,19 +153,19 @@ export interface BatchUsersUsageResponse {
*/
export
async
function
getBatchUsersUsage
(
userIds
:
number
[]):
Promise
<
BatchUsersUsageResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
BatchUsersUsageResponse
>
(
'
/admin/dashboard/users-usage
'
,
{
user_ids
:
userIds
,
})
;
return
data
;
user_ids
:
userIds
})
return
data
}
export
interface
BatchApiKeyUsageStats
{
api_key_id
:
number
;
today_actual_cost
:
number
;
total_actual_cost
:
number
;
api_key_id
:
number
today_actual_cost
:
number
total_actual_cost
:
number
}
export
interface
BatchApiKeysUsageResponse
{
stats
:
Record
<
string
,
BatchApiKeyUsageStats
>
;
stats
:
Record
<
string
,
BatchApiKeyUsageStats
>
}
/**
...
...
@@ -161,11 +173,16 @@ export interface BatchApiKeysUsageResponse {
* @param apiKeyIds - Array of API key IDs
* @returns Usage stats map keyed by API key ID
*/
export
async
function
getBatchApiKeysUsage
(
apiKeyIds
:
number
[]):
Promise
<
BatchApiKeysUsageResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
BatchApiKeysUsageResponse
>
(
'
/admin/dashboard/api-keys-usage
'
,
{
api_key_ids
:
apiKeyIds
,
});
return
data
;
export
async
function
getBatchApiKeysUsage
(
apiKeyIds
:
number
[]
):
Promise
<
BatchApiKeysUsageResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
BatchApiKeysUsageResponse
>
(
'
/admin/dashboard/api-keys-usage
'
,
{
api_key_ids
:
apiKeyIds
}
)
return
data
}
export
const
dashboardAPI
=
{
...
...
@@ -176,7 +193,7 @@ export const dashboardAPI = {
getApiKeyUsageTrend
,
getUserUsageTrend
,
getBatchUsersUsage
,
getBatchApiKeysUsage
,
}
;
getBatchApiKeysUsage
}
export
default
dashboardAPI
;
export
default
dashboardAPI
frontend/src/api/admin/gemini.ts
0 → 100644
View file @
429f38d0
/**
* Admin Gemini API endpoints
* Handles Gemini OAuth flows for administrators
*/
import
{
apiClient
}
from
'
../client
'
export
interface
GeminiAuthUrlResponse
{
auth_url
:
string
session_id
:
string
state
:
string
}
export
interface
GeminiOAuthCapabilities
{
ai_studio_oauth_enabled
:
boolean
required_redirect_uris
:
string
[]
}
export
interface
GeminiAuthUrlRequest
{
proxy_id
?:
number
project_id
?:
string
oauth_type
?:
'
code_assist
'
|
'
ai_studio
'
}
export
interface
GeminiExchangeCodeRequest
{
session_id
:
string
state
:
string
code
:
string
proxy_id
?:
number
oauth_type
?:
'
code_assist
'
|
'
ai_studio
'
}
export
type
GeminiTokenInfo
=
Record
<
string
,
unknown
>
export
async
function
generateAuthUrl
(
payload
:
GeminiAuthUrlRequest
):
Promise
<
GeminiAuthUrlResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
GeminiAuthUrlResponse
>
(
'
/admin/gemini/oauth/auth-url
'
,
payload
)
return
data
}
export
async
function
exchangeCode
(
payload
:
GeminiExchangeCodeRequest
):
Promise
<
GeminiTokenInfo
>
{
const
{
data
}
=
await
apiClient
.
post
<
GeminiTokenInfo
>
(
'
/admin/gemini/oauth/exchange-code
'
,
payload
)
return
data
}
export
async
function
getCapabilities
():
Promise
<
GeminiOAuthCapabilities
>
{
const
{
data
}
=
await
apiClient
.
get
<
GeminiOAuthCapabilities
>
(
'
/admin/gemini/oauth/capabilities
'
)
return
data
}
export
default
{
generateAuthUrl
,
exchangeCode
,
getCapabilities
}
frontend/src/api/admin/groups.ts
View file @
429f38d0
...
...
@@ -3,14 +3,14 @@
* Handles API key group management for administrators
*/
import
{
apiClient
}
from
'
../client
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
Group
,
GroupPlatform
,
CreateGroupRequest
,
UpdateGroupRequest
,
PaginatedResponse
,
}
from
'
@/types
'
;
PaginatedResponse
}
from
'
@/types
'
/**
* List all groups with pagination
...
...
@@ -23,19 +23,19 @@ export async function list(
page
:
number
=
1
,
pageSize
:
number
=
20
,
filters
?:
{
platform
?:
GroupPlatform
;
status
?:
'
active
'
|
'
inactive
'
;
is_exclusive
?:
boolean
;
platform
?:
GroupPlatform
status
?:
'
active
'
|
'
inactive
'
is_exclusive
?:
boolean
}
):
Promise
<
PaginatedResponse
<
Group
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
Group
>>
(
'
/admin/groups
'
,
{
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
}
,
})
;
return
data
;
...
filters
}
})
return
data
}
/**
...
...
@@ -46,8 +46,8 @@ export async function list(
export
async
function
getAll
(
platform
?:
GroupPlatform
):
Promise
<
Group
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
Group
[]
>
(
'
/admin/groups/all
'
,
{
params
:
platform
?
{
platform
}
:
undefined
})
;
return
data
;
})
return
data
}
/**
...
...
@@ -56,7 +56,7 @@ export async function getAll(platform?: GroupPlatform): Promise<Group[]> {
* @returns List of groups for the specified platform
*/
export
async
function
getByPlatform
(
platform
:
GroupPlatform
):
Promise
<
Group
[]
>
{
return
getAll
(
platform
)
;
return
getAll
(
platform
)
}
/**
...
...
@@ -65,8 +65,8 @@ export async function getByPlatform(platform: GroupPlatform): Promise<Group[]> {
* @returns Group details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
Group
>
{
const
{
data
}
=
await
apiClient
.
get
<
Group
>
(
`/admin/groups/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
Group
>
(
`/admin/groups/
${
id
}
`
)
return
data
}
/**
...
...
@@ -75,8 +75,8 @@ export async function getById(id: number): Promise<Group> {
* @returns Created group
*/
export
async
function
create
(
groupData
:
CreateGroupRequest
):
Promise
<
Group
>
{
const
{
data
}
=
await
apiClient
.
post
<
Group
>
(
'
/admin/groups
'
,
groupData
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
Group
>
(
'
/admin/groups
'
,
groupData
)
return
data
}
/**
...
...
@@ -86,8 +86,8 @@ export async function create(groupData: CreateGroupRequest): Promise<Group> {
* @returns Updated group
*/
export
async
function
update
(
id
:
number
,
updates
:
UpdateGroupRequest
):
Promise
<
Group
>
{
const
{
data
}
=
await
apiClient
.
put
<
Group
>
(
`/admin/groups/
${
id
}
`
,
updates
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
put
<
Group
>
(
`/admin/groups/
${
id
}
`
,
updates
)
return
data
}
/**
...
...
@@ -96,8 +96,8 @@ export async function update(id: number, updates: UpdateGroupRequest): Promise<G
* @returns Success confirmation
*/
export
async
function
deleteGroup
(
id
:
number
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/groups/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/groups/
${
id
}
`
)
return
data
}
/**
...
...
@@ -106,11 +106,8 @@ export async function deleteGroup(id: number): Promise<{ message: string }> {
* @param status - New status
* @returns Updated group
*/
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
Group
>
{
return
update
(
id
,
{
status
});
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
Group
>
{
return
update
(
id
,
{
status
})
}
/**
...
...
@@ -119,18 +116,18 @@ export async function toggleStatus(
* @returns Group usage statistics
*/
export
async
function
getStats
(
id
:
number
):
Promise
<
{
total_api_keys
:
number
;
active_api_keys
:
number
;
total_requests
:
number
;
total_cost
:
number
;
total_api_keys
:
number
active_api_keys
:
number
total_requests
:
number
total_cost
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
total_api_keys
:
number
;
active_api_keys
:
number
;
total_requests
:
number
;
total_cost
:
number
;
}
>
(
`/admin/groups/
${
id
}
/stats`
)
;
return
data
;
total_api_keys
:
number
active_api_keys
:
number
total_requests
:
number
total_cost
:
number
}
>
(
`/admin/groups/
${
id
}
/stats`
)
return
data
}
/**
...
...
@@ -145,13 +142,10 @@ export async function getGroupApiKeys(
page
:
number
=
1
,
pageSize
:
number
=
20
):
Promise
<
PaginatedResponse
<
any
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/groups/
${
id
}
/api-keys`
,
{
params
:
{
page
,
page_size
:
pageSize
},
}
);
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/groups/
${
id
}
/api-keys`
,
{
params
:
{
page
,
page_size
:
pageSize
}
})
return
data
}
export
const
groupsAPI
=
{
...
...
@@ -164,7 +158,7 @@ export const groupsAPI = {
delete
:
deleteGroup
,
toggleStatus
,
getStats
,
getGroupApiKeys
,
}
;
getGroupApiKeys
}
export
default
groupsAPI
;
export
default
groupsAPI
frontend/src/api/admin/index.ts
View file @
429f38d0
...
...
@@ -3,16 +3,17 @@
* Centralized exports for all admin API modules
*/
import
dashboardAPI
from
'
./dashboard
'
;
import
usersAPI
from
'
./users
'
;
import
groupsAPI
from
'
./groups
'
;
import
accountsAPI
from
'
./accounts
'
;
import
proxiesAPI
from
'
./proxies
'
;
import
redeemAPI
from
'
./redeem
'
;
import
settingsAPI
from
'
./settings
'
;
import
systemAPI
from
'
./system
'
;
import
subscriptionsAPI
from
'
./subscriptions
'
;
import
usageAPI
from
'
./usage
'
;
import
dashboardAPI
from
'
./dashboard
'
import
usersAPI
from
'
./users
'
import
groupsAPI
from
'
./groups
'
import
accountsAPI
from
'
./accounts
'
import
proxiesAPI
from
'
./proxies
'
import
redeemAPI
from
'
./redeem
'
import
settingsAPI
from
'
./settings
'
import
systemAPI
from
'
./system
'
import
subscriptionsAPI
from
'
./subscriptions
'
import
usageAPI
from
'
./usage
'
import
geminiAPI
from
'
./gemini
'
/**
* Unified admin API object for convenient access
...
...
@@ -28,8 +29,21 @@ export const adminAPI = {
system
:
systemAPI
,
subscriptions
:
subscriptionsAPI
,
usage
:
usageAPI
,
};
gemini
:
geminiAPI
}
export
{
dashboardAPI
,
usersAPI
,
groupsAPI
,
accountsAPI
,
proxiesAPI
,
redeemAPI
,
settingsAPI
,
systemAPI
,
subscriptionsAPI
,
usageAPI
};
export
{
dashboardAPI
,
usersAPI
,
groupsAPI
,
accountsAPI
,
proxiesAPI
,
redeemAPI
,
settingsAPI
,
systemAPI
,
subscriptionsAPI
,
usageAPI
,
geminiAPI
}
export
default
adminAPI
;
export
default
adminAPI
frontend/src/api/admin/proxies.ts
View file @
429f38d0
...
...
@@ -3,13 +3,8 @@
* Handles proxy server management for administrators
*/
import
{
apiClient
}
from
'
../client
'
;
import
type
{
Proxy
,
CreateProxyRequest
,
UpdateProxyRequest
,
PaginatedResponse
,
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
Proxy
,
CreateProxyRequest
,
UpdateProxyRequest
,
PaginatedResponse
}
from
'
@/types
'
/**
* List all proxies with pagination
...
...
@@ -22,19 +17,19 @@ export async function list(
page
:
number
=
1
,
pageSize
:
number
=
20
,
filters
?:
{
protocol
?:
string
;
status
?:
'
active
'
|
'
inactive
'
;
search
?:
string
;
protocol
?:
string
status
?:
'
active
'
|
'
inactive
'
search
?:
string
}
):
Promise
<
PaginatedResponse
<
Proxy
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
Proxy
>>
(
'
/admin/proxies
'
,
{
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
}
,
})
;
return
data
;
...
filters
}
})
return
data
}
/**
...
...
@@ -42,8 +37,8 @@ export async function list(
* @returns List of all active proxies
*/
export
async
function
getAll
():
Promise
<
Proxy
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
Proxy
[]
>
(
'
/admin/proxies/all
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
Proxy
[]
>
(
'
/admin/proxies/all
'
)
return
data
}
/**
...
...
@@ -52,9 +47,9 @@ export async function getAll(): Promise<Proxy[]> {
*/
export
async
function
getAllWithCount
():
Promise
<
Proxy
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
Proxy
[]
>
(
'
/admin/proxies/all
'
,
{
params
:
{
with_count
:
'
true
'
}
,
})
;
return
data
;
params
:
{
with_count
:
'
true
'
}
})
return
data
}
/**
...
...
@@ -63,8 +58,8 @@ export async function getAllWithCount(): Promise<Proxy[]> {
* @returns Proxy details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
Proxy
>
{
const
{
data
}
=
await
apiClient
.
get
<
Proxy
>
(
`/admin/proxies/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
Proxy
>
(
`/admin/proxies/
${
id
}
`
)
return
data
}
/**
...
...
@@ -73,8 +68,8 @@ export async function getById(id: number): Promise<Proxy> {
* @returns Created proxy
*/
export
async
function
create
(
proxyData
:
CreateProxyRequest
):
Promise
<
Proxy
>
{
const
{
data
}
=
await
apiClient
.
post
<
Proxy
>
(
'
/admin/proxies
'
,
proxyData
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
Proxy
>
(
'
/admin/proxies
'
,
proxyData
)
return
data
}
/**
...
...
@@ -84,8 +79,8 @@ export async function create(proxyData: CreateProxyRequest): Promise<Proxy> {
* @returns Updated proxy
*/
export
async
function
update
(
id
:
number
,
updates
:
UpdateProxyRequest
):
Promise
<
Proxy
>
{
const
{
data
}
=
await
apiClient
.
put
<
Proxy
>
(
`/admin/proxies/
${
id
}
`
,
updates
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
put
<
Proxy
>
(
`/admin/proxies/
${
id
}
`
,
updates
)
return
data
}
/**
...
...
@@ -94,8 +89,8 @@ export async function update(id: number, updates: UpdateProxyRequest): Promise<P
* @returns Success confirmation
*/
export
async
function
deleteProxy
(
id
:
number
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/proxies/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/proxies/
${
id
}
`
)
return
data
}
/**
...
...
@@ -104,11 +99,8 @@ export async function deleteProxy(id: number): Promise<{ message: string }> {
* @param status - New status
* @returns Updated proxy
*/
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
Proxy
>
{
return
update
(
id
,
{
status
});
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
Proxy
>
{
return
update
(
id
,
{
status
})
}
/**
...
...
@@ -117,24 +109,24 @@ export async function toggleStatus(
* @returns Test result with IP info
*/
export
async
function
testProxy
(
id
:
number
):
Promise
<
{
success
:
boolean
;
message
:
string
;
latency_ms
?:
number
;
ip_address
?:
string
;
city
?:
string
;
region
?:
string
;
country
?:
string
;
success
:
boolean
message
:
string
latency_ms
?:
number
ip_address
?:
string
city
?:
string
region
?:
string
country
?:
string
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
success
:
boolean
;
message
:
string
;
latency_ms
?:
number
;
ip_address
?:
string
;
city
?:
string
;
region
?:
string
;
country
?:
string
;
}
>
(
`/admin/proxies/
${
id
}
/test`
)
;
return
data
;
success
:
boolean
message
:
string
latency_ms
?:
number
ip_address
?:
string
city
?:
string
region
?:
string
country
?:
string
}
>
(
`/admin/proxies/
${
id
}
/test`
)
return
data
}
/**
...
...
@@ -143,20 +135,20 @@ export async function testProxy(id: number): Promise<{
* @returns Proxy usage statistics
*/
export
async
function
getStats
(
id
:
number
):
Promise
<
{
total_accounts
:
number
;
active_accounts
:
number
;
total_requests
:
number
;
success_rate
:
number
;
average_latency
:
number
;
total_accounts
:
number
active_accounts
:
number
total_requests
:
number
success_rate
:
number
average_latency
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
total_accounts
:
number
;
active_accounts
:
number
;
total_requests
:
number
;
success_rate
:
number
;
average_latency
:
number
;
}
>
(
`/admin/proxies/
${
id
}
/stats`
)
;
return
data
;
total_accounts
:
number
active_accounts
:
number
total_requests
:
number
success_rate
:
number
average_latency
:
number
}
>
(
`/admin/proxies/
${
id
}
/stats`
)
return
data
}
/**
...
...
@@ -165,10 +157,8 @@ export async function getStats(id: number): Promise<{
* @returns List of accounts using the proxy
*/
export
async
function
getProxyAccounts
(
id
:
number
):
Promise
<
PaginatedResponse
<
any
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/proxies/
${
id
}
/accounts`
);
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/proxies/
${
id
}
/accounts`
)
return
data
}
/**
...
...
@@ -176,21 +166,23 @@ export async function getProxyAccounts(id: number): Promise<PaginatedResponse<an
* @param proxies - Array of proxy data to create
* @returns Creation result with count of created and skipped
*/
export
async
function
batchCreate
(
proxies
:
Array
<
{
protocol
:
string
;
host
:
string
;
port
:
number
;
username
?:
string
;
password
?:
string
;
}
>
):
Promise
<
{
created
:
number
;
skipped
:
number
;
export
async
function
batchCreate
(
proxies
:
Array
<
{
protocol
:
string
host
:
string
port
:
number
username
?:
string
password
?:
string
}
>
):
Promise
<
{
created
:
number
skipped
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
created
:
number
;
skipped
:
number
;
}
>
(
'
/admin/proxies/batch
'
,
{
proxies
})
;
return
data
;
created
:
number
skipped
:
number
}
>
(
'
/admin/proxies/batch
'
,
{
proxies
})
return
data
}
export
const
proxiesAPI
=
{
...
...
@@ -205,7 +197,7 @@ export const proxiesAPI = {
testProxy
,
getStats
,
getProxyAccounts
,
batchCreate
,
}
;
batchCreate
}
export
default
proxiesAPI
;
export
default
proxiesAPI
Prev
1
2
3
4
5
6
7
…
9
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment