initial commit

This commit is contained in:
Ken Yasue
2025-03-25 06:19:44 +01:00
parent b97fa96c25
commit 9aef2ad891
71 changed files with 13016 additions and 1 deletions

View File

@ -0,0 +1,57 @@
import { DataSource, DataSourceOptions } from 'typeorm';
import { User } from './entities/User';
import { Post } from './entities/Post';
import path from 'path';
// Default configuration for SQLite (development/testing)
const sqliteConfig: DataSourceOptions = {
type: 'sqlite',
database: path.join(process.cwd(), 'data', 'database.sqlite'),
entities: [User, Post],
synchronize: true, // Set to false in production
logging: process.env.NODE_ENV === 'development',
};
// MySQL configuration
const mysqlConfig: DataSourceOptions = {
type: 'mysql',
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '3306'),
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_DATABASE || 'kantancms',
entities: [User, Post],
synchronize: false, // Always false in production
logging: process.env.NODE_ENV === 'development',
};
// PostgreSQL configuration
const postgresConfig: DataSourceOptions = {
type: 'postgres',
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432'),
username: process.env.DB_USERNAME || 'postgres',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_DATABASE || 'kantancms',
entities: [User, Post],
synchronize: false, // Always false in production
logging: process.env.NODE_ENV === 'development',
};
// Select the database configuration based on environment variable
const getConfig = (): DataSourceOptions => {
const dbType = process.env.DB_TYPE || 'sqlite';
switch (dbType) {
case 'mysql':
return mysqlConfig;
case 'postgres':
return postgresConfig;
case 'sqlite':
default:
return sqliteConfig;
}
};
// Create and export the DataSource
export const AppDataSource = new DataSource(getConfig());

View File

@ -0,0 +1,35 @@
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, JoinColumn } from 'typeorm';
// Forward reference to User to avoid circular dependency
import type { User } from './User';
@Entity('posts')
export class Post {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ nullable: true })
parentId: string;
@Column()
userId: string;
@Column()
title: string;
@Column('text')
content: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
modifiedAt: Date;
@ManyToOne(() => Post, post => post.id, { nullable: true })
@JoinColumn({ name: 'parentId' })
parent: Post;
@ManyToOne('User', 'posts')
@JoinColumn({ name: 'userId' })
user: User;
}

View File

@ -0,0 +1,41 @@
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, OneToMany } from 'typeorm';
// Forward reference to Post to avoid circular dependency
import type { Post } from './Post';
import * as bcrypt from 'bcrypt';
@Entity('users')
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ unique: true })
username: string;
@Column()
password: string;
@Column({ nullable: true, type: 'varchar', default: null })
avatar: string | null;
@Column({ type: 'varchar', default: 'system' })
theme: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
modifiedAt: Date;
@OneToMany('Post', 'user')
posts: Post[];
// Method to hash password before saving
async hashPassword() {
this.password = await bcrypt.hash(this.password, 10);
}
// Method to validate password
async validatePassword(password: string): Promise<boolean> {
return bcrypt.compare(password, this.password);
}
}

36
src/lib/database/index.ts Normal file
View File

@ -0,0 +1,36 @@
import 'reflect-metadata';
import { AppDataSource } from './config';
import fs from 'fs';
import path from 'path';
// Ensure data directory exists for SQLite
const dataDir = path.join(process.cwd(), 'data');
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
// Initialize database connection
export const initializeDatabase = async () => {
try {
if (!AppDataSource.isInitialized) {
await AppDataSource.initialize();
console.log('Database connection established successfully');
}
return AppDataSource;
} catch (error) {
console.error('Error during database initialization:', error);
throw error;
}
};
// Get the initialized data source
export const getDataSource = async () => {
if (!AppDataSource.isInitialized) {
await initializeDatabase();
}
return AppDataSource;
};
// Export entities - Post must be exported after User to resolve circular dependency
export * from './entities/User';
export * from './entities/Post';