REFACTOR(repo): simplify project structure

- Move services/nextjs to nextjs/
- Move deploy/docker/Dockerfile.prod to Dockerfile
- Add GitHub Actions workflows (ci.yml, build.yml)
- Remove deploy/, services/, scripts/ folders
This commit is contained in:
2026-01-05 02:29:10 +09:00
commit e82ea71c22
205 changed files with 21304 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
import { NextRequest, NextResponse } from 'next/server'
import { authenticateUser, generateToken } from '@/shared/lib/auth'
export async function POST(req: NextRequest) {
try {
const { email, password } = await req.json()
// Validation
if (!email || !password) {
return NextResponse.json(
{ error: 'Email and password are required' },
{ status: 400 }
)
}
// Authenticate user
const user = await authenticateUser(email, password)
if (!user) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
)
}
// Generate JWT token
const token = generateToken({
userId: user.id,
email: user.email,
})
// Create response with user data
const response = NextResponse.json({
message: 'Login successful',
token,
user: {
id: user.id,
email: user.email,
name: user.name,
image: user.image,
},
})
// Set auth token in cookie (HttpOnly for security)
response.cookies.set('auth-token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 7, // 7 days
path: '/',
})
return response
} catch (error) {
console.error('Login error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,22 @@
import { NextRequest, NextResponse } from 'next/server'
export async function POST(req: NextRequest) {
try {
// Create response
const response = NextResponse.json({
message: 'Logout successful',
})
// Clear auth token cookie
response.cookies.delete('auth-token')
return response
} catch (error) {
console.error('Logout error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,54 @@
import { NextRequest, NextResponse } from 'next/server'
import { verifyToken } from '@/shared/lib/auth'
import { db } from '@/shared/lib/db'
export async function GET(req: NextRequest) {
try {
// Get token from cookie
const token = req.cookies.get('auth-token')?.value
if (!token) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
)
}
// Verify token
const payload = verifyToken(token)
if (!payload) {
return NextResponse.json(
{ error: 'Invalid token' },
{ status: 401 }
)
}
// Get user from database
const user = await db.user.findUnique({
where: { id: payload.userId },
select: {
id: true,
email: true,
name: true,
image: true,
},
})
if (!user) {
return NextResponse.json(
{ error: 'User not found' },
{ status: 404 }
)
}
return NextResponse.json(user)
} catch (error) {
console.error('Get user error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,76 @@
import { NextRequest, NextResponse } from 'next/server'
import { createUser, generateToken } from '@/shared/lib/auth'
import { db } from '@/shared/lib/db'
export async function POST(req: NextRequest) {
try {
const { email, password, name } = await req.json()
// Validation
if (!email || !password) {
return NextResponse.json(
{ error: 'Email and password are required' },
{ status: 400 }
)
}
if (password.length < 6) {
return NextResponse.json(
{ error: 'Password must be at least 6 characters' },
{ status: 400 }
)
}
// Check if user already exists
const existingUser = await db.user.findUnique({
where: { email },
})
if (existingUser) {
return NextResponse.json(
{ error: 'User already exists' },
{ status: 400 }
)
}
// Create user
const user = await createUser(email, password, name)
// Generate JWT token
const token = generateToken({
userId: user.id,
email: user.email,
})
// Create response with user data
const response = NextResponse.json(
{
message: 'User created successfully',
token,
user: {
id: user.id,
email: user.email,
name: user.name,
}
},
{ status: 201 }
)
// Set auth token in cookie (HttpOnly for security)
response.cookies.set('auth-token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 60 * 60 * 24 * 7, // 7 days
path: '/',
})
return response
} catch (error) {
console.error('Registration error:', error)
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
)
}
}