merge: 최신 main을 정적 프런트엔드 작업에 통합한다
This commit is contained in:
@@ -21,6 +21,7 @@ import { openPassword, zDisplayName, zPasswordEnvelope, zRegistrationUsername }
|
||||
import { resolveEffectiveAccountIcon } from './auth/accountIconProjection.js';
|
||||
import { purifyGatewayNoticeHtml } from './security/gatewayNoticeHtml.js';
|
||||
import type { GatewayApiContext } from './context.js';
|
||||
import { listScenarioPreviews } from './scenario/scenarioCatalog.js';
|
||||
import {
|
||||
KakaoVerificationError,
|
||||
mergeRequiredKakaoScopes,
|
||||
@@ -193,6 +194,42 @@ export const appRouter = router({
|
||||
})
|
||||
);
|
||||
}),
|
||||
scenarios: procedure
|
||||
.input(z.object({ profileName: z.string().min(1).max(64) }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const provided = ctx.requestHeaders['x-session-token'];
|
||||
const sessionToken = Array.isArray(provided) ? provided[0] : provided;
|
||||
if (!sessionToken) {
|
||||
throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Session token is required.' });
|
||||
}
|
||||
const session = await ctx.sessions.getSession(sessionToken);
|
||||
const user = session ? await ctx.users.findById(session.userId) : null;
|
||||
if (!session || !user) {
|
||||
throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Session is not valid.' });
|
||||
}
|
||||
|
||||
const visibleProfiles = await ctx.profileStatus.listLobbyProfiles({ userId: user.id });
|
||||
if (!visibleProfiles.some((profile) => profile.profileName === input.profileName)) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Profile not found.' });
|
||||
}
|
||||
const profile = await ctx.profiles.getProfile(input.profileName);
|
||||
const activeBuildCommit = profile?.buildCommitSha?.trim();
|
||||
if (!profile || !activeBuildCommit) {
|
||||
throw new TRPCError({
|
||||
code: 'PRECONDITION_FAILED',
|
||||
message: 'The profile has no active build commit.',
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
return await listScenarioPreviews({ gitRef: activeBuildCommit });
|
||||
} catch {
|
||||
throw new TRPCError({
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
message: 'The active build scenario catalog could not be read.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
}),
|
||||
admin: adminRouter,
|
||||
account: accountRouter,
|
||||
|
||||
@@ -22,6 +22,8 @@ export interface ScenarioPreview {
|
||||
id: number;
|
||||
title: string;
|
||||
year: number | null;
|
||||
defaultStatTotal: number;
|
||||
fiction: number | null;
|
||||
npcCount: number;
|
||||
npcExCount: number;
|
||||
npcNeutralCount: number;
|
||||
@@ -227,6 +229,8 @@ const buildScenarioPreview = async (scenarioId: number): Promise<ScenarioPreview
|
||||
id: scenarioId,
|
||||
title: scenario.title,
|
||||
year: scenario.startYear ?? null,
|
||||
defaultStatTotal: scenario.config.stat.total,
|
||||
fiction: scenario.fiction,
|
||||
npcCount: scenario.generals.length,
|
||||
npcExCount: scenario.generalsEx.length,
|
||||
npcNeutralCount: scenario.generalsNeutral.length,
|
||||
@@ -272,6 +276,8 @@ const buildScenarioPreviewFromGit = async (commitSha: string, scenarioId: number
|
||||
id: scenarioId,
|
||||
title: scenario.title,
|
||||
year: scenario.startYear ?? null,
|
||||
defaultStatTotal: scenario.config.stat.total,
|
||||
fiction: scenario.fiction,
|
||||
npcCount: scenario.generals.length,
|
||||
npcExCount: scenario.generalsEx.length,
|
||||
npcNeutralCount: scenario.generalsNeutral.length,
|
||||
|
||||
Reference in New Issue
Block a user