Skip to content

ArtMin96/ai

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Contributing to Conductor

Architecture Patterns

Conductor follows a DDD-lite architecture. All domain code lives under app/Domains/{Domain}/.

Actions

Single-responsibility classes with one public execute() method. Dependencies via constructor injection.

<?php

declare(strict_types=1);

namespace App\Domains\{Domain}\Actions;

final class DoSomething
{
    public function __construct(
        private readonly SomeDependency $dependency,
    ) {}

    public function execute(SomeDTO $data): ResultType
    {
        // Single responsibility
    }
}

Rules:

  • Always final class
  • Always declare(strict_types=1)
  • Single public execute() method
  • Constructor injection for dependencies
  • Explicit return type declarations

DTOs (Data Transfer Objects)

Immutable data carriers using final readonly class and constructor property promotion.

<?php

declare(strict_types=1);

namespace App\Domains\{Domain}\DTOs;

final readonly class ExampleData
{
    /**
     * @param  array<int, string>  $items
     */
    public function __construct(
        public string $name,
        public int $priority,
        public array $items = [],
    ) {}

    /**
     * @param  array{name: string, priority: int, items?: array<int, string>}  $data
     */
    public static function fromArray(array $data): self
    {
        return new self(
            name: $data['name'],
            priority: $data['priority'],
            items: $data['items'] ?? [],
        );
    }
}

Rules:

  • Always final readonly class
  • Always declare(strict_types=1)
  • Constructor property promotion
  • PHPDoc @param generics for array types
  • Include fromArray() or fromRequest() static factory method

Value Objects

Domain concepts with equality semantics.

<?php

declare(strict_types=1);

namespace App\Domains\{Domain}\ValueObjects;

final readonly class StoryId
{
    public function __construct(
        public string $prefix,
        public int $number,
    ) {}

    public function toString(): string
    {
        return sprintf('%s-%03d', $this->prefix, $this->number);
    }
}

Rules:

  • Always final readonly class
  • Always declare(strict_types=1)
  • Provide toString() or similar display method

Enums

Finite state sets with string backing type and TitleCase keys.

<?php

declare(strict_types=1);

namespace App\Domains\{Domain}\Enums;

enum Status: string
{
    case Pending = 'pending';
    case InProgress = 'in_progress';
    case Completed = 'completed';
}

Rules:

  • Always string backing type
  • Always TitleCase keys (e.g., InProgress, not IN_PROGRESS)
  • Always declare(strict_types=1)

Models

Eloquent models with ULID primary keys.

<?php

declare(strict_types=1);

namespace App\Domains\{Domain}\Models;

use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Project extends Model
{
    use HasFactory, HasUlids;

    protected $fillable = ['name', 'path'];

    protected function casts(): array
    {
        return [
            'settings' => 'array',
        ];
    }
}

Rules:

  • Use HasUlids trait (Laravel built-in) for ULID primary keys
  • Use HasFactory for testing
  • Define casts() as a method, not a property
  • Use Model::query() for queries, not DB:: facade

Event Broadcasting

Events that need to reach the NativePHP frontend implement ShouldBroadcastNow on the nativephp channel:

use Illuminate\Broadcasting\Channel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

class SomethingHappened implements ShouldBroadcastNow
{
    public function broadcastOn(): array
    {
        return [new Channel('nativephp')];
    }
}

Frontend listeners must be inside the native:init handler:

window.addEventListener('native:init', () => {
    Native.on('App\\Domains\\Example\\Events\\SomethingHappened', (payload) => {
        // Handle event
    });
});

Browser dev fallback: Use Inertia polling (router.reload() at 1-2s intervals) when running without NativePHP.

Code Style

  • Run vendor/bin/pint --dirty after modifying PHP files
  • Run npm run lint after modifying TypeScript files
  • Commit format: feat: {STORY_ID} - {Title}

Queue Configuration

  • Standard jobs dispatch to the default queue
  • Long-running agent processes dispatch to the execution queue (no timeout)

About

No description, website, or topics provided.

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors