build: initialize RetroHub with Laravel, Inertia, Vue, and Horizon

This commit is contained in:
2026-08-10 13:45:18 +02:00
commit 717db65139
218 changed files with 28356 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace Database\Factories;
use App\Features\Consoles\Models\Console;
use Illuminate\Database\Eloquent\Factories\Factory;
class ConsoleFactory extends Factory
{
protected $model = Console::class;
public function definition(): array
{
$name = fake()->unique()->words(2, true);
return [
'name' => $name,
'slug' => fake()->unique()->slug(),
'rom_extensions' => [['nes']],
'igdb_platform_id' => fake()->optional()->randomNumber(3),
'tgdb_platform_id' => fake()->optional()->randomNumber(4),
];
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace Database\Factories;
use App\Features\Consoles\Models\Console;
use App\Features\Games\Models\Game;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class GameFactory extends Factory
{
protected $model = Game::class;
public function definition(): array
{
$title = fake()->unique()->words(3, true);
return [
'console_id' => Console::factory(),
'title' => $title,
'slug' => Str::slug($title),
'description' => fake()->optional()->paragraph(),
'release_year' => fake()->optional()->year(),
'developer' => fake()->optional()->company(),
'publisher' => fake()->optional()->company(),
'genre' => fake()->optional()->randomElement(['Action', 'RPG', 'Platformer', 'Puzzle', 'Sports']),
'rating' => fake()->optional(0.7)->randomFloat(1, 0, 10),
];
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace Database\Factories;
use App\Features\Games\Models\Game;
use App\Features\Games\Models\RomFile;
use Illuminate\Database\Eloquent\Factories\Factory;
class RomFileFactory extends Factory
{
protected $model = RomFile::class;
public function definition(): array
{
$filename = fake()->word().'.nes';
return [
'game_id' => Game::factory(),
'file_path' => "roms/nes/{$filename}",
'file_name' => $filename,
'file_size' => fake()->numberBetween(100000, 10000000),
'file_hash' => hash('sha256', fake()->uuid()),
];
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Database\Factories;
use App\Features\Games\Models\Game;
use App\Features\Settings\Models\SaveFile;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class SaveFileFactory extends Factory
{
protected $model = SaveFile::class;
public function definition(): array
{
$filename = fake()->word().'.srm';
return [
'user_id' => User::factory(),
'game_id' => Game::factory(),
'file_path' => "saves/{$filename}",
'file_name' => $filename,
'file_size' => fake()->numberBetween(1000, 100000),
'last_synced_at' => fake()->optional()->dateTime(),
];
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends Factory<User>
*/
class UserFactory extends Factory
{
protected $model = User::class;
protected static ?string $password;
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace Database\Factories;
use App\Features\Settings\Models\UserSetting;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserSettingFactory extends Factory
{
protected $model = UserSetting::class;
public function definition(): array
{
return [
'user_id' => User::factory(),
'setting_key' => fake()->unique()->word(),
'setting_value' => fake()->optional()->word(),
];
}
}
@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('consoles', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->string('icon_path')->nullable();
$table->json('rom_extensions');
$table->integer('igdb_platform_id')->nullable();
$table->integer('tgdb_platform_id')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('consoles');
}
};
@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('games', function (Blueprint $table) {
$table->id();
$table->foreignId('console_id')->constrained()->cascadeOnDelete();
$table->string('title');
$table->string('slug');
$table->integer('igdb_id')->nullable();
$table->integer('tgdb_id')->nullable();
$table->text('description')->nullable();
$table->integer('release_year')->nullable();
$table->string('developer')->nullable();
$table->string('publisher')->nullable();
$table->string('genre')->nullable();
$table->decimal('rating', 3, 1)->nullable();
$table->string('cover_path')->nullable();
$table->string('thumbnail_path')->nullable();
$table->timestamps();
$table->unique(['console_id', 'slug']);
});
}
public function down(): void
{
Schema::dropIfExists('games');
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('rom_files', function (Blueprint $table) {
$table->id();
$table->foreignId('game_id')->constrained()->cascadeOnDelete();
$table->string('file_path');
$table->string('file_name');
$table->bigInteger('file_size');
$table->string('file_hash')->unique();
$table->string('region')->nullable();
$table->string('language')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('rom_files');
}
};
@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('save_files', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('game_id')->constrained()->cascadeOnDelete();
$table->string('file_path');
$table->string('file_name');
$table->bigInteger('file_size');
$table->timestamp('last_synced_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('save_files');
}
};
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('user_settings', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('setting_key');
$table->text('setting_value')->nullable();
$table->timestamps();
$table->unique(['user_id', 'setting_key']);
});
}
public function down(): void
{
Schema::dropIfExists('user_settings');
}
};
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('users');
}
};
@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
}
public function down(): void
{
Schema::dropIfExists('password_reset_tokens');
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
public function down(): void
{
Schema::dropIfExists('sessions');
}
};
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('webdav_accounts', function (Blueprint $table): void {
$table->id();
// Credentials
$table->string('username')->unique();
$table->text('password_encrypted');
// State
$table->boolean('enabled')->default(true);
// Optional relation to application user
$table->unsignedBigInteger('user_id')->nullable()->index();
// Display name
$table->string('display_name')->nullable();
// Meta / extensibility
$table->json('meta')->nullable();
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->nullOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('webdav_accounts');
}
};
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace Database\Seeders;
use App\Models\Console;
use Illuminate\Database\Seeder;
class ConsoleSeeder extends Seeder
{
public function run(): void
{
$consoles = [
['name' => 'Nintendo Entertainment System', 'slug' => 'nes', 'rom_extensions' => ['nes', 'fds'], 'igdb_platform_id' => 18, 'tgdb_platform_id' => 4951],
['name' => 'Super Nintendo Entertainment System', 'slug' => 'snes', 'rom_extensions' => ['sfc', 'smc'], 'igdb_platform_id' => 19, 'tgdb_platform_id' => 4949],
['name' => 'Nintendo 64', 'slug' => 'n64', 'rom_extensions' => ['n64', 'v64', 'z64'], 'igdb_platform_id' => 4, 'tgdb_platform_id' => 4948],
['name' => 'Nintendo GameCube', 'slug' => 'gamecube', 'rom_extensions' => ['iso', 'gcm'], 'igdb_platform_id' => 21, 'tgdb_platform_id' => 4947],
['name' => 'Game Boy Advance', 'slug' => 'gba', 'rom_extensions' => ['gba'], 'igdb_platform_id' => 33, 'tgdb_platform_id' => 4953],
['name' => 'Nintendo DS', 'slug' => 'nds', 'rom_extensions' => ['nds'], 'igdb_platform_id' => 24, 'tgdb_platform_id' => 4954],
['name' => 'Sega Genesis / Mega Drive', 'slug' => 'genesis', 'rom_extensions' => ['md', 'bin', 'gen'], 'igdb_platform_id' => 29, 'tgdb_platform_id' => 4944],
['name' => 'Sega Saturn', 'slug' => 'saturn', 'rom_extensions' => ['iso', 'bin', 'cue'], 'igdb_platform_id' => 30, 'tgdb_platform_id' => 4945],
['name' => 'Sega Dreamcast', 'slug' => 'dreamcast', 'rom_extensions' => ['gdi', 'cdi', 'iso'], 'igdb_platform_id' => 31, 'tgdb_platform_id' => 4946],
['name' => 'Sony PlayStation', 'slug' => 'ps1', 'rom_extensions' => ['iso', 'bin', 'cue'], 'igdb_platform_id' => 7, 'tgdb_platform_id' => 4956],
['name' => 'Sony PlayStation 2', 'slug' => 'ps2', 'rom_extensions' => ['iso', 'bin', 'cue'], 'igdb_platform_id' => 8, 'tgdb_platform_id' => 4957],
['name' => 'Sony PlayStation Portable', 'slug' => 'psp', 'rom_extensions' => ['iso', 'cso'], 'igdb_platform_id' => 38, 'tgdb_platform_id' => 4958],
];
foreach ($consoles as $console) {
Console::updateOrCreate(
['slug' => $console['slug']],
$console
);
}
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call([
ConsoleSeeder::class,
]);
}
}