bump deps
This commit is contained in:
parent
c00c429ede
commit
e1ec5f275f
@ -56,12 +56,19 @@ module.exports = bundleAnalyzer({ enabled: !!process.env.ANALYZE })({
|
||||
additionalData: `$asset-url: "${baseAssetUrl}";`
|
||||
},
|
||||
experimental: {
|
||||
instrumentationHook: true
|
||||
instrumentationHook: true,
|
||||
serverComponentsExternalPackages: ['kysely', 'mysql2', 'bcrypt']
|
||||
},
|
||||
productionBrowserSourceMaps: true,
|
||||
webpack: config => {
|
||||
config.externals = [...config.externals, 'bcrypt', 'mysql2'];
|
||||
webpack: (config, { nextRuntime }) => {
|
||||
config.resolve.alias['resize-observer-polyfill'] = path.resolve(__dirname, 'resize-observer.cjs');
|
||||
if (nextRuntime === 'edge') {
|
||||
config.resolve.alias['mysql2'] = path.resolve(__dirname, 'empty.cjs');
|
||||
config.resolve.alias['kysely'] = path.resolve(__dirname, 'empty.cjs');
|
||||
config.resolve.alias['bcrypt'] = path.resolve(__dirname, 'empty.cjs');
|
||||
config.resolve.alias['crypto'] = path.resolve(__dirname, 'empty.cjs');
|
||||
config.resolve.alias['node:crypto'] = path.resolve(__dirname, 'empty.cjs');
|
||||
}
|
||||
return config;
|
||||
}
|
||||
});
|
||||
|
1483
package-lock.json
generated
1483
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
27
package.json
27
package.json
@ -17,21 +17,21 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@heroicons/react": "^2.1.3",
|
||||
"@next/bundle-analyzer": "^14.1.4",
|
||||
"@next/bundle-analyzer": "^14.2.0",
|
||||
"@nextui-org/react": "^2.2.10",
|
||||
"@tanstack/react-virtual": "^3.2.0",
|
||||
"@tanstack/react-virtual": "^3.2.1",
|
||||
"bcrypt": "^5.1.1",
|
||||
"clsx": "^2.1.0",
|
||||
"db-migrate": "^0.11.14",
|
||||
"db-migrate-mysql": "^2.3.2",
|
||||
"deep-is": "^0.1.4",
|
||||
"framer-motion": "^10.18.0",
|
||||
"framer-motion": "^11.0.28",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"kysely": "^0.27.3",
|
||||
"mysql2": "^3.9.2",
|
||||
"next": "14.1.4",
|
||||
"mysql2": "^3.9.4",
|
||||
"next": "14.2.0",
|
||||
"next-auth": "^5.0.0-beta.15",
|
||||
"next-client-cookies": "^1.1.0",
|
||||
"next-client-cookies": "^1.1.1",
|
||||
"next-themes": "^0.3.0",
|
||||
"react": "^18",
|
||||
"react-day-picker": "^8.10.0",
|
||||
@ -40,13 +40,13 @@
|
||||
"react-icons": "^5.0.1",
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-swipeable": "^7.0.1",
|
||||
"sass": "^1.72.0",
|
||||
"sass": "^1.75.0",
|
||||
"tailwind-merge": "^2.2.2",
|
||||
"tailwindcss-text-fill-stroke": "^2.0.0-beta.1",
|
||||
"usehooks-ts": "^3.0.2"
|
||||
"usehooks-ts": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dotenvx/dotenvx": "^0.26.0",
|
||||
"@dotenvx/dotenvx": "^0.32.0",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/jsonwebtoken": "^9.0.6",
|
||||
"@types/node": "^20",
|
||||
@ -54,15 +54,14 @@
|
||||
"@types/react-dom": "^18",
|
||||
"@types/react-grid-layout": "^1.3.5",
|
||||
"@types/react-resizable": "^3.0.7",
|
||||
"@types/react-virtualized": "^9.21.29",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.1.4",
|
||||
"kysely-codegen": "^0.14.1",
|
||||
"eslint-config-next": "14.2.0",
|
||||
"kysely-codegen": "^0.14.2",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"type-fest": "^4.14.0",
|
||||
"type-fest": "^4.15.0",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
@ -44,13 +44,15 @@ type LoginOptions = {
|
||||
|
||||
export const login = async (options?: LoginOptions) => {
|
||||
if (!options)
|
||||
return signIn();
|
||||
return { redirect: await signIn(undefined, { redirect: false }) as string };
|
||||
|
||||
try {
|
||||
return await signIn('credentials', {
|
||||
const res = await signIn('credentials', {
|
||||
...options,
|
||||
redirectTo: options?.redirectTo ?? '/'
|
||||
redirectTo: options.redirectTo ?? '/',
|
||||
redirect: false,
|
||||
});
|
||||
return { redirect: res };
|
||||
} catch (e) {
|
||||
if (e instanceof AuthError) {
|
||||
if (e.type === 'CredentialsSignin')
|
||||
@ -63,8 +65,11 @@ export const login = async (options?: LoginOptions) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const logout = async (options: { redirectTo?: string, redirect?: boolean }) => {
|
||||
return signOut(options);
|
||||
export const logout = async (options: { redirectTo?: string }) => {
|
||||
return await signOut({
|
||||
...options,
|
||||
redirect: false
|
||||
});
|
||||
};
|
||||
|
||||
export const register = async (formData: FormData) => {
|
||||
|
@ -124,7 +124,7 @@ export async function getPlaylog(opts: GetPlaylogOptions) {
|
||||
.select(({ fn }) => fn.countAll().as('total'))
|
||||
.executeTakeFirstOrThrow()).total);
|
||||
|
||||
return { data: playlog, total };
|
||||
return { data: structuredClone(playlog), total };
|
||||
}
|
||||
|
||||
export type ChuniPlaylog = Awaited<ReturnType<typeof getPlaylog>>;
|
||||
|
@ -3,17 +3,15 @@
|
||||
import { GeneratedDB, db } from '@/db';
|
||||
import { getUser, requireUser } from './auth';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { CompiledQuery, Transaction, sql } from 'kysely';
|
||||
import { Transaction, sql } from 'kysely';
|
||||
import { syncUserFriends, withChuniRivalCount } from '@/data/friend';
|
||||
import { SqlBool } from 'kysely';
|
||||
import { Exact } from 'type-fest';
|
||||
import { revalidatePath } from 'next/cache';
|
||||
|
||||
export const getFriendRequests = async () => {
|
||||
const user = await getUser();
|
||||
if (!user) return [];
|
||||
|
||||
return db.selectFrom('actaeon_friend_requests as req')
|
||||
return structuredClone(await db.selectFrom('actaeon_friend_requests as req')
|
||||
.where('user', '=', user.id)
|
||||
.innerJoin('aime_user as u', 'u.id', 'req.friend')
|
||||
.innerJoin('actaeon_user_ext as ext', 'ext.userId', 'u.id')
|
||||
@ -23,7 +21,7 @@ export const getFriendRequests = async () => {
|
||||
'ext.uuid as userUuid'
|
||||
])
|
||||
.orderBy('req.createdDate desc')
|
||||
.execute();
|
||||
.execute());
|
||||
};
|
||||
|
||||
export type FriendRequest = Awaited<ReturnType<typeof getFriendRequests>>[number];
|
||||
|
@ -157,5 +157,5 @@ export const createMachine = async ({ arcade, update }: { arcade: number, update
|
||||
revalidatePath('/arcade', 'page');
|
||||
revalidatePath('/arcade/[arcadeId]', 'page');
|
||||
|
||||
return { error: false, message: '', data: await getArcadeCabs({ arcade, user, permissions: arcadePermissions }) };
|
||||
return { error: false, message: '', data: structuredClone(await getArcadeCabs({ arcade, user, permissions: arcadePermissions })) };
|
||||
}
|
||||
|
@ -40,7 +40,8 @@ export const LoginCard = ({ initialError, referer, callback }: LoginCardProps) =
|
||||
})
|
||||
.then(res => {
|
||||
if (res?.error)
|
||||
setError(res.message)
|
||||
return setError(res.message)
|
||||
setTimeout(() => location.href = res.redirect, 10);
|
||||
})
|
||||
.finally(() => setLoading(false));
|
||||
};
|
||||
|
@ -18,8 +18,8 @@ export default async function ArcadeDetailPage({ params }: { params: { arcadeId:
|
||||
|
||||
const [users, cabs, links] = await Promise.all([
|
||||
getArcadeUsers({ arcade: arcade.id, permissions: arcade.permissions, user }),
|
||||
getArcadeCabs({ arcade: arcade.id, permissions: arcade.permissions, user }),
|
||||
getArcadeInviteLinks({ arcade: arcade.id, permissions: arcade.permissions, user })
|
||||
getArcadeCabs({ arcade: arcade.id, permissions: arcade.permissions, user }).then(d => structuredClone(d)),
|
||||
getArcadeInviteLinks({ arcade: arcade.id, permissions: arcade.permissions, user }).then(d => structuredClone(d))
|
||||
]);
|
||||
|
||||
return (<ArcadeDetail users={users} arcade={arcade} cabs={cabs} links={links} />)
|
||||
|
@ -17,9 +17,9 @@ export default async function ChuniDashboard() {
|
||||
return (<ChuniNoProfile />);
|
||||
|
||||
const [profile, rating, playlog] = await Promise.all([
|
||||
getUserData(user),
|
||||
getUserRating(user),
|
||||
getPlaylog({ limit: 72 })
|
||||
getUserData(user).then(d => structuredClone(d)),
|
||||
getUserRating(user).then(d => structuredClone(d)),
|
||||
getPlaylog({ limit: 72 }).then(d => structuredClone(d))
|
||||
]);
|
||||
|
||||
return (<div className="flex h-full flex-col md:flex-row">
|
||||
|
@ -10,7 +10,7 @@ export default async function ChuniMusicDetailPage({ params }: { params: { music
|
||||
return notFound();
|
||||
|
||||
const [music, playlog] = await Promise.all([
|
||||
getMusic(musicId),
|
||||
getMusic(musicId).then(d => structuredClone(d)),
|
||||
getPlaylog({ musicId, limit: 500 })
|
||||
]);
|
||||
|
||||
|
@ -6,6 +6,6 @@ export default async function ChuniMusicPage() {
|
||||
const music = await getMusic();
|
||||
|
||||
return (
|
||||
<ChuniMusicList music={music} />
|
||||
<ChuniMusicList music={structuredClone(music)} />
|
||||
);
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ export default async function ChuniUserboxPage() {
|
||||
if (!user?.chuni)
|
||||
return (<ChuniNoProfile />);
|
||||
|
||||
const profile = await getUserData(user);
|
||||
const userboxItems = await getUserboxItems(user, profile);
|
||||
const profile = structuredClone(await getUserData(user));
|
||||
const userboxItems = structuredClone(await getUserboxItems(user, profile));
|
||||
|
||||
return (<ChuniUserbox profile={profile} userboxItems={userboxItems} />);
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ export const dynamic = 'force-dynamic';
|
||||
export default async function DashboardPage() {
|
||||
const [user, status] = await Promise.all([
|
||||
getUser(),
|
||||
getServerStatus()
|
||||
getServerStatus().then(d => structuredClone(d))
|
||||
]);
|
||||
|
||||
if (!user) return (<Dashboard serverStatus={status} />)
|
||||
|
||||
const [chuniProfile, dashboard] = await Promise.all([
|
||||
getUserData(user),
|
||||
getUserData(user).then(d => structuredClone(d)),
|
||||
getDashboard(user)
|
||||
]);
|
||||
|
||||
|
@ -6,7 +6,7 @@ export const dynamic = 'force-dynamic';
|
||||
|
||||
export default async function FriendsPage() {
|
||||
const user = await requireUser();
|
||||
const friends = await getFriends(user.id);
|
||||
const friends = structuredClone(await getFriends(user.id));
|
||||
|
||||
return (<Friends friends={friends} />);
|
||||
};
|
@ -305,7 +305,8 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
||||
</div>
|
||||
</DropdownItem>
|
||||
<DropdownItem className="p-0" color="danger" variant="flat">
|
||||
<div className="w-full h-full block px-2 py-1.5 text-danger" onClick={() => logout({ redirectTo: '/' })}>
|
||||
<div className="w-full h-full block px-2 py-1.5 text-danger" onClick={() => logout({ redirectTo: '/' })
|
||||
.then(r => setTimeout(() => location.href = r.redirect, 10))}>
|
||||
Logout
|
||||
</div>
|
||||
</DropdownItem>
|
||||
@ -314,7 +315,8 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
||||
</> :
|
||||
<>
|
||||
<ThemeSwitcherDropdown />
|
||||
<Button size="sm" className="ml-2" color="primary" onClick={() => login()}>
|
||||
<Button size="sm" className="ml-2" color="primary" onClick={() => login()
|
||||
.then(r => setTimeout(() => location.href = r.redirect, 10))}>
|
||||
Login
|
||||
</Button>
|
||||
</>
|
||||
@ -397,7 +399,8 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
||||
</Button>
|
||||
</Link>}
|
||||
</div>
|
||||
<Button color="primary" className="w-full flex-shrink-0" onClick={() => user ? logout({ redirectTo: '/' }) : login()}>
|
||||
<Button color="primary" className="w-full flex-shrink-0" onClick={() => (user ? logout({ redirectTo: '/' }) : login())
|
||||
.then(r => setTimeout(() => location.href = r.redirect!, 10))}>
|
||||
{user ? 'Logout' : 'Login'}
|
||||
</Button>
|
||||
</div>
|
||||
@ -457,7 +460,8 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Button className="mt-auto mx-3 flex-shrink-0" color="danger" onPress={() => logout({ redirectTo: '/' })}>
|
||||
<Button className="mt-auto mx-3 flex-shrink-0" color="danger" onPress={() => logout({ redirectTo: '/' })
|
||||
.then(r => setTimeout(() => location.href = r.redirect, 10))}>
|
||||
Logout
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@ import { getGlobalConfig } from '@/config';
|
||||
|
||||
export default async function SettingsPage() {
|
||||
const user = await requireUser();
|
||||
const cards = await getCards(user.id);
|
||||
const cards = structuredClone(await getCards(user.id));
|
||||
|
||||
return (<div className="w-full flex items-center justify-center">
|
||||
<div className="w-full max-w-full sm:max-w-5xl flex flex-col gap-2 2xl:max-w-screen-4xl 2xl:grid grid-cols-12">
|
||||
|
@ -15,7 +15,7 @@ export default async function TeamDetailPage({ params }: { params: { teamId: str
|
||||
|
||||
const [users, links] = await Promise.all([
|
||||
getTeamUsers({ user, team }),
|
||||
getTeamInviteLinks({ user, team })
|
||||
getTeamInviteLinks({ user, team }).then(d => structuredClone(d))
|
||||
]);
|
||||
|
||||
if (!team.visible)
|
||||
|
@ -9,7 +9,7 @@ export const dynamic = 'force-dynamic';
|
||||
|
||||
export default async function UserProfilePage({ params }: { params: { userId: string; }; }) {
|
||||
const viewingUser = await getUser();
|
||||
const user = await withUsersVisibleTo(viewingUser)
|
||||
const user = structuredClone(await withUsersVisibleTo(viewingUser)
|
||||
.selectFrom('aime_user as u')
|
||||
.innerJoin('actaeon_user_ext as ext', 'ext.userId', 'u.id')
|
||||
.where('ext.uuid', '=', params.userId)
|
||||
@ -22,7 +22,7 @@ export default async function UserProfilePage({ params }: { params: { userId: st
|
||||
'last_login_date',
|
||||
userIsVisible('u.id').as('visible')
|
||||
])
|
||||
.executeTakeFirst();
|
||||
.executeTakeFirst());
|
||||
|
||||
if (!user)
|
||||
return notFound();
|
||||
@ -32,18 +32,18 @@ export default async function UserProfilePage({ params }: { params: { userId: st
|
||||
.where('user1', '=', user.id)
|
||||
.where('user2', '=', viewingUser?.id!)
|
||||
.select('chuniRival')
|
||||
.executeTakeFirst(),
|
||||
.executeTakeFirst().then(d => structuredClone(d)),
|
||||
db.selectFrom('actaeon_friend_requests')
|
||||
.where('user', '=', user.id)
|
||||
.where('friend', '=', viewingUser?.id!)
|
||||
.select('user')
|
||||
.executeTakeFirst()
|
||||
.executeTakeFirst().then(d => structuredClone(d))
|
||||
]);
|
||||
|
||||
|
||||
if (!user.visible)
|
||||
return (<UserProfile friend={friend} pendingFriend={!!pendingFriend} user={user as UserProfile<false>}/>);
|
||||
|
||||
const chuniProfile = await getChuniUserData(user);
|
||||
|
||||
const chuniProfile = structuredClone(await getChuniUserData(user));
|
||||
|
||||
return (<UserProfile friend={friend} pendingFriend={!!pendingFriend} user={user as UserProfile<true>} chuniProfile={chuniProfile} />);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import CredentialsProvider from 'next-auth/providers/credentials';
|
||||
import { db, GeneratedDB } from '@/db';
|
||||
import { DBUserPayload } from '@/types/user';
|
||||
import { cache } from 'react';
|
||||
import { SelectQueryBuilder, sql } from 'kysely';
|
||||
import { SelectQueryBuilder } from 'kysely';
|
||||
import { AimeUser } from '@/types/db';
|
||||
import crypto from 'crypto';
|
||||
import { createActaeonTeamsFromExistingTeams } from './data/team';
|
||||
@ -40,7 +40,7 @@ else if (['1', 'true', 'yes'].includes(process.env.COOKIE_SECURE?.toLowerCase()!
|
||||
|
||||
const nextAuth = NextAuth({
|
||||
pages: {
|
||||
signIn: `${basePath}/auth/login`
|
||||
signIn: `${basePath}/auth/login/`
|
||||
},
|
||||
...config,
|
||||
basePath: `${basePath}/api/auth/`,
|
||||
|
@ -11,7 +11,8 @@ export const PrivateVisibilityError = () => {
|
||||
<LockClosedIcon className="w-48 mb-10" />
|
||||
<header className="text-2xl font-semibold">This page is private.</header>
|
||||
{!user ? <span>You may be able to access it by
|
||||
<span className="underline hover:text-secondary transition cursor-pointer" onClick={() => login()}>logging in.</span>
|
||||
<span className="underline hover:text-secondary transition cursor-pointer" onClick={() => login()
|
||||
.then(r => setTimeout(() => location.href = r.redirect!, 10))}>logging in.</span>
|
||||
</span> : <span>You do not have permission to view this page.</span>}
|
||||
</main>);
|
||||
}
|
||||
|
@ -81,8 +81,5 @@ export async function register() {
|
||||
createActaeonTeamsFromExistingTeams().catch(console.error),
|
||||
createActaeonFriendsFromExistingFriends().catch(console.error)
|
||||
]);
|
||||
} else if (process.env.NEXT_RUNTIME === 'edge') {
|
||||
(globalThis as any).bcrypt = {};
|
||||
(globalThis as any).mysql2 = {};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user