refactor(请求): 去掉 axios,所有请求统一从 authFetch 出门;换 token 时断网不再平白弹登录框
Deploy / deploy (push) Canceled after 0s
Deploy / deploy (push) Canceled after 0s
utils/api 改成基于 authFetch 的一层 fetch 封装,调用方用法不变;下载测试点也走 authFetch,token 过期时会换一张重试。换 token 那一步断网时,AI 流式接口和自学上报 原来会拿掉 token 重发、弹登录框,现在和普通请求一样报「网络异常」。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
13843c79a0
commit
d6c3171d13
9 files changed
+103
-192
No files matched your search
+7
-6
@@ -95,13 +95,14 @@ shared → ./src/shared
|
||||
|
||||
### HTTP Client
|
||||
|
||||
`utils/api.ts` — Axios instance with interceptors (`baseURL: "/api"`). It unwraps both
|
||||
the axios envelope and the backend's `{ data }` envelope, so callers get the payload
|
||||
directly. All API calls proxy through the dev server (see `vite.config.ts`).
|
||||
`utils/api.ts` — 薄薄一层 fetch 封装(没有 axios),前缀 `/api`,get / post / put / delete
|
||||
四个方法。它剥掉后端的 `{ data }` 信封,调用方直接拿到业务数据;失败抛 `ApiError`。
|
||||
dev 下由 `vite.config.ts` 的 proxy 转给后端。
|
||||
|
||||
登录态是 `Authorization: Bearer` 的 access token(15 分钟)+ refresh token,都在
|
||||
localStorage,换 token 的逻辑全在 `utils/auth.ts`。**不走 axios 的请求用 `authFetch`
|
||||
代替裸 `fetch`**,否则不带 token、也不会在 `token-expired` 时换一张重试。
|
||||
localStorage,换 token 的逻辑全在 `utils/auth.ts`。**所有请求都从 `authFetch` 出门**
|
||||
(`utils/api` 也是),要自己发 fetch(流式、`keepalive`、下载二进制)时用它代替裸
|
||||
`fetch`,否则不带 token、也不会在 `token-expired` 时换一张重试。
|
||||
WebSocket 的 token 借子协议带(浏览器设不了请求头),见契约 `WS_AUTH_PROTOCOL`。
|
||||
|
||||
### Contract guard (`utils/contract.ts`)
|
||||
@@ -179,7 +180,7 @@ Env files: `.env`(本机)、`.env.production`(服务器)、`.env.staging
|
||||
| `PUBLIC_CODE_URL` | 代码分享服务(提交详情、题目页的「分享」) |
|
||||
| `PUBLIC_ICONIFY_URL` | 自建 Iconify 图标源,不设则走公共 CDN |
|
||||
|
||||
后端地址**不在这里**:`utils/api.ts` 写死 `baseURL: "/api"`,dev 由 `vite.config.ts` 的
|
||||
后端地址**不在这里**:`utils/api.ts` 写死前缀 `/api`,dev 由 `vite.config.ts` 的
|
||||
proxy 转给 3000,线上由 Caddy 同源伺服。
|
||||
|
||||
### Routing
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
"@vueuse/router": "^15.0.0",
|
||||
"@wangeditor-next/editor": "^6.5.0",
|
||||
"@wangeditor-next/editor-for-vue": "^6.5.0",
|
||||
"axios": "^1.20.0",
|
||||
"canvas-confetti": "^1.9.4",
|
||||
"chart.js": "^4.5.1",
|
||||
"chartjs-chart-wordcloud": "^4.4.5",
|
||||
|
||||
@@ -304,9 +304,7 @@ export async function uploadImage(file: File): Promise<string> {
|
||||
success: boolean
|
||||
filePath: string
|
||||
msg: string
|
||||
}>("admin/upload-image", form, {
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
})
|
||||
}>("admin/upload-image", form)
|
||||
return res.success ? res.filePath : ""
|
||||
}
|
||||
|
||||
@@ -317,9 +315,7 @@ export function uploadTestcases(file: File, options: { sql?: boolean } = {}) {
|
||||
if (options.sql) {
|
||||
form.append("sql", "1")
|
||||
}
|
||||
return api.post<UploadTestCaseResponse>("admin/test-cases", form, {
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
})
|
||||
return api.post<UploadTestCaseResponse>("admin/test-cases", form)
|
||||
}
|
||||
|
||||
// SQL 题测试点预览:后端跑一遍初始化脚本+标准答案,返回数据表和期望结果展示数据
|
||||
|
||||
@@ -93,7 +93,7 @@ export function getProblemProgress() {
|
||||
|
||||
/**
|
||||
* 「随便来一道」:当前知识点和类型里,先挑能用 language 做的、自己没做对的简单 / 中等题,
|
||||
* 返回题号。空串的参数拦截器会去掉
|
||||
* 返回题号。空串的参数 utils/api 会去掉
|
||||
*/
|
||||
export function getRandomProblem(params: { tag: string; type: string; language: string }) {
|
||||
return api.get<string>("problems/random", { params })
|
||||
@@ -357,9 +357,7 @@ export function getContestClassView(contestID: string) {
|
||||
export function uploadAvatar(file: File) {
|
||||
const form = new window.FormData()
|
||||
form.append("image", file)
|
||||
return api.post("me/avatar", form, {
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
})
|
||||
return api.post("me/avatar", form)
|
||||
}
|
||||
|
||||
export function updateProfile(data: { realName?: string; mood?: string }) {
|
||||
@@ -551,8 +549,8 @@ export function getLearnProgress(type: "python" | "c") {
|
||||
/**
|
||||
* 上报自学留痕。`opened` 为真表示刚进这一课,否则只是补停留时长。
|
||||
*
|
||||
* 走裸 fetch 而不是 axios,是为了 `keepalive`:离开页面那一下的最后一次上报,
|
||||
* axios 发出去也会随页面卸载被浏览器掐掉,学生每节课的最后一段时长就永远丢了。
|
||||
* 直接走 authFetch 而不是 utils/api,是为了 `keepalive`:离开页面那一下的最后一次上报,
|
||||
* 不带它会随页面卸载被浏览器掐掉,学生每节课的最后一段时长就永远丢了。
|
||||
* 失败一律吞掉 —— 留痕是旁路,不该让学生看到任何报错。
|
||||
*/
|
||||
export function reportLearnProgress(
|
||||
|
||||
+61
-79
@@ -1,11 +1,6 @@
|
||||
import axios, {
|
||||
type AxiosRequestConfig,
|
||||
type AxiosResponse,
|
||||
type InternalAxiosRequestConfig,
|
||||
} from "axios"
|
||||
import { createDiscreteApi } from "naive-ui"
|
||||
import { useAuthModalStore } from "shared/store/authModal"
|
||||
import { getAccessToken, refreshAccessToken } from "./auth"
|
||||
import { authFetch } from "./auth"
|
||||
import { STORAGE_KEY } from "./constants"
|
||||
import storage from "./storage"
|
||||
|
||||
@@ -20,7 +15,7 @@ interface ErrorPayload {
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截器 reject 出来的就是它:`error` 是错误码,`data` 是后端文案。
|
||||
* 请求失败时抛的就是它:`error` 是错误码,`data` 是后端文案。
|
||||
*
|
||||
* 字段名沿用原来那个裸对象 `{ error, data }`,存量调用点读 `err.error` / `err.data`
|
||||
* 的语义不变;做成 Error 的子类是为了在 catch 里能和代码 bug(TypeError 之类)分开,
|
||||
@@ -50,26 +45,12 @@ export function errorMessage(err: unknown, fallback = "未知错误") {
|
||||
return isApiError(err) && err.data ? err.data : fallback
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功时直接拿到业务数据本身。后端成功响应是 `{ data }`(见 apps/api/src/http.ts
|
||||
* 的 success),拦截器把 axios 外层和这层信封一起剥掉。
|
||||
*
|
||||
* 失败走 reject,形状是 `{ error: 错误码, data: 文案 }` —— 和成功路径不对称是
|
||||
* 故意的:成功没有错误码可言。分支处理一律判 `err.error` 里的错误码。
|
||||
*/
|
||||
interface ApiClient {
|
||||
get<T>(url: string, config?: AxiosRequestConfig): Promise<T>
|
||||
post<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>
|
||||
put<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T>
|
||||
delete<T>(url: string, config?: AxiosRequestConfig): Promise<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* 这几种错误全站都是同样的处理,不放在这里的话每个调用点都得自己 catch,
|
||||
* 漏一个就是「点了没反应」。需要分支处理的调用方一律判 `err.error` 里的
|
||||
* 错误码,**不要**去 match `err.data` 的文案 —— 文案是后端可以随时改的。
|
||||
*
|
||||
* 导出给不走 axios 的请求用(AI 的流式接口是裸 fetch,见 utils/stream.ts)——
|
||||
* 导出给不走 api 客户端的请求用(AI 的流式接口,见 utils/stream.ts)——
|
||||
* 同一个错误码从两条路进来,学生看到的结果不该有两个样子。
|
||||
*/
|
||||
/** handleGlobalApiError 已经替调用方提示过的错误码,调用方别再弹第二遍 */
|
||||
@@ -94,68 +75,69 @@ export function handleGlobalApiError(code: string, message?: string) {
|
||||
}
|
||||
}
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: "/api",
|
||||
})
|
||||
const NETWORK_ERROR_MESSAGE = "网络异常,请检查网络后重试"
|
||||
|
||||
/** 已经因为 token-expired 重试过一次的请求,别再进第二轮,也别再被请求拦截器换 token */
|
||||
type RetriableConfig = InternalAxiosRequestConfig & { authRetried?: boolean }
|
||||
interface RequestConfig {
|
||||
/** 拼进 query string。值是 ""、null、undefined 的键直接丢掉,调用方不用自己挑 */
|
||||
params?: Record<string, unknown>
|
||||
/** 请求体,只给 delete 用:别的方法的请求体走第二个参数 */
|
||||
data?: unknown
|
||||
}
|
||||
|
||||
instance.interceptors.request.use(async (config: RetriableConfig) => {
|
||||
if (!config.authRetried) {
|
||||
const token = await getAccessToken()
|
||||
if (token) config.headers.set("Authorization", `Bearer ${token}`)
|
||||
function withQuery(url: string, params?: Record<string, unknown>) {
|
||||
const query = new URLSearchParams()
|
||||
for (const [key, value] of Object.entries(params ?? {})) {
|
||||
if (value !== "" && value !== null && value !== undefined) query.append(key, String(value))
|
||||
}
|
||||
if (config.params) {
|
||||
config.params = Object.fromEntries(
|
||||
Object.entries(config.params).filter(
|
||||
([, value]) => value !== "" && value !== null && value !== undefined,
|
||||
),
|
||||
)
|
||||
const search = query.toString()
|
||||
return search ? `${url}?${search}` : url
|
||||
}
|
||||
|
||||
async function request<T>(method: string, url: string, body: unknown, config: RequestConfig = {}) {
|
||||
const init: RequestInit = { method }
|
||||
// FormData 不能手动设 Content-Type:multipart 的 boundary 得让浏览器自己写进去
|
||||
if (body instanceof FormData) {
|
||||
init.body = body
|
||||
} else if (body !== undefined) {
|
||||
init.headers = { "Content-Type": "application/json" }
|
||||
init.body = JSON.stringify(body)
|
||||
}
|
||||
return config
|
||||
})
|
||||
|
||||
instance.interceptors.response.use(
|
||||
// 这里**故意**不返回 AxiosResponse:把 axios 的外层和后端的 { data } 信封一起
|
||||
// 剥掉,让调用方直接拿到业务数据。类型上和 axios 的拦截器签名对不上(它期望原样
|
||||
// 返回响应),文件末尾的 `as unknown as ApiClient` 就是为了把真实形状交出去。
|
||||
((response: AxiosResponse) => response.data.data) as unknown as (
|
||||
response: AxiosResponse,
|
||||
) => AxiosResponse,
|
||||
async (error) => {
|
||||
const payload = error.response?.data as ErrorPayload | undefined
|
||||
const code = payload?.error?.code ?? "network-error"
|
||||
// 没有响应体 = 请求根本没到后端(断网、反代挂了、超时),学生看到的就是这一句
|
||||
const message = payload?.error?.message ?? "网络异常,请检查网络后重试"
|
||||
let response: Response
|
||||
try {
|
||||
response = await authFetch(withQuery(`/api/${url}`, config.params), init)
|
||||
} catch {
|
||||
// 请求根本没到后端(断网、反代挂了),学生看到的就是这一句
|
||||
throw new ApiError("network-error", NETWORK_ERROR_MESSAGE)
|
||||
}
|
||||
const payload = (await response.json().catch(() => null)) as ({ data?: T } & ErrorPayload) | null
|
||||
if (response.ok) return payload?.data as T
|
||||
|
||||
// access token 不能用了(过期、被吊销):拿 refresh token 换一张,原请求重发一次。
|
||||
// 重发的结果照样走这两个拦截器,调用方拿到的和一次成功没有区别
|
||||
const config = error.config as RetriableConfig | undefined
|
||||
if (code === "token-expired" && config && !config.authRetried) {
|
||||
config.authRetried = true
|
||||
const sent = String(config.headers.get("Authorization") ?? "").replace(/^Bearer /, "")
|
||||
const outcome = await refreshAccessToken(sent)
|
||||
if (outcome.token) {
|
||||
config.headers.set("Authorization", `Bearer ${outcome.token}`)
|
||||
return instance.request(config)
|
||||
}
|
||||
if (outcome.code === "network-error") {
|
||||
return Promise.reject(new ApiError("network-error", "网络异常,请检查网络后重试"))
|
||||
}
|
||||
if (outcome.code === "account-disabled") {
|
||||
handleGlobalApiError("account-disabled")
|
||||
return Promise.reject(new ApiError("account-disabled", "账号已被禁用,请联系老师"))
|
||||
}
|
||||
// 登录真的过期了。拿掉 token 重发:要登录的接口回 login-required 弹登录框,
|
||||
// 可选登录的(首页、题目列表……)照常当游客看,不平白弹框
|
||||
config.headers.delete("Authorization")
|
||||
return instance.request(config)
|
||||
}
|
||||
// 没有 JSON 信封 = 不是后端回的(网关的错误页之类),当网络问题
|
||||
const code = payload?.error?.code ?? "network-error"
|
||||
const message = payload?.error?.message ?? NETWORK_ERROR_MESSAGE
|
||||
handleGlobalApiError(code, message)
|
||||
throw new ApiError(code, message)
|
||||
}
|
||||
|
||||
handleGlobalApiError(code, message)
|
||||
return Promise.reject(new ApiError(code, message))
|
||||
},
|
||||
)
|
||||
/**
|
||||
* 成功时直接拿到业务数据本身:后端成功响应是 `{ data }`(见 apps/api/src/http.ts
|
||||
* 的 success),这层信封在这里剥掉。
|
||||
*
|
||||
* 失败抛 ApiError,`error` 是错误码、`data` 是文案 —— 和成功路径不对称是故意的:
|
||||
* 成功没有错误码可言。分支处理一律判 `err.error` 里的错误码。
|
||||
*
|
||||
* token 过期换一张重发、换不到当游客重发,都在 authFetch 里,调用方拿到的和一次
|
||||
* 成功没有区别。
|
||||
*/
|
||||
const api = {
|
||||
get: <T>(url: string, config?: RequestConfig) => request<T>("GET", url, undefined, config),
|
||||
post: <T>(url: string, data?: unknown, config?: RequestConfig) =>
|
||||
request<T>("POST", url, data, config),
|
||||
put: <T>(url: string, data?: unknown, config?: RequestConfig) =>
|
||||
request<T>("PUT", url, data, config),
|
||||
delete: <T>(url: string, config?: RequestConfig) =>
|
||||
request<T>("DELETE", url, config?.data, config),
|
||||
}
|
||||
|
||||
export default instance as unknown as ApiClient
|
||||
export default api
|
||||
@@ -86,7 +86,7 @@ async function runRefresh(stale?: string): Promise<RefreshOutcome> {
|
||||
|
||||
let response: Response
|
||||
try {
|
||||
// 裸 fetch:走 utils/api 的 axios 会再进它的拦截器,绕回这里
|
||||
// 裸 fetch:走 authFetch / utils/api 会再来换 token,绕回这里
|
||||
response = await fetch("/api/auth/refresh", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -135,9 +135,11 @@ async function responseCode(response: Response) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 不走 axios 的请求(AI 流式接口、离开页面时的 keepalive 上报)用它代替 fetch:
|
||||
* 带上 token,后端回 `token-expired` 就换一张重试一次 —— 和 utils/api.ts 拦截器
|
||||
* 是同一套规矩。
|
||||
* 带登录态的 fetch,所有发往后端的请求都从这里出门(utils/api 也是):带上 token,
|
||||
* 后端回 `token-expired` 就换一张重试一次。
|
||||
*
|
||||
* 换 token 那一步断了网就照 fetch 的样子 reject —— 这时候拿掉 token 重发,要登录的
|
||||
* 接口会回 login-required,学生平白看到登录框,而真正的原因只是网络抖了一下。
|
||||
*/
|
||||
export async function authFetch(input: string, init: RequestInit = {}) {
|
||||
const send = (token: string | null) =>
|
||||
@@ -154,6 +156,7 @@ export async function authFetch(input: string, init: RequestInit = {}) {
|
||||
if ((await responseCode(response)) !== "token-expired") return response
|
||||
|
||||
const outcome = await refreshAccessToken(token)
|
||||
if (outcome.code === "network-error") throw new TypeError("换 token 时网络异常")
|
||||
// 账号被禁用:换 token 那一步就知道了,原请求不必再发。造一个和后端同形的响应,
|
||||
// 调用方按原样处理(弹「账号已被禁用」而不是登录框)
|
||||
if (outcome.code === "account-disabled") {
|
||||
|
||||
@@ -1,58 +1,35 @@
|
||||
import axios from "axios"
|
||||
import { createDiscreteApi } from "naive-ui"
|
||||
import { getAccessToken } from "./auth"
|
||||
|
||||
// 指向新后端的 /api/admin。响应是 zip 二进制,不走 { error, data } 信封,
|
||||
// 所以不能复用 utils/api 的拦截器(它会把 response.data.data 取出来)。
|
||||
const http = axios.create({
|
||||
baseURL: "/api/admin",
|
||||
responseType: "blob",
|
||||
})
|
||||
|
||||
http.interceptors.request.use(async (config) => {
|
||||
const token = await getAccessToken()
|
||||
if (token) config.headers.set("Authorization", `Bearer ${token}`)
|
||||
return config
|
||||
})
|
||||
import { authFetch } from "./auth"
|
||||
|
||||
// 脱离 n-message-provider 也能弹,理由同 utils/api.ts
|
||||
const { message: toast } = createDiscreteApi(["message"])
|
||||
|
||||
/**
|
||||
* 失败时把错误信封读出来。`responseType: "blob"` 是给成功路径(zip)设的,
|
||||
* 出错时 axios 照样把 JSON 信封包成 Blob 交回来,直接 `.error.message` 取不到。
|
||||
*/
|
||||
async function failureMessage(error: unknown) {
|
||||
const data = (error as { response?: { data?: unknown } }).response?.data
|
||||
if (data instanceof Blob) {
|
||||
try {
|
||||
const payload = JSON.parse(await data.text())
|
||||
const message = payload?.error?.message
|
||||
if (typeof message === "string" && message) return message
|
||||
} catch {
|
||||
// 不是 JSON(网关的 HTML 错误页之类),走下面的兜底文案
|
||||
}
|
||||
}
|
||||
return "下载失败"
|
||||
/** 失败时读后端的错误信封;不是 JSON(网关的 HTML 错误页之类)就用兜底文案 */
|
||||
async function failureMessage(response: Response) {
|
||||
const payload = (await response.json().catch(() => null)) as {
|
||||
error?: { message?: string }
|
||||
} | null
|
||||
const message = payload?.error?.message
|
||||
return typeof message === "string" && message ? message : "下载失败"
|
||||
}
|
||||
|
||||
// 指向 /api/admin。响应是 zip 二进制,不走 { error, data } 信封,所以不经 utils/api
|
||||
async function download(url: string) {
|
||||
let res
|
||||
let response: Response
|
||||
try {
|
||||
res = await http.get(url)
|
||||
} catch (error) {
|
||||
response = await authFetch(`/api/admin/${url}`)
|
||||
} catch {
|
||||
toast.error("下载失败")
|
||||
return
|
||||
}
|
||||
if (!response.ok) {
|
||||
// 以前这里什么都不接:题目还没传测试点时后端回 404,页面上一点反应都没有
|
||||
toast.error(await failureMessage(error))
|
||||
toast.error(await failureMessage(response))
|
||||
return
|
||||
}
|
||||
const headers = res.headers
|
||||
const link = document.createElement("a")
|
||||
link.href = window.URL.createObjectURL(
|
||||
new window.Blob([res.data], {
|
||||
type: String(headers["content-type"] ?? ""),
|
||||
}),
|
||||
)
|
||||
link.download = (headers["content-disposition"] || "").split("filename=")[1]
|
||||
link.href = window.URL.createObjectURL(await response.blob())
|
||||
link.download = (response.headers.get("content-disposition") || "").split("filename=")[1] ?? ""
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
link.remove()
|
||||
|
||||
@@ -100,8 +100,8 @@ export async function consumeJSONEventStream<T = any>(
|
||||
* AI 端点的非 2xx 响应体是 JSON 不是 SSE,直接丢给上面的解析器只会抛
|
||||
* 「无法解析服务端事件数据: {...}」。后端 error.message 是英文的,按 code 换成中文。
|
||||
*
|
||||
* 登录失效 / 账号禁用走和 axios 拦截器同一套处理(弹登录框 / 提示禁用)——
|
||||
* 原来这里裸 fetch 绕过了拦截器,未登录时只显示一句「AI 分析生成失败」。
|
||||
* 登录失效 / 账号禁用走和 utils/api 同一套处理(弹登录框 / 提示禁用)——
|
||||
* 原来这里裸 fetch 绕过了那边,未登录时只显示一句「AI 分析生成失败」。
|
||||
*/
|
||||
async function aiStreamError(response: Response) {
|
||||
const body = (await response.json().catch(() => null)) as {
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
"@vueuse/router": "^15.0.0",
|
||||
"@wangeditor-next/editor": "^6.5.0",
|
||||
"@wangeditor-next/editor-for-vue": "^6.5.0",
|
||||
"axios": "^1.20.0",
|
||||
"canvas-confetti": "^1.9.4",
|
||||
"chart.js": "^4.5.1",
|
||||
"chartjs-chart-wordcloud": "^4.4.5",
|
||||
@@ -839,8 +838,6 @@
|
||||
|
||||
"acorn": ["acorn@8.18.0", "https://registry.npmjs.com/acorn/-/acorn-8.18.0.tgz", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
|
||||
|
||||
"agent-base": ["agent-base@6.0.2", "https://registry.npmjs.com/agent-base/-/agent-base-6.0.2.tgz", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||
|
||||
"alien-signals": ["alien-signals@3.2.1", "https://registry.npmjs.com/alien-signals/-/alien-signals-3.2.1.tgz", {}, "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmjs.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
@@ -859,10 +856,6 @@
|
||||
|
||||
"async-validator": ["async-validator@4.2.5", "https://registry.npmjs.com/async-validator/-/async-validator-4.2.5.tgz", {}, "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="],
|
||||
|
||||
"asynckit": ["asynckit@0.4.0", "https://registry.npmjs.com/asynckit/-/asynckit-0.4.0.tgz", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
|
||||
"axios": ["axios@1.20.0", "https://registry.npmjs.com/axios/-/axios-1.20.0.tgz", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.6", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg=="],
|
||||
|
||||
"babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.17", "https://registry.npmjs.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w=="],
|
||||
|
||||
"babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.14.2", "https://registry.npmjs.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8", "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g=="],
|
||||
@@ -883,8 +876,6 @@
|
||||
|
||||
"bun-types": ["bun-types@1.4.0", "https://registry.npmjs.com/bun-types/-/bun-types-1.4.0.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-iIKw23BspnQQYd3prITOBxeUsxBHnwzX6YJfGMuNOZzeNcMmVqzIIVGRm1l69ogaPQmb4wB6BN8mA5bE9YuC5Q=="],
|
||||
|
||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "https://registry.npmjs.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001810", "https://registry.npmjs.com/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", {}, "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg=="],
|
||||
|
||||
"canvas-confetti": ["canvas-confetti@1.9.4", "https://registry.npmjs.com/canvas-confetti/-/canvas-confetti-1.9.4.tgz", {}, "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw=="],
|
||||
@@ -901,8 +892,6 @@
|
||||
|
||||
"codemirror": ["codemirror@6.0.2", "https://registry.npmjs.com/codemirror/-/codemirror-6.0.2.tgz", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/lint": "^6.0.0", "@codemirror/search": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" } }, "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw=="],
|
||||
|
||||
"combined-stream": ["combined-stream@1.0.8", "https://registry.npmjs.com/combined-stream/-/combined-stream-1.0.8.tgz", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
|
||||
"commander": ["commander@2.20.3", "https://registry.npmjs.com/commander/-/commander-2.20.3.tgz", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
|
||||
"compute-scroll-into-view": ["compute-scroll-into-view@3.1.1", "https://registry.npmjs.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", {}, "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw=="],
|
||||
@@ -937,8 +926,6 @@
|
||||
|
||||
"debug": ["debug@4.4.3", "https://registry.npmjs.com/debug/-/debug-4.4.3.tgz", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"delayed-stream": ["delayed-stream@1.0.0", "https://registry.npmjs.com/delayed-stream/-/delayed-stream-1.0.0.tgz", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||
|
||||
"denque": ["denque@2.1.0", "https://registry.npmjs.com/denque/-/denque-2.1.0.tgz", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="],
|
||||
|
||||
"dequal": ["dequal@2.0.3", "https://registry.npmjs.com/dequal/-/dequal-2.0.3.tgz", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
||||
@@ -953,22 +940,14 @@
|
||||
|
||||
"drizzle-orm": ["drizzle-orm@0.45.4", "https://registry.npmjs.com/drizzle-orm/-/drizzle-orm-0.45.4.tgz", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@netlify/db": ">=0.4.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "prisma": "*", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@netlify/db", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "prisma", "sql.js", "sqlite3"] }, "sha512-NiM1YZpJ2UxyeE67DpDDZ+Tsw4YLX3trSlkNT7Tm9eKoUNb1LvaAaQzXgYQsWs+AQ9TUmmwMmBOCXuqqxUWKKQ=="],
|
||||
|
||||
"dunder-proto": ["dunder-proto@1.0.1", "https://registry.npmjs.com/dunder-proto/-/dunder-proto-1.0.1.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.430", "https://registry.npmjs.com/electron-to-chromium/-/electron-to-chromium-1.5.430.tgz", {}, "sha512-e1QEj72Y4zd8RlNZVmoTg+iCOSVwpk05IOiiQwdrkwCSVlZfPthevErhE+nckGd2YbsXfp1SkisznhGVIXP2NQ=="],
|
||||
|
||||
"entities": ["entities@4.5.0", "https://registry.npmjs.com/entities/-/entities-4.5.0.tgz", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||
|
||||
"es-define-property": ["es-define-property@1.0.1", "https://registry.npmjs.com/es-define-property/-/es-define-property-1.0.1.tgz", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||
|
||||
"es-errors": ["es-errors@1.3.0", "https://registry.npmjs.com/es-errors/-/es-errors-1.3.0.tgz", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||
|
||||
"es-module-lexer": ["es-module-lexer@2.3.2", "https://registry.npmjs.com/es-module-lexer/-/es-module-lexer-2.3.2.tgz", {}, "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw=="],
|
||||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.2", "https://registry.npmjs.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
|
||||
|
||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "https://registry.npmjs.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
"es5-ext": ["es5-ext@0.10.64", "https://registry.npmjs.com/es5-ext/-/es5-ext-0.10.64.tgz", { "dependencies": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", "esniff": "^2.0.1", "next-tick": "^1.1.0" } }, "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg=="],
|
||||
|
||||
"es6-iterator": ["es6-iterator@2.0.3", "https://registry.npmjs.com/es6-iterator/-/es6-iterator-2.0.3.tgz", { "dependencies": { "d": "1", "es5-ext": "^0.10.35", "es6-symbol": "^3.1.1" } }, "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g=="],
|
||||
@@ -1003,28 +982,14 @@
|
||||
|
||||
"flatted": ["flatted@3.4.4", "https://registry.npmjs.com/flatted/-/flatted-3.4.4.tgz", {}, "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q=="],
|
||||
|
||||
"follow-redirects": ["follow-redirects@1.16.0", "https://registry.npmjs.com/follow-redirects/-/follow-redirects-1.16.0.tgz", {}, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="],
|
||||
|
||||
"form-data": ["form-data@4.0.6", "https://registry.npmjs.com/form-data/-/form-data-4.0.6.tgz", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.4", "mime-types": "^2.1.35" } }, "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "https://registry.npmjs.com/fsevents/-/fsevents-2.3.3.tgz", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "https://registry.npmjs.com/function-bind/-/function-bind-1.1.2.tgz", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"gensync": ["gensync@1.0.0-beta.2", "https://registry.npmjs.com/gensync/-/gensync-1.0.0-beta.2.tgz", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
|
||||
|
||||
"get-intrinsic": ["get-intrinsic@1.3.0", "https://registry.npmjs.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||
|
||||
"get-proto": ["get-proto@1.0.1", "https://registry.npmjs.com/get-proto/-/get-proto-1.0.1.tgz", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
||||
"get-tsconfig": ["get-tsconfig@4.14.1", "https://registry.npmjs.com/get-tsconfig/-/get-tsconfig-4.14.1.tgz", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-Dz/6HxkrxgNehhxLVeyv8sad9UzF2xBVeaKBQNDfJ5XiSXmp2gTR0eO0RWiT2NCKS5aGP9jjkOMggTN90qU50A=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "https://registry.npmjs.com/gopd/-/gopd-1.2.0.tgz", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"has-symbols": ["has-symbols@1.1.0", "https://registry.npmjs.com/has-symbols/-/has-symbols-1.1.0.tgz", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||
|
||||
"has-tostringtag": ["has-tostringtag@1.0.2", "https://registry.npmjs.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||
|
||||
"hasown": ["hasown@2.0.4", "https://registry.npmjs.com/hasown/-/hasown-2.0.4.tgz", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
|
||||
|
||||
"highlight.js": ["highlight.js@11.12.0", "https://registry.npmjs.com/highlight.js/-/highlight.js-11.12.0.tgz", {}, "sha512-nbfWpyRMcMrPMmDwJB+dhX/eiaPKtc2RB+0QZskqJ3WjRA/FDS0e9hZrx8EC/lbEv8gXy98FcDbNa/dspAaJMg=="],
|
||||
@@ -1035,8 +1000,6 @@
|
||||
|
||||
"html-void-elements": ["html-void-elements@3.0.0", "https://registry.npmjs.com/html-void-elements/-/html-void-elements-3.0.0.tgz", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
|
||||
|
||||
"https-proxy-agent": ["https-proxy-agent@5.0.1", "https://registry.npmjs.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
||||
|
||||
"i18next": ["i18next@23.16.8", "https://registry.npmjs.com/i18next/-/i18next-23.16.8.tgz", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="],
|
||||
|
||||
"ioredis": ["ioredis@6.0.0", "https://registry.npmjs.com/ioredis/-/ioredis-6.0.0.tgz", { "dependencies": { "@ioredis/commands": "2.0.0", "cluster-key-slot": "1.1.1", "debug": "4.4.3", "denque": "2.1.0", "redis-errors": "1.2.0", "standard-as-callback": "2.1.0" } }, "sha512-f+Dtubxfpf6KYFq7WVXJoOLn0bk4TJrMrN9SzeE+jrWrCWj7XX3fA6vkryafhADX+GMymRxgDJDOI33COkJc0w=="],
|
||||
@@ -1115,18 +1078,12 @@
|
||||
|
||||
"markdown-it": ["markdown-it@14.3.0", "https://registry.npmjs.com/markdown-it/-/markdown-it-14.3.0.tgz", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.5.0", "linkify-it": "^5.0.2", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "https://registry.npmjs.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
"mdurl": ["mdurl@2.1.0", "https://registry.npmjs.com/mdurl/-/mdurl-2.1.0.tgz", {}, "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg=="],
|
||||
|
||||
"meow": ["meow@13.2.0", "https://registry.npmjs.com/meow/-/meow-13.2.0.tgz", {}, "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA=="],
|
||||
|
||||
"mime-db": ["mime-db@1.52.0", "https://registry.npmjs.com/mime-db/-/mime-db-1.52.0.tgz", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"mime-match": ["mime-match@1.0.2", "https://registry.npmjs.com/mime-match/-/mime-match-1.0.2.tgz", { "dependencies": { "wildcard": "^1.1.0" } }, "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg=="],
|
||||
|
||||
"mime-types": ["mime-types@2.1.35", "https://registry.npmjs.com/mime-types/-/mime-types-2.1.35.tgz", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"mlly": ["mlly@1.8.2", "https://registry.npmjs.com/mlly/-/mlly-1.8.2.tgz", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="],
|
||||
|
||||
"mrmime": ["mrmime@2.0.1", "https://registry.npmjs.com/mrmime/-/mrmime-2.0.1.tgz", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
||||
@@ -1177,7 +1134,7 @@
|
||||
|
||||
"pathe": ["pathe@2.0.3", "https://registry.npmjs.com/pathe/-/pathe-2.0.3.tgz", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"pele": ["pele@1.6.0", "", {}, "sha512-VfAiVItsOGlGhvnBfphdT28VCG7mXMZxQNOwAGsCtxI2ztbUsT39MraEOYjsapLxVETkdUZscm0DdotYDQMLdw=="],
|
||||
"pele": ["pele@1.6.0", "https://registry.npmjs.com/pele/-/pele-1.6.0.tgz", {}, "sha512-VfAiVItsOGlGhvnBfphdT28VCG7mXMZxQNOwAGsCtxI2ztbUsT39MraEOYjsapLxVETkdUZscm0DdotYDQMLdw=="],
|
||||
|
||||
"perfect-debounce": ["perfect-debounce@2.1.0", "https://registry.npmjs.com/perfect-debounce/-/perfect-debounce-2.1.0.tgz", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="],
|
||||
|
||||
@@ -1203,8 +1160,6 @@
|
||||
|
||||
"prismjs": ["prismjs@1.30.0", "https://registry.npmjs.com/prismjs/-/prismjs-1.30.0.tgz", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="],
|
||||
|
||||
"proxy-from-env": ["proxy-from-env@2.1.0", "https://registry.npmjs.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
|
||||
|
||||
"punycode.js": ["punycode.js@2.3.1", "https://registry.npmjs.com/punycode.js/-/punycode.js-2.3.1.tgz", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="],
|
||||
|
||||
"quansync": ["quansync@0.2.11", "https://registry.npmjs.com/quansync/-/quansync-0.2.11.tgz", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="],
|
||||
|
||||
Reference in new issue
Block a user