大修改
This commit is contained in:
1 parent
a1cbc9404a
commit
e81481623c
47 files changed
+1453
-285
No files matched your search
@@ -1,11 +1,15 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import { api } from '@/lib/api';
|
||||
import { clearToken, isLoggedIn } from '@/lib/auth';
|
||||
import { ENV_LABEL, getViewEnv, setViewEnv, type DataSourceEnv } from '@/lib/env';
|
||||
import { RESOURCE_CONFIGS } from '@/lib/resources';
|
||||
|
||||
type DataSource = DataSourceEnv;
|
||||
|
||||
const FIXED_NAV = [
|
||||
{ href: '/', label: '数据看板' },
|
||||
{ href: '/users', label: '用户' },
|
||||
@@ -13,10 +17,41 @@ const FIXED_NAV = [
|
||||
{ href: '/settings', label: '系统配置' },
|
||||
];
|
||||
|
||||
/**
|
||||
* 底部「数据源」区域预留的高度(px)。
|
||||
*
|
||||
* 这个区块用 position:fixed 钉在视口左下角,脱离文档流,
|
||||
* 所以要在这里留出等高的空白,免得它盖住最后几个菜单项。
|
||||
* 数值按内容量给足余量,字体缩放时也不至于被遮住。
|
||||
*/
|
||||
const FOOTER_RESERVE_PX = 290;
|
||||
|
||||
export default function AdminLayout({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
|
||||
const [ready, setReady] = useState(false);
|
||||
/** 管理端「查看哪个库」——只影响自己 */
|
||||
const [viewEnv, setView] = useState<DataSource>('production');
|
||||
/** 线上小程序实际读的库 */
|
||||
const [miniEnv, setMiniEnv] = useState<DataSource>('production');
|
||||
const [developAvailable, setDevelopAvailable] = useState(false);
|
||||
const [confirmOpen, setConfirmOpen] = useState(false);
|
||||
const [switching, setSwitching] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const loadState = useCallback(() => {
|
||||
setView(getViewEnv());
|
||||
api
|
||||
.stats()
|
||||
.then((s) => {
|
||||
setMiniEnv(s.miniProgramEnv === 'develop' ? 'develop' : 'production');
|
||||
setDevelopAvailable(s.developAvailable);
|
||||
})
|
||||
.catch(() => {
|
||||
/* 取不到时按生产库显示,不阻塞页面 */
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoggedIn()) {
|
||||
@@ -24,44 +59,194 @@ export default function AdminLayout({ children }: { children: React.ReactNode })
|
||||
return;
|
||||
}
|
||||
setReady(true);
|
||||
}, [router]);
|
||||
loadState();
|
||||
}, [router, loadState]);
|
||||
|
||||
/** 只切自己的查看视角,不动线上数据来源。 */
|
||||
const changeViewEnv = (next: DataSource) => {
|
||||
if (next === viewEnv) return;
|
||||
setViewEnv(next);
|
||||
setView(next);
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
/** 真正切换线上小程序的数据源,必须二次确认。 */
|
||||
const applyMiniProgramEnv = () => {
|
||||
const next: DataSource = miniEnv === 'production' ? 'develop' : 'production';
|
||||
setSwitching(true);
|
||||
setError('');
|
||||
api
|
||||
.switchMiniProgramDataSource(next)
|
||||
.then(() => {
|
||||
setMiniEnv(next);
|
||||
setConfirmOpen(false);
|
||||
window.location.reload();
|
||||
})
|
||||
.catch((err: { message: string }) => {
|
||||
setError(err.message || '切换失败');
|
||||
setSwitching(false);
|
||||
});
|
||||
};
|
||||
|
||||
if (!ready) {
|
||||
return <div className="flex min-h-screen items-center justify-center text-sm text-gray-400">加载中…</div>;
|
||||
}
|
||||
|
||||
const nextMiniEnv: DataSource = miniEnv === 'production' ? 'develop' : 'production';
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen">
|
||||
<aside className="w-56 shrink-0 border-r border-gray-200 bg-white">
|
||||
<div className="border-b border-gray-200 px-4 py-4">
|
||||
<div className="text-sm font-semibold text-gray-900">叶雷讲数学</div>
|
||||
<div className="text-xs text-gray-400">管理后台</div>
|
||||
</div>
|
||||
<nav className="p-2">
|
||||
{FIXED_NAV.map((item) => (
|
||||
<NavItem key={item.href} href={item.href} label={item.label} active={pathname === item.href} />
|
||||
))}
|
||||
<div className="min-h-screen">
|
||||
{/*
|
||||
侧边栏:固定定位、高度恒等于视口。导航区自己滚动。
|
||||
注意它只承载「导航」,底部数据源区不在它里面——见下面那个独立 fixed 区块。
|
||||
*/}
|
||||
<aside className="fixed left-0 top-0 z-30 h-screen w-60 border-r border-gray-200 bg-white">
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="shrink-0 border-b border-gray-200 px-4 py-4">
|
||||
<div className="text-sm font-semibold text-gray-900">叶雷讲数学</div>
|
||||
<div className="text-xs text-gray-400">管理后台</div>
|
||||
</div>
|
||||
|
||||
<div className="px-3 pt-4 pb-1 text-xs text-gray-400">内容管理</div>
|
||||
{RESOURCE_CONFIGS.map((r) => (
|
||||
<NavItem key={r.key} href={`/${r.key}`} label={r.title} active={pathname === `/${r.key}`} />
|
||||
))}
|
||||
</nav>
|
||||
<nav className="min-h-0 flex-1 overflow-y-auto p-2">
|
||||
{FIXED_NAV.map((item) => (
|
||||
<NavItem key={item.href} href={item.href} label={item.label} active={pathname === item.href} />
|
||||
))}
|
||||
<div className="px-3 pt-4 pb-1 text-xs text-gray-400">内容管理</div>
|
||||
{RESOURCE_CONFIGS.map((r) => (
|
||||
<NavItem key={r.key} href={`/${r.key}`} label={r.title} active={pathname === `/${r.key}`} />
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<div className="border-t border-gray-200 p-2">
|
||||
<button
|
||||
onClick={() => {
|
||||
clearToken();
|
||||
router.replace('/login');
|
||||
}}
|
||||
className="w-full rounded-md px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100"
|
||||
>
|
||||
退出登录
|
||||
</button>
|
||||
{/* 给下面那个 fixed 区块让位,避免遮住最后几个菜单 */}
|
||||
<div className="shrink-0" style={{ height: FOOTER_RESERVE_PX }} aria-hidden="true" />
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main className="flex-1 p-6">{children}</main>
|
||||
{/*
|
||||
数据源区:独立的 fixed 元素,钉在视口左下角。
|
||||
它不在侧边栏里,也不参与任何 flex 布局,因此页面长短、导航多少、窗口高低都影响不到它。
|
||||
*/}
|
||||
<div className="fixed bottom-0 left-0 z-40 w-60 border-t border-gray-200 bg-white p-2">
|
||||
<div className="px-3 pb-1 text-xs text-gray-400">查看的数据源</div>
|
||||
<div className="flex gap-1 px-2">
|
||||
{(['production', 'develop'] as DataSource[]).map((key) => {
|
||||
const disabled = key === 'develop' && !developAvailable;
|
||||
return (
|
||||
<button
|
||||
key={key}
|
||||
onClick={() => changeViewEnv(key)}
|
||||
disabled={disabled}
|
||||
title={disabled ? '服务端未配置开发库' : '只影响你自己的查看与编辑'}
|
||||
className={`flex-1 rounded-md border px-2 py-1.5 text-xs transition ${
|
||||
viewEnv === key
|
||||
? key === 'develop'
|
||||
? 'border-orange-400 bg-orange-50 font-medium text-orange-700'
|
||||
: 'border-blue-400 bg-blue-50 font-medium text-blue-700'
|
||||
: 'border-gray-200 text-gray-500 hover:bg-gray-50'
|
||||
} ${disabled ? 'cursor-not-allowed opacity-40' : ''}`}
|
||||
>
|
||||
{ENV_LABEL[key]}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<p className="px-3 pt-1 pb-2 text-[11px] leading-tight text-gray-400">
|
||||
只影响你自己的查看与编辑,不影响小程序
|
||||
</p>
|
||||
|
||||
<div className="border-t border-gray-100 px-3 pt-3 pb-1 text-xs text-gray-400">
|
||||
线上小程序数据源
|
||||
</div>
|
||||
<div className="px-2 pb-2">
|
||||
<div className="mb-1.5 flex items-center gap-1.5 px-1 text-sm">
|
||||
<span
|
||||
className={`inline-block h-2 w-2 rounded-full ${
|
||||
miniEnv === 'develop' ? 'bg-orange-500' : 'bg-green-500'
|
||||
}`}
|
||||
/>
|
||||
<span className={miniEnv === 'develop' ? 'font-medium text-orange-700' : 'text-gray-700'}>
|
||||
{ENV_LABEL[miniEnv]}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setConfirmOpen(true)}
|
||||
disabled={!developAvailable || switching}
|
||||
title={developAvailable ? undefined : '服务端未配置开发库'}
|
||||
className="w-full rounded-md border border-gray-300 bg-white px-2 py-1.5 text-xs text-gray-700 transition hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-40"
|
||||
>
|
||||
切换到{ENV_LABEL[nextMiniEnv]}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
clearToken();
|
||||
router.replace('/login');
|
||||
}}
|
||||
className="w-full rounded-md px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100"
|
||||
>
|
||||
退出登录
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<main className="ml-60">
|
||||
{miniEnv === 'develop' && (
|
||||
<div className="border-b border-orange-300 bg-orange-100 px-6 py-2 text-sm font-medium text-orange-800">
|
||||
⚠ 线上小程序当前读的是<span className="font-bold">开发库</span>
|
||||
——所有用户打开小程序看到的都是开发库数据,测完请及时切回生产库。
|
||||
</div>
|
||||
)}
|
||||
{miniEnv !== 'develop' && viewEnv === 'develop' && (
|
||||
<div className="border-b border-blue-200 bg-blue-50 px-6 py-2 text-sm text-blue-800">
|
||||
你正在查看<span className="font-bold">开发库</span>的数据(仅影响你自己,小程序仍在读生产库)
|
||||
</div>
|
||||
)}
|
||||
<div className="p-6">{children}</div>
|
||||
</main>
|
||||
|
||||
{confirmOpen && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
|
||||
<div className="w-full max-w-md rounded-lg bg-white p-5 shadow-xl">
|
||||
<h3 className="mb-3 text-base font-semibold text-gray-900">确认切换线上小程序数据源?</h3>
|
||||
<div className="space-y-2 text-sm text-gray-600">
|
||||
<p>
|
||||
即将把线上小程序从
|
||||
<span className="mx-1 font-medium">{ENV_LABEL[miniEnv]}</span>
|
||||
切换到
|
||||
<span className="mx-1 font-medium text-orange-700">{ENV_LABEL[nextMiniEnv]}</span>。
|
||||
</p>
|
||||
{nextMiniEnv === 'develop' ? (
|
||||
<p className="rounded-md bg-orange-50 px-3 py-2 text-orange-800">
|
||||
切换后,<span className="font-medium">所有用户</span>在微信里打开小程序看到的都是开发库数据
|
||||
(旧开发库:132 个用户、3 门课程,首页两个栏目为空)。
|
||||
他们会以为课程丢失,请务必在测试结束后切回生产库。
|
||||
</p>
|
||||
) : (
|
||||
<p className="rounded-md bg-green-50 px-3 py-2 text-green-800">
|
||||
将恢复为生产库,用户看到的即真实数据。
|
||||
</p>
|
||||
)}
|
||||
{error && <p className="rounded-md bg-red-50 px-3 py-2 text-red-700">{error}</p>}
|
||||
</div>
|
||||
<div className="mt-5 flex justify-end gap-2">
|
||||
<button
|
||||
onClick={() => setConfirmOpen(false)}
|
||||
disabled={switching}
|
||||
className="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50"
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
onClick={applyMiniProgramEnv}
|
||||
disabled={switching}
|
||||
className="rounded-md bg-orange-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-orange-700 disabled:opacity-50"
|
||||
>
|
||||
{switching ? '切换中…' : '确认切换'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import { clearToken, getToken } from './auth';
|
||||
import { getViewEnv } from './env';
|
||||
|
||||
const BASE = (process.env.NEXT_PUBLIC_API_BASE_URL ?? 'http://127.0.0.1:3000').replace(/\/+$/, '');
|
||||
/**
|
||||
* 服务端地址。`NEXT_PUBLIC_*` 是**构建时写死**的,所以这个兜底值必须指向真实部署地址——
|
||||
* 之前兜底写了 127.0.0.1:3000,改成「本机构建、上传产物」之后,
|
||||
* 构建时读不到环境变量就落到这个兜底值,结果线上后台在拿访问者的电脑当服务器,全部请求失败。
|
||||
*
|
||||
* 需要指向别的环境时,构建前设置 NEXT_PUBLIC_API_BASE_URL 覆盖即可。
|
||||
*/
|
||||
const BASE = (process.env.NEXT_PUBLIC_API_BASE_URL || 'https://yelaymaths-api.yeomai.site').replace(/\/+$/, '');
|
||||
|
||||
export interface ApiFailure {
|
||||
code: number;
|
||||
@@ -20,6 +28,8 @@ async function request<T>(path: string, init: RequestInit = {}): Promise<T> {
|
||||
const token = getToken();
|
||||
const headers: Record<string, string> = {
|
||||
'content-type': 'application/json',
|
||||
// 管理端「查看哪个库」,只影响自己看到的和编辑的数据
|
||||
'x-yelay-env': getViewEnv(),
|
||||
...((init.headers as Record<string, string>) ?? {}),
|
||||
};
|
||||
if (token) headers.Authorization = `Bearer ${token}`;
|
||||
@@ -94,8 +104,21 @@ export const api = {
|
||||
payEnabled: boolean;
|
||||
/** 0 现网 / 1 沙箱 */
|
||||
payEnv: number;
|
||||
/** 当前数据源 */
|
||||
dataEnv: string;
|
||||
/** 服务端是否配置了开发库 */
|
||||
developAvailable: boolean;
|
||||
/** 线上小程序当前读的库 */
|
||||
miniProgramEnv: string;
|
||||
}>('/admin/v1/stats'),
|
||||
|
||||
/** 切换**线上小程序**的数据源。影响所有用户,前端必须二次确认。 */
|
||||
switchMiniProgramDataSource: (env: 'production' | 'develop') =>
|
||||
request<{ miniProgramEnv: string }>('/admin/v1/data-source', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ env }),
|
||||
}),
|
||||
|
||||
listUsers: (page: number, pageSize: number, keyword: string) =>
|
||||
request<Paged<Record<string, unknown>>>(`/admin/v1/users${qs({ page, pageSize, keyword })}`),
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
'use client';
|
||||
|
||||
export type DataSourceEnv = 'production' | 'develop';
|
||||
|
||||
const VIEW_ENV_KEY = 'yelay_admin_view_env';
|
||||
|
||||
/**
|
||||
* 管理端「查看哪个库」。
|
||||
*
|
||||
* 只存在浏览器本地,只影响你自己的查看与编辑视角,
|
||||
* 不会改变线上小程序的数据来源——那是另一个开关的事。
|
||||
*/
|
||||
export function getViewEnv(): DataSourceEnv {
|
||||
if (typeof window === 'undefined') return 'production';
|
||||
return window.localStorage.getItem(VIEW_ENV_KEY) === 'develop' ? 'develop' : 'production';
|
||||
}
|
||||
|
||||
export function setViewEnv(env: DataSourceEnv): void {
|
||||
window.localStorage.setItem(VIEW_ENV_KEY, env);
|
||||
}
|
||||
|
||||
export const ENV_LABEL: Record<DataSourceEnv, string> = {
|
||||
production: '生产库',
|
||||
develop: '开发库',
|
||||
};
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"fileNames":["./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.string.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.array.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.object.d.ts",".Line truncated
|
||||
{"fileNames":["./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.string.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.array.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","./node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.object.d.ts",".Line truncated
|
||||
Reference in new issue
Block a user