1
This commit is contained in:
73
server-node/src/modules/story/storyActionRoutes.ts
Normal file
73
server-node/src/modules/story/storyActionRoutes.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Router } from 'express';
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { RuntimeStoryActionRequest } from '../../../../packages/shared/src/contracts/story.js';
|
||||
import type { AppContext } from '../../context.js';
|
||||
import { badRequest } from '../../errors.js';
|
||||
import { asyncHandler, sendApiResponse } from '../../http.js';
|
||||
import { requireJwtAuth } from '../../middleware/auth.js';
|
||||
import { routeMeta } from '../../middleware/routeMeta.js';
|
||||
import {
|
||||
getRuntimeStoryState,
|
||||
resolveRuntimeStoryAction,
|
||||
} from './storyActionService.js';
|
||||
|
||||
const actionPayloadSchema = z.record(z.string(), z.unknown());
|
||||
|
||||
const runtimeStoryActionSchema = z.object({
|
||||
sessionId: z.string().trim().min(1),
|
||||
clientVersion: z.number().int().min(0).optional(),
|
||||
action: z.object({
|
||||
type: z.literal('story_choice'),
|
||||
functionId: z.string().trim().min(1),
|
||||
targetId: z.string().trim().optional(),
|
||||
payload: actionPayloadSchema.optional().default({}),
|
||||
}),
|
||||
});
|
||||
|
||||
export function createStoryActionRoutes(context: AppContext) {
|
||||
const router = Router();
|
||||
const requireAuth = requireJwtAuth(context.config, context.userRepository);
|
||||
|
||||
router.use(requireAuth);
|
||||
|
||||
router.post(
|
||||
'/actions/resolve',
|
||||
routeMeta({ operation: 'runtime.story.actions.resolve' }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const payload = runtimeStoryActionSchema.parse(
|
||||
request.body,
|
||||
) as RuntimeStoryActionRequest;
|
||||
sendApiResponse(
|
||||
response,
|
||||
await resolveRuntimeStoryAction({
|
||||
runtimeRepository: context.runtimeRepository,
|
||||
userId: request.userId!,
|
||||
request: payload,
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/state/:sessionId',
|
||||
routeMeta({ operation: 'runtime.story.state.get' }),
|
||||
asyncHandler(async (request, response) => {
|
||||
const sessionId = request.params.sessionId?.trim() || '';
|
||||
if (!sessionId) {
|
||||
throw badRequest('sessionId is required');
|
||||
}
|
||||
|
||||
sendApiResponse(
|
||||
response,
|
||||
await getRuntimeStoryState({
|
||||
runtimeRepository: context.runtimeRepository,
|
||||
userId: request.userId!,
|
||||
sessionId,
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
return router;
|
||||
}
|
||||
Reference in New Issue
Block a user