diff --git a/backend/src/index.js b/backend/src/index.ts similarity index 52% rename from backend/src/index.js rename to backend/src/index.ts index 5b84f3f..7268b90 100644 --- a/backend/src/index.js +++ b/backend/src/index.ts @@ -1,4 +1,5 @@ -const { Pool } = require("pg"); +import { Pool } from "pg"; + const pool = new Pool({ user: process.env.DB_USER, host: process.env.DB_HOST, @@ -7,57 +8,57 @@ const pool = new Pool({ port: parseInt(process.env.DB_PORT || '5432'), ssl: { rejectUnauthorized: false } }); -async function initializeTable() { - try { - await pool.query(` - CREATE TABLE IF NOT EXISTS scores ( - id SERIAL PRIMARY KEY, - player_name VARCHAR(100) NOT NULL, - time_taken INTEGER NOT NULL, - blocks INTEGER NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); - `); - console.log('Table initialized'); - } catch (error) { - console.error('Table initialization error:', error); - } + +async function initializeTable(): Promise { + await pool.query(` + CREATE TABLE IF NOT EXISTS scores ( + id SERIAL PRIMARY KEY, + player_name VARCHAR(100) NOT NULL, + time_taken INTEGER NOT NULL, + blocks INTEGER NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + `); } -exports.handler = async (event) => { - // console.log('Full event:', JSON.stringify(event, null, 2)); - // console.log('httpMethod:', event.httpMethod); - // console.log('path:', event.path); - // console.log('body:', event.body); - - await initializeTable(); - - const headers = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token', - 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', - 'Content-Type': 'application/json' - }; - - const method = event.httpMethod ? event.httpMethod.toUpperCase() : null; +const tableInitPromise = initializeTable().catch(error => { + console.error('Table initialization error:', error); + process.exit(1); +}); + +interface LambdaEvent { + httpMethod: string; + body: string | null; +} + +interface LambdaResponse { + statusCode: number; + headers: Record; + body: string; +} + +const headers = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token', + 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', + 'Content-Type': 'application/json' +}; + +export const handler = async (event: LambdaEvent): Promise => { + await tableInitPromise; + + const method = event.httpMethod?.toUpperCase() ?? null; + if (method === 'OPTIONS') { - return { - statusCode: 200, - headers, - body: '' - }; + return { statusCode: 200, headers, body: '' }; } + if (method === 'GET') { try { const result = await pool.query( `SELECT player_name, time_taken, blocks, created_at FROM scores ORDER BY time_taken ASC LIMIT 10;` ); - - return { - statusCode: 200, - headers, - body: JSON.stringify(result.rows) - }; + return { statusCode: 200, headers, body: JSON.stringify(result.rows) }; } catch (error) { console.error('DB Select Error:', error); return { @@ -67,11 +68,15 @@ exports.handler = async (event) => { }; } } - if (event.httpMethod === 'POST') { + + if (method === 'POST') { try { + if (!event.body) { + return { statusCode: 400, headers, body: JSON.stringify({ message: 'Invalid data' }) }; + } const body = JSON.parse(event.body); const { player_name, time_taken, blocks } = body; - + if (typeof time_taken !== 'number' || !player_name) { return { statusCode: 400, @@ -79,12 +84,12 @@ exports.handler = async (event) => { body: JSON.stringify({ message: 'Invalid data' }) }; } - + await pool.query( `INSERT INTO scores(player_name, time_taken, blocks) VALUES($1, $2, $3);`, [player_name, time_taken, blocks] ); - + return { statusCode: 201, headers, @@ -99,10 +104,10 @@ exports.handler = async (event) => { }; } } + return { statusCode: 404, headers, - body: JSON.stringify({ message: "DEBUG: Final Fallback 404." }) // メッセージを再変更 + body: JSON.stringify({ message: 'Not Found' }) }; }; - diff --git a/backend/src/server.ts b/backend/src/server.ts index 056b69f..f68983f 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -1,30 +1,55 @@ import * as dotenv from "dotenv"; import express from 'express'; -import { Pool} from "pg"; +import { Pool } from "pg"; import cors from 'cors'; dotenv.config(); const pool = new Pool({ connectionString: process.env.DATABASE_URL, }); -pool.connect().catch(err => console.error('DB connection error:', err)); + +pool.query(` + CREATE TABLE IF NOT EXISTS scores ( + id SERIAL PRIMARY KEY, + player_name VARCHAR(100) NOT NULL, + time_taken INTEGER NOT NULL, + blocks INTEGER NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); +`).catch(error => { + console.error('Table initialization error:', error); + process.exit(1); +}); const app = express(); const corsOptions = { - origin: process.env.CORS_URL, + origin: process.env.CORS_URL, optionsSuccessStatus: 200 }; app.use(cors(corsOptions)); -app.use(express.json()); +app.use(express.json()); + +app.get('/api/scores', async (req, res) => { + try { + const result = await pool.query( + `SELECT player_name, time_taken, blocks, created_at FROM scores ORDER BY time_taken ASC LIMIT 10;` + ); + res.status(200).json(result.rows); + } catch (error) { + console.error('DB Select Error:', error); + res.status(500).send('Database error'); + } +}); + app.post('/api/score', async (req, res) => { - const { player_name, time_taken } = req.body; + const { player_name, time_taken, blocks } = req.body; if (typeof time_taken !== 'number' || !player_name) { return res.status(400).send('Invalid data'); } try { await pool.query( - `INSERT INTO users(player_name, time_taken) VALUES($1, $2);`, - [player_name, time_taken] + `INSERT INTO scores(player_name, time_taken, blocks) VALUES($1, $2, $3);`, + [player_name, time_taken, blocks] ); res.status(201).send({ message: 'Score saved successfully' }); } catch (error) {