chore: bootstrap development environment
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#111827" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,7 @@
|
||||
# Calculation engine
|
||||
|
||||
기존 스킬 로스 계산기의 계산 로직을 UI와 분리해 둘 위치입니다.
|
||||
|
||||
- Svelte 컴포넌트나 SvelteKit 서버 모듈을 import하지 않습니다.
|
||||
- 브라우저, Web Worker, Node.js, 단위 테스트에서 공유할 수 있는 순수 TypeScript로 작성합니다.
|
||||
- 공용 데이터 타입은 `src/lib/models`에서 가져옵니다.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Shared models
|
||||
|
||||
UI, 계산 엔진, 서버가 함께 사용하는 도메인 타입과 검증 규칙을 둡니다. 특정 실행 환경에 의존하는 코드는 포함하지 않습니다.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Server-only modules
|
||||
|
||||
SQLite/Drizzle 저장소와 SvelteKit 서버에서만 사용하는 모듈을 둡니다. 이 디렉터리의 코드는 브라우저나 계산 엔진에서 import하지 않습니다.
|
||||
@@ -0,0 +1,24 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import { dirname } from 'node:path';
|
||||
import Database from 'better-sqlite3';
|
||||
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
||||
import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
|
||||
import { sql } from 'drizzle-orm';
|
||||
|
||||
const databaseUrl = env.DATABASE_URL ?? './data/holodream.db';
|
||||
|
||||
if (databaseUrl !== ':memory:') {
|
||||
mkdirSync(dirname(databaseUrl), { recursive: true });
|
||||
}
|
||||
|
||||
const sqlite = new Database(databaseUrl);
|
||||
sqlite.pragma('journal_mode = WAL');
|
||||
sqlite.pragma('foreign_keys = ON');
|
||||
|
||||
export const db = drizzle(sqlite);
|
||||
migrate(db, { migrationsFolder: './drizzle' });
|
||||
|
||||
export function checkDatabase(): void {
|
||||
db.run(sql`select 1`);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core';
|
||||
|
||||
// Infrastructure-only table. Game and user schemas will be added in later phases.
|
||||
export const appMetadata = sqliteTable('app_metadata', {
|
||||
key: text('key').primaryKey(),
|
||||
value: text('value').notNull(),
|
||||
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull()
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
# Web Workers
|
||||
|
||||
덱 조합 탐색처럼 UI를 막을 수 있는 계산의 Web Worker 진입점을 둡니다. 실제 최적화 로직은 `src/lib/engine`을 호출하도록 구성합니다.
|
||||
@@ -0,0 +1,47 @@
|
||||
<svelte:head>
|
||||
<title>Holodream Tools</title>
|
||||
<meta name="description" content="홀로드림스 통합 덱 최적화 도구" />
|
||||
</svelte:head>
|
||||
|
||||
<main>
|
||||
<section class="panel">
|
||||
<p class="eyebrow">Development Environment</p>
|
||||
<h1>Holodream Tools</h1>
|
||||
<p>통합 덱 최적화 사이트의 기본 개발 환경이 준비되었습니다.</p>
|
||||
|
||||
<div class="status">
|
||||
<span class="dot"></span>
|
||||
<span>SvelteKit 서버가 실행 중입니다.</span>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
:global(*) { box-sizing: border-box; }
|
||||
:global(body) {
|
||||
margin: 0;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
color: #e5e7eb;
|
||||
background: #0b1020;
|
||||
}
|
||||
main {
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 24px;
|
||||
}
|
||||
.panel {
|
||||
width: min(680px, 100%);
|
||||
padding: 36px;
|
||||
border: 1px solid #27324a;
|
||||
border-radius: 18px;
|
||||
background: #111827;
|
||||
}
|
||||
.eyebrow { color: #93c5fd; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; font-size: 12px; }
|
||||
h1 { margin: 8px 0 12px; font-size: clamp(32px, 6vw, 52px); }
|
||||
p { color: #aeb8c8; line-height: 1.65; }
|
||||
.status { margin-top: 28px; display: flex; align-items: center; gap: 10px; color: #d1fae5; }
|
||||
.dot { width: 10px; height: 10px; border-radius: 999px; background: #34d399; box-shadow: 0 0 16px #34d399; }
|
||||
</style>
|
||||
@@ -0,0 +1,29 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { checkDatabase } from '$lib/server/db/client';
|
||||
|
||||
export function GET() {
|
||||
const checkedAt = new Date().toISOString();
|
||||
|
||||
try {
|
||||
checkDatabase();
|
||||
|
||||
return json({
|
||||
ok: true,
|
||||
service: 'holodream-tools',
|
||||
database: 'ok',
|
||||
checkedAt
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Health check failed', error);
|
||||
|
||||
return json(
|
||||
{
|
||||
ok: false,
|
||||
service: 'holodream-tools',
|
||||
database: 'unavailable',
|
||||
checkedAt
|
||||
},
|
||||
{ status: 503 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user