Laravel schema and base Eloquent models for imported FTN archive facts.
This package owns the durable facts that come from FTN message archives: areas, messages, source identity, addressing, bodies, reply metadata, control lines, and import provenance.
It does not own reader UI state. Read flags, bookmarks, cached counters, and current positions belong in the consuming app.
composer require golded-dev/laravel-ftn-database:^1.0Requires PHP 8.4+ and Laravel 13 components.
Supported database targets:
- SQLite
- MySQL
- PostgreSQL
Golded\Ftn\Database\FtnDatabaseServiceProviderGolded\Ftn\Database\Models\AreaGolded\Ftn\Database\Models\Message- config publishing through the
ftn-database-configtag - migration publishing through the
ftn-database-migrationstag - package migrations that load by default
The package creates areas and messages.
Package migrations load automatically unless the consumer disables them:
'load_migrations' => false,Publish migrations when the app needs to own the files directly:
php artisan vendor:publish --tag=ftn-database-migrationscontrol_lines_json and provenance_json are text-backed JSON payloads with array casts on the model. That keeps SQLite, MySQL, and PostgreSQL behavior plain.
Publish the config:
php artisan vendor:publish --tag=ftn-database-configDefault config:
return [
'load_migrations' => true,
'models' => [
'area' => Golded\Ftn\Database\Models\Area::class,
'message' => Golded\Ftn\Database\Models\Message::class,
],
];Apps can point relationships at subclasses:
'models' => [
'area' => App\Models\Area::class,
'message' => App\Models\Message::class,
],The base relationships resolve through config. They do not know about App\Models.
Use the base models directly for archive-only apps:
use Golded\Ftn\Database\Models\Area;
use Golded\Ftn\Database\Models\Message;
$area = Area::create([
'code' => 'TEST',
'name' => 'Test Area',
'source_type' => 'jam',
]);
Message::create([
'area_id' => $area->id,
'source_type' => 'jam',
'source_uid' => 'jam:offset:256',
'body_text' => 'Hello',
]);For GoldED-style apps, subclass the models and add only app-owned state:
namespace App\Models;
use Golded\Ftn\Database\Models\Message as BaseMessage;
class Message extends BaseMessage
{
protected $fillable = [
'area_id',
'msgno',
'source_type',
'source_uid',
'body_text',
'is_read',
'is_marked',
'is_bookmarked',
'thread_key',
];
}Keep imported archive facts in the package columns. Keep reader behavior in the app.
The import identity is:
area_idsource_typesource_uid
msgno is display and navigation metadata. It is not identity.
external_id is unique only inside an area. Multiple null external IDs are allowed.
Install dependencies:
composer installRun tests:
composer testRun static analysis:
composer test:typesRun Rector dry-run:
composer test:refactorRun everything:
composer test:allThe MySQL migration check is skipped unless these environment variables are set:
FTN_DATABASE_MYSQL_DATABASEFTN_DATABASE_MYSQL_HOSTFTN_DATABASE_MYSQL_PORTFTN_DATABASE_MYSQL_USERNAMEFTN_DATABASE_MYSQL_PASSWORD
The PostgreSQL migration check is skipped unless these environment variables are set:
FTN_DATABASE_POSTGRES_DATABASEFTN_DATABASE_POSTGRES_HOSTFTN_DATABASE_POSTGRES_PORTFTN_DATABASE_POSTGRES_USERNAMEFTN_DATABASE_POSTGRES_PASSWORD
This package starts at 1.0.0 and uses semantic versioning.
Breaking changes include schema changes, model fillable or cast changes that affect persisted data, service provider behavior changes, and supported Laravel or PHP version changes.
Contributions are welcome when they keep the archive/app boundary sharp. See CONTRIBUTING.md.
Do not report security issues in public tickets. See SECURITY.md.
See CHANGELOG.md.
Released under the MIT License. See LICENSE.