Adding better routing
This commit is contained in:
@@ -423,6 +423,15 @@ app.post('/api/playthroughs/:id/achievements', async (req, res, next) => {
|
||||
result.ok ? res.json({ earned: result.earned }) : res.status(result.error === 'Playthrough not found' ? 404 : 400).json({ error: result.error })
|
||||
} catch (error) { next(error) }
|
||||
})
|
||||
// Dev teleport: jump the playthrough to an explicit story node. Powers /node/:id.
|
||||
app.post('/api/playthroughs/:id/goto', async (req, res, next) => {
|
||||
try {
|
||||
if (process.env.NODE_ENV === 'production') return res.status(403).json({ error: 'Node teleport is disabled' })
|
||||
if (!req.body?.nodeId) return res.status(400).json({ error: 'A nodeId is required' })
|
||||
const result = await narrative.gotoNode(resolveUserId(req), String(req.params.id), String(req.body.nodeId))
|
||||
result.ok ? res.json(result.state ?? null) : res.status(result.error === 'Playthrough not found' || result.error === 'Node not found' ? 404 : 400).json({ error: result.error })
|
||||
} catch (error) { next(error) }
|
||||
})
|
||||
|
||||
app.use((error: unknown, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
|
||||
if (error instanceof multer.MulterError) {
|
||||
|
||||
@@ -49,6 +49,7 @@ export interface NarrativeRepository {
|
||||
advancePlaythrough(userId: string, playthroughId: string, terminalKey?: string): Promise<{ ok: boolean; state?: PlaythroughState; error?: string }>
|
||||
listAchievements(playthroughId: string): Promise<string[] | null>
|
||||
awardAchievement(playthroughId: string, flagKey: string, nodeId?: string | null): Promise<{ ok: boolean; earned: boolean; error?: string }>
|
||||
gotoNode(userId: string, playthroughId: string, nodeId: string): Promise<{ ok: boolean; state?: PlaythroughState; error?: string }>
|
||||
listMysteries(): Promise<MysterySummary[]>
|
||||
deleteMystery(id: string): Promise<boolean>
|
||||
uploadAsset(file: UploadedFile): Promise<AssetDto>
|
||||
@@ -251,6 +252,28 @@ export function createNarrativeRepository(pool: Pool, objectStorage: ObjectStora
|
||||
return { ok: true, earned: (result.rowCount || 0) > 0 }
|
||||
},
|
||||
|
||||
// Dev teleport: jump the playthrough straight to an explicit node (no gate
|
||||
// resolution). Instantiates a fresh level clone for level nodes. Powers /node/:id.
|
||||
async gotoNode(userId, playthroughId, nodeId) {
|
||||
const client = await pool.connect()
|
||||
try {
|
||||
await client.query('BEGIN')
|
||||
const playthrough = (await client.query<{ mystery_id: string; mystery_slug: string }>(
|
||||
`SELECT p.mystery_id, m.slug AS mystery_slug FROM osint.playthroughs p JOIN osint.mysteries m ON m.id=p.mystery_id
|
||||
WHERE p.id=$1 AND p.user_id=$2 FOR UPDATE OF p`, [playthroughId, userId])).rows[0]
|
||||
if (!playthrough) { await client.query('ROLLBACK'); return { ok: false, error: 'Playthrough not found' } }
|
||||
const node = (await client.query<{ id: string; node_type: string; level_template_version_id: string | null }>(
|
||||
'SELECT id,node_type,level_template_version_id FROM osint.story_nodes WHERE id=$1 AND mystery_id=$2', [nodeId, playthrough.mystery_id])).rows[0]
|
||||
if (!node) { await client.query('ROLLBACK'); return { ok: false, error: 'Node not found' } }
|
||||
const levelId = node.node_type === 'level' && node.level_template_version_id
|
||||
? await instantiateLevel(client, node.level_template_version_id, playthrough.mystery_slug) : null
|
||||
await client.query(`UPDATE osint.playthroughs SET status='active',current_node_id=$2,current_level_id=$3,updated_at=NOW() WHERE id=$1`, [playthroughId, node.id, levelId])
|
||||
await client.query('COMMIT')
|
||||
} catch (error) { await client.query('ROLLBACK'); throw error } finally { client.release() }
|
||||
const state = await stateForPlaythrough(playthroughId)
|
||||
return { ok: true, state: state ?? undefined }
|
||||
},
|
||||
|
||||
async advancePlaythrough(userId, playthroughId, terminalKey) {
|
||||
const client = await pool.connect()
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user