diff --git a/src/actions/arcade.ts b/src/actions/arcade.ts index 5f4d0f3..1f97043 100644 --- a/src/actions/arcade.ts +++ b/src/actions/arcade.ts @@ -14,6 +14,7 @@ import { randomString } from '@/helpers/random'; import crypto from 'crypto'; import type { Entries } from 'type-fest'; +import { revalidatePath } from 'next/cache'; export type ArcadeUpdate = Partial>; @@ -89,20 +90,23 @@ export const updateArcade = async (id: number, update: ArcadeUpdate) => { .where('arcadeId', '=', id) .executeTakeFirst(); }); + + revalidatePath('/arcade', 'page'); + revalidatePath('/arcade/[arcadeId]', 'page'); }; export const joinPublicArcade = async (arcade: number) => { const user = await requireUser(); - const arcadePrivacy = await db.selectFrom('arcade') + const arcadeData = await db.selectFrom('arcade') .innerJoin('actaeon_arcade_ext as ext', 'ext.arcadeId', 'arcade.id') .where('arcade.id', '=', arcade) - .select('ext.joinPrivacy') + .select(['ext.joinPrivacy', 'ext.uuid']) .executeTakeFirst(); - if (!arcadePrivacy) + if (!arcadeData) return notFound(); - if (arcadePrivacy.joinPrivacy !== JoinPrivacy.PUBLIC) + if (arcadeData.joinPrivacy !== JoinPrivacy.PUBLIC) requirePermission(user.permissions, UserPermissions.ACMOD); await db.insertInto('arcade_owner') @@ -112,6 +116,9 @@ export const joinPublicArcade = async (arcade: number) => { permissions: 1 }) .executeTakeFirst(); + + revalidatePath('/arcade', 'page'); + revalidatePath(`/arcade/${arcadeData.uuid}`, 'page'); } export const removeUserFromArcade = async (arcade: number, userId?: number) => { @@ -127,6 +134,9 @@ export const removeUserFromArcade = async (arcade: number, userId?: number) => { .where('arcade', '=', arcade) .where('user', '=', userId) .executeTakeFirst(); + + revalidatePath('/arcade', 'page'); + revalidatePath('/arcade/[arcadeId]', 'page'); } export const createArcadeLink = async (arcade: number, remainingUses: number | null) => { @@ -142,6 +152,7 @@ export const createArcadeLink = async (arcade: number, remainingUses: number | n totalUses: 0 }) .executeTakeFirst(); + revalidatePath('/arcade/[arcadeId]', 'page'); return id; }; @@ -153,6 +164,7 @@ export const deleteArcadeLink = async (arcade: number, link: string) => { .where('arcadeId', '=', arcade) .where('id', '=', link) .executeTakeFirst(); + revalidatePath('/arcade/[arcadeId]', 'page'); }; export const createArcade = async (name: string) => { @@ -182,6 +194,7 @@ export const createArcade = async (name: string) => { .executeTakeFirst(); }); + revalidatePath('/arcade', 'page'); redirect('/arcade/' + uuid); }; @@ -194,6 +207,7 @@ export const deleteArcade = async (id: number) => { .where('id', '=', id) .executeTakeFirst(); + revalidatePath('/arcade', 'page'); redirect('/arcade'); } @@ -208,4 +222,6 @@ export const setUserArcadePermissions = async ({ arcadeUser, arcade, permissions .where('user', '=', arcadeUser) .where('arcade', '=', arcade) .executeTakeFirst(); + revalidatePath('/arcade', 'page'); + revalidatePath('/arcade/[arcadeId]', 'page'); }; diff --git a/src/actions/card.ts b/src/actions/card.ts index cb3d9f1..321ea50 100644 --- a/src/actions/card.ts +++ b/src/actions/card.ts @@ -7,6 +7,7 @@ import { requirePermission } from '@/helpers/permissions'; import { addCardToUser } from '@/data/card'; import { AdminUser, getUsers } from '@/data/user'; import { ActionResult } from '@/types/action-result'; +import { revalidatePath } from 'next/cache'; export const getCards = async () => { const user = await requireUser(); @@ -27,6 +28,9 @@ export const banUnbanCard = async (opts: { cardId: number, userId: number, isBan eb('user', '=', opts.userId) ])) .executeTakeFirst(); + + revalidatePath('/settings', 'page'); + revalidatePath('/admin/users', 'page'); }; export const lockUnlockCard = async (opts: { cardId: number, userId: number, isLock: boolean }) => { @@ -41,6 +45,9 @@ export const lockUnlockCard = async (opts: { cardId: number, userId: number, isL eb('user', '=', opts.userId) ])) .executeTakeFirst(); + + revalidatePath('/settings', 'page'); + revalidatePath('/admin/users', 'page'); }; export const adminAddCardToUser = async (user: number, code: string): Promise> => { @@ -51,5 +58,8 @@ export const adminAddCardToUser = async (user: number, code: string): Promise { const user = await getUser(); @@ -83,6 +84,9 @@ export const addFavoriteMusic = async (musicId: number) => { favKind: 1 }) .executeTakeFirst(); + + revalidatePath('/chuni/music', 'page'); + revalidatePath(`/chuni/music/${musicId}`, 'page'); }; export const removeFavoriteMusic = async (musicId: number) => { @@ -98,4 +102,7 @@ export const removeFavoriteMusic = async (musicId: number) => { eb('favKind', '=', 1) ])) .executeTakeFirst(); + + revalidatePath('/chuni/music', 'page'); + revalidatePath(`/chuni/music/${musicId}`, 'page'); } diff --git a/src/actions/chuni/profile.ts b/src/actions/chuni/profile.ts index d925a3a..93202ed 100644 --- a/src/actions/chuni/profile.ts +++ b/src/actions/chuni/profile.ts @@ -13,6 +13,7 @@ import { getUser, requireUser } from '@/actions/auth'; import { Entries } from 'type-fest'; import { CHUNI_NAMEPLATE_PROFILE_KEYS } from '@/components/chuni/nameplate'; import { getGlobalConfig } from '@/config'; +import { revalidatePath } from 'next/cache'; type RecentRating = { scoreMax: string, @@ -222,6 +223,11 @@ export const updateProfile = async (data: ProfileUpdate) => { ])) .set(update) .execute(); + + revalidatePath('/chuni/dashboard', 'page'); + revalidatePath('/chuni/userbox', 'page'); + revalidatePath('/', 'page'); + revalidatePath(`/user/${user.uuid}`, 'page') return { error: false }; }; diff --git a/src/actions/friend.ts b/src/actions/friend.ts index d2611fb..f5c22c9 100644 --- a/src/actions/friend.ts +++ b/src/actions/friend.ts @@ -7,6 +7,7 @@ import { CompiledQuery, 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(); @@ -48,6 +49,9 @@ export const sendFriendRequest = async (toUser: number) => { uuid: sql`uuid_v4()` }) .executeTakeFirst(); + + revalidatePath('/user/[userId]', 'page'); + revalidatePath('/friends', 'page'); } export const unfriend = async (friend: number) => { @@ -71,6 +75,9 @@ export const unfriend = async (friend: number) => { await syncUserFriends(user.id, trx); await syncUserFriends(friend, trx); }); + + revalidatePath('/user/[userId]', 'page'); + revalidatePath('/friends', 'page'); }; export const acceptFriendRequest = async (id: string) => { @@ -110,6 +117,9 @@ export const acceptFriendRequest = async (id: string) => { await syncUserFriends(user.id, trx); await syncUserFriends(request.friend, trx); }); + + revalidatePath('/user/[userId]', 'page'); + revalidatePath('/friends', 'page'); }; export const rejectFriendRequest = async (id: string) => { @@ -163,6 +173,9 @@ export const addFriendAsRival = async (friend: number) => { await syncUserFriends(user.id, trx); await syncUserFriends(friend, trx); }); + + revalidatePath('/user/[userId]', 'page'); + revalidatePath('/friends', 'page'); }; export const removeFriendAsRival = async (friend: number) => { @@ -174,4 +187,7 @@ export const removeFriendAsRival = async (friend: number) => { await syncUserFriends(user.id, trx); await syncUserFriends(friend, trx); }); + + revalidatePath('/user/[userId]', 'page'); + revalidatePath('/friends', 'page'); }; diff --git a/src/actions/machine.ts b/src/actions/machine.ts index 2f76dfd..7b6c599 100644 --- a/src/actions/machine.ts +++ b/src/actions/machine.ts @@ -7,6 +7,7 @@ import { requireUser } from '@/actions/auth'; import { requireArcadePermission } from '@/helpers/permissions'; import { ArcadePermissions } from '@/types/permissions'; import type { Entries } from 'type-fest'; +import { revalidatePath } from 'next/cache'; export type CabUpdate = Omit; @@ -91,6 +92,9 @@ export const deleteMachine = async (arcade: number, machine: number) => { .where('arcade', '=', arcade) .where('id', '=', machine) .executeTakeFirst(); + + revalidatePath('/arcade', 'page'); + revalidatePath('/arcade/[arcadeId]', 'page'); }; const validateUpdate = async (update: CabUpdate, cab: number | null) => { @@ -129,6 +133,9 @@ export const updateMachine = async ({ arcade, machine, update }: { arcade: numbe .where('machine.arcade', '=', arcade) .set(update) .executeTakeFirst(); + + revalidatePath('/arcade', 'page'); + revalidatePath('/arcade/[arcadeId]', 'page'); }; export const createMachine = async ({ arcade, update }: { arcade: number, update: CabUpdate }) => { @@ -146,6 +153,9 @@ export const createMachine = async ({ arcade, update }: { arcade: number, update arcade }) .executeTakeFirst(); + + revalidatePath('/arcade', 'page'); + revalidatePath('/arcade/[arcadeId]', 'page'); return { error: false, message: '', data: await getArcadeCabs({ arcade, user, permissions: arcadePermissions }) }; } diff --git a/src/actions/team.ts b/src/actions/team.ts index e075224..09e242c 100644 --- a/src/actions/team.ts +++ b/src/actions/team.ts @@ -12,6 +12,7 @@ import { hasPermission, requirePermission } from '@/helpers/permissions'; import { makeValidator } from '@/types/validator-map'; import { DB } from '@/types/db'; import { randomString } from '@/helpers/random'; +import { revalidatePath } from 'next/cache'; const validator = makeValidator() .nonNullableKeys('name', 'joinPrivacy', 'visibility') @@ -84,6 +85,8 @@ export const createTeam = async (name: string): Promise => { await syncUserTeams(user.id, { chuniTeam }, trx); }); + revalidatePath('/team', 'page'); + redirect(`/team/${uuid}`); }; @@ -134,6 +137,9 @@ export const modifyTeam = async (team: string, update: TeamUpdate): Promise { await syncUserTeams(user.id, teamData, trx); }); + + revalidatePath('/team', 'page'); + revalidatePath(`/team/${team}`, 'page'); }; export const removeUserFromTeam = async (team: string, userId?: number) => { @@ -189,6 +198,9 @@ export const removeUserFromTeam = async (team: string, userId?: number) => { await syncUserTeams(userId, null, trx); }); + + revalidatePath('/team', 'page'); + revalidatePath(`/team/${team}`, 'page'); }; export const deleteTeam = async (team: string) => { @@ -203,6 +215,9 @@ export const deleteTeam = async (team: string) => { .where('uuid', '=', teamData.uuid) .executeTakeFirst(); }); + + revalidatePath('/team', 'page'); + revalidatePath(`/team/${team}`, 'page'); }; export const deleteTeamLink = async (team: string, link: string) => { @@ -211,6 +226,8 @@ export const deleteTeamLink = async (team: string, link: string) => { .where('teamId', '=', teamData.uuid) .where('id', '=', link) .executeTakeFirst(); + + revalidatePath(`/team/${team}`, 'page'); }; export const createTeamLink = async (team: string, remainingUses: number | null) => { @@ -226,5 +243,7 @@ export const createTeamLink = async (team: string, remainingUses: number | null) }) .executeTakeFirst(); + revalidatePath(`/team/${team}`, 'page'); + return id; }; diff --git a/src/app/(with-header)/admin/system-config/page.tsx b/src/app/(with-header)/admin/system-config/page.tsx index 83af563..021faac 100644 --- a/src/app/(with-header)/admin/system-config/page.tsx +++ b/src/app/(with-header)/admin/system-config/page.tsx @@ -3,6 +3,8 @@ import { getGlobalConfig } from '@/config'; import { UserPermissions } from '@/types/permissions'; import { SystemConfig } from './system-config'; +export const dynamic = 'force-dynamic'; + export default async function SystemConfigPage() { await requireUser({ permission: UserPermissions.SYSADMIN }); diff --git a/src/app/(with-header)/admin/users/page.tsx b/src/app/(with-header)/admin/users/page.tsx index 15d6d3d..9a130a8 100644 --- a/src/app/(with-header)/admin/users/page.tsx +++ b/src/app/(with-header)/admin/users/page.tsx @@ -3,6 +3,8 @@ import { UserPermissions } from '@/types/permissions'; import { AdminUserList } from './admin-user-list'; import { getUsers } from '@/data/user'; +export const dynamic = 'force-dynamic'; + export default async function AdminUsersPage() { await requireUser({ permission: UserPermissions.USERMOD }); const users = await getUsers(); diff --git a/src/app/(with-header)/arcade/[arcadeId]/page.tsx b/src/app/(with-header)/arcade/[arcadeId]/page.tsx index ca8ff99..80c12d3 100644 --- a/src/app/(with-header)/arcade/[arcadeId]/page.tsx +++ b/src/app/(with-header)/arcade/[arcadeId]/page.tsx @@ -4,6 +4,8 @@ import { notFound } from 'next/navigation'; import { ArcadeDetail } from './arcade'; import { PrivateVisibilityError } from '@/components/private-visibility-error'; +export const dynamic = 'force-dynamic'; + export default async function ArcadeDetailPage({ params }: { params: { arcadeId: string }}) { const user = await getUser(); const arcade = (await getArcades({ user, uuids: [params.arcadeId], includeUnlisted: true }))[0]; diff --git a/src/app/(with-header)/arcade/page.tsx b/src/app/(with-header)/arcade/page.tsx index b74b45e..edb06f9 100644 --- a/src/app/(with-header)/arcade/page.tsx +++ b/src/app/(with-header)/arcade/page.tsx @@ -13,6 +13,8 @@ const getLocation = (arcade: Arcade) => { return out; }; +export const dynamic = 'force-dynamic'; + export default async function ArcadePage() { const user = await getUser(); const arcades = (await getArcades({ user })).filter(a => a.visible); diff --git a/src/app/(with-header)/chuni/dashboard/page.tsx b/src/app/(with-header)/chuni/dashboard/page.tsx index 6db718c..84fa276 100644 --- a/src/app/(with-header)/chuni/dashboard/page.tsx +++ b/src/app/(with-header)/chuni/dashboard/page.tsx @@ -8,6 +8,8 @@ import { ChuniTopRatingSidebar } from './top-rating-sidebar'; import { Button } from '@nextui-org/react'; import Link from 'next/link'; +export const dynamic = 'force-dynamic'; + export default async function ChuniDashboard() { const user = await requireUser(); const [profile, rating, playlog] = await Promise.all([ diff --git a/src/app/(with-header)/chuni/userbox/page.tsx b/src/app/(with-header)/chuni/userbox/page.tsx index 59e9c10..81719c6 100644 --- a/src/app/(with-header)/chuni/userbox/page.tsx +++ b/src/app/(with-header)/chuni/userbox/page.tsx @@ -10,6 +10,8 @@ export const viewport: Viewport = { interactiveWidget: 'resizes-content' }; +export const dynamic = 'force-dynamic'; + export default async function ChuniUserboxPage() { const user = await requireUser(); const profile = await getUserData(user); diff --git a/src/app/(with-header)/friends/page.tsx b/src/app/(with-header)/friends/page.tsx index 6d40115..136533c 100644 --- a/src/app/(with-header)/friends/page.tsx +++ b/src/app/(with-header)/friends/page.tsx @@ -2,6 +2,8 @@ import { requireUser } from '@/actions/auth'; import { getFriends } from '@/data/friend'; import { Friends } from './friends'; +export const dynamic = 'force-dynamic'; + export default async function FriendsPage() { const user = await requireUser(); const friends = await getFriends(user.id); diff --git a/src/app/(with-header)/team/[teamId]/page.tsx b/src/app/(with-header)/team/[teamId]/page.tsx index b439ac1..7b601a0 100644 --- a/src/app/(with-header)/team/[teamId]/page.tsx +++ b/src/app/(with-header)/team/[teamId]/page.tsx @@ -4,6 +4,8 @@ import { notFound } from 'next/navigation'; import { PrivateVisibilityError } from '@/components/private-visibility-error'; import { TeamDetail } from './team'; +export const dynamic = 'force-dynamic'; + export default async function TeamDetailPage({ params }: { params: { teamId: string }}) { const user = await getUser(); const team = (await getTeams({ user, uuids: [params.teamId], showUnlisted: true }))[0]; diff --git a/src/app/(with-header)/team/page.tsx b/src/app/(with-header)/team/page.tsx index 34c45d1..257d5c6 100644 --- a/src/app/(with-header)/team/page.tsx +++ b/src/app/(with-header)/team/page.tsx @@ -7,6 +7,8 @@ import { StarIcon } from '@heroicons/react/24/solid'; import { Divider, Tooltip } from '@nextui-org/react'; import Link from 'next/link'; +export const dynamic = 'force-dynamic'; + export default async function TeamPage() { const user = await getUser(); const teams = (await getTeams({ user })) diff --git a/src/app/(with-header)/user/[userId]/page.tsx b/src/app/(with-header)/user/[userId]/page.tsx index dc4e385..98ef400 100644 --- a/src/app/(with-header)/user/[userId]/page.tsx +++ b/src/app/(with-header)/user/[userId]/page.tsx @@ -5,6 +5,8 @@ import { getUserData as getChuniUserData } from '@/actions/chuni/profile'; import { UserProfile } from './user-profile'; import { db } from '@/db'; +export const dynamic = 'force-dynamic'; + export default async function UserProfilePage({ params }: { params: { userId: string; }; }) { const viewingUser = await getUser(); const user = await withUsersVisibleTo(viewingUser) diff --git a/src/config.ts b/src/config.ts index 56ed7c4..507988c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,3 +1,4 @@ +import { revalidatePath } from 'next/cache'; import { db } from './db'; export type GlobalConfig = { @@ -66,6 +67,9 @@ export const setGlobalConfig = async (update: Partial) => { (CONFIG as any)[key] = res?.value ?? value; } + if ('chuni_allow_equip_unearned' in update) + revalidatePath('/chuni/userbox', 'page'); + await db.transaction().execute(async trx => { for (const [key, value] of Object.entries(update)) { await trx.updateTable('actaeon_global_config')