programado/komando

Laravel utilities by programado, including database synchronization and reusable GraphQL file attachments.
5
Install
composer require programado/komando
Latest Version:v1.1.1
PHP:>=8.4
License:MIT
Last Updated:Aug 29, 2026
Links: GitHub  ·  Packagist
Maintainer: programado

Komando

GraphQL scalars

Programado\Komando\GraphQL\Scalars\DateTimeTz extends Lighthouse's DateTimeTz scalar. It accepts ISO 8601 timestamps emitted by Temporal with up to nine fractional digits, truncates them to Carbon's microsecond precision and normalizes parsed values to UTC.

scalar DateTimeTz @scalar(class: "Programado\\Komando\\GraphQL\\Scalars\\DateTimeTz")

Exception reports

Komando can queue throttled exception report mails without serializing the request body. The module is disabled by default. Enable and configure it in config/komando.php, then forward Laravel's report callback to the reporter:

use Illuminate\Foundation\Configuration\Exceptions;
use Programado\Komando\ExceptionReporting\Services\ExceptionMailReporter;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->report(function (Throwable $exception) {
        app(ExceptionMailReporter::class)->report(
            $exception,
            app()->runningInConsole() ? null : request(),
        );
    });
})

The reporter groups equivalent failures by exception class, normalized message and application location. It stores only the request method, URL without query parameters, route, authenticated user ID and request ID. Delivery failures are wrapped in a non-reportable exception so a broken mail transport cannot recursively create more report jobs. Configure and run a worker for the queue named by komando.exception_reports.queue.

GraphQL file attachments

Komando provides reusable named singular and plural file attachments for Eloquent models and Lighthouse mutations. The package includes a ready-to-use file model, file and attachment migrations, a download route and the complete attachment lifecycle. Applications only keep their slot enum, authorization and legacy data migrations.

Requirements

  • Configure Lighthouse with transactional_mutations enabled so the parent mutation and its files share one transaction.
  • Enable the file module before running migrations.
  • Custom file models must contain name, mime_type, extension, size and metadata columns.

The package migrations create files and file_attachments. Laravel derives file_id as an integer, UUID or ULID through the configured file model. attachable_id follows Laravel's global morph key type.

Schema::morphUsingUuids();
// Or Schema::morphUsingUlids() when attachment owners use ULIDs.

Existing applications keep project-specific data migrations, for example renaming an old polymorphic table or mapping legacy tags to slots. Set migrate_file_table to false when the application already owns the files table. Keep this setting stable so migration rollback uses the same table ownership decision. Set migrations to false only when the application deliberately owns all package tables.

Configuration

Publish the configuration and configure the application's file model:

php artisan vendor:publish --provider="Programado\Komando\Providers\KomandoServiceProvider" --tag="config"
'files' => [
    'enabled' => true,
    'migrations' => true,
    'migrate_file_table' => true,
    'file_model' => Programado\Komando\Files\Models\File::class,
    'attachment_model' => Programado\Komando\Files\Models\FileAttachment::class,
    'factory' => Programado\Komando\Files\Services\DefaultStoredFileFactory::class,
    'disk' => 'files',
    'attachment_table' => 'file_attachments',
    'graphql_slot_type' => 'FileSlot',
    'download' => [
        'enabled' => true,
        'path' => 'api/files/{file}/download',
        'middleware' => [],
    ],
],

The default file model uses ULIDs and exposes storageName(), name(), path() and url(). Its download route is named komando.files.download. The path and middleware can be configured without changing the generated URLs.

Applications can replace it with a custom model implementing StoredFileContract and using IsStoredFile:

use Programado\Komando\Files\Contracts\StoredFileContract;
use Programado\Komando\Files\Traits\IsStoredFile;

class File extends Model implements StoredFileContract
{
    use HasUlids, IsStoredFile;
}

Models that own files implement HasFileAttachmentsContract:

use Programado\Komando\Files\Contracts\HasFileAttachmentsContract;
use Programado\Komando\Files\Traits\HasFileAttachments;

class Workspace extends Model implements HasFileAttachmentsContract
{
    use HasFileAttachments;
}

The application owns and registers its concrete backed FileSlot enum. Alternatively, keep the default graphql_slot_type value String and quote slot names in the schema.

Publish the shared attachment input:

php artisan vendor:publish --provider="Programado\Komando\Providers\KomandoServiceProvider" --tag="komando-files-graphql"

The directives are discovered automatically and work on output and input fields:

type Workspace {
  logo_light: File @fileAttachment(slot: WORKSPACE_LOGO_LIGHT)
  documents(where: _ @searchBy, order: _ @sortBy): [File!]!
    @fileAttachments(slot: WORKSPACE_DOCUMENTS)
}

input UpsertWorkspaceInput {
  id: ID
  logo_light: Upload @fileAttachment(slot: WORKSPACE_LOGO_LIGHT)
  documents: FileAttachmentChangesInput @fileAttachments(slot: WORKSPACE_DOCUMENTS)
}

For @fileAttachment, omitted input keeps the slot unchanged, an Upload replaces it and null removes it. @fileAttachments requires a named collection and accepts add: [Upload!] and remove: [ID!]; removal is restricted to plural files related to the mutated owner and named slot. Field arguments such as where: _ @searchBy and order: _ @sortBy are applied to the underlying file query. New physical files are deleted after rollback, while replaced files are only deleted after commit and only when no attachment references remain.

Applications with additional required file columns can configure a custom implementation of StoredFileFactoryContract.

After the database record and physical file are stored successfully, Komando dispatches StoredFileStored. The event implements ShouldDispatchAfterCommit, so listeners only run after the complete Lighthouse transaction commits.

Database sync

Description

This Artisan command enables the synchronization of databases between a remote system and your local development environment. It creates a dump of the remote database, compresses it, transfers it to your local system, and imports it into your local database.

Requirements

Local Requirements

  • scp - for secure file transfer
  • 7z - for compressing/decompressing database dumps
  • mysql - for importing the database

Remote Requirements

  • mysqldump - for creating database dumps
  • 7z - for compressing database dumps

Installation

  1. Install the package via Composer:
composer require programado/komando
  1. Publish the configuration file:
php artisan vendor:publish --provider="Programado\Komando\Providers\KomandoServiceProvider" --tag="config"
  1. Configure your environment variables in .env:
KOMANDO_SSH_HOST=your-remote-host.com
KOMANDO_SSH_USER=app
KOMANDO_SSH_PORT=22
KOMANDO_REMOTE_DB_HOST=127.0.0.1
KOMANDO_REMOTE_DB_USER=default
KOMANDO_REMOTE_DB_PASSWORD=your-password

Configuration

The package uses a configuration file config/komando.php with the following structure:

return [
    'database_sync' => [
        'default_connection' => 'mysql',
        'connections' => ['mysql'], // Database connections to sync
        
        'ssh' => [
            'host' => env('KOMANDO_SSH_HOST'),
            'user' => env('KOMANDO_SSH_USER', 'app'),
            'port' => env('KOMANDO_SSH_PORT', 22),
        ],
        
        'remote_database' => [
            'host' => env('KOMANDO_REMOTE_DB_HOST', '127.0.0.1'),
            'user' => env('KOMANDO_REMOTE_DB_USER', 'default'),
            'password' => env('KOMANDO_REMOTE_DB_PASSWORD'),
        ],
        
        'commands' => [
            'local' => ['scp', '7z', 'mysql'],
            'remote' => ['mysqldump', '7z'],
        ],
        
        'compression' => [
            'level' => 9, // 7z compression level (1-9)
        ],
        
        'mysqldump' => [
            'options' => ['--skip-lock-tables'],
        ],
        
        'safety' => [
            'allow_production_wipe' => false,
        ],
    ],
];

Usage

php artisan komando:sync:database

The command now reads all configuration from the config file and environment variables. No command-line parameters are needed.

Configuration Options

  • connections: Array of database connection names to sync
  • ssh.host: SSH hostname (required)
  • ssh.user: SSH username (default: 'app')
  • ssh.port: SSH port (default: 22)
  • remote_database.*: Remote database connection settings
  • commands.*: Required commands for local and remote systems
  • compression.level: 7z compression level (1-9)
  • mysqldump.options: Additional mysqldump options
  • safety.allow_production_wipe: Allow database wipe in production (default: false)

Process

The command performs the following actions for each specified database connection:

  1. Checks if all required commands are available on both local and remote systems
  2. Creates a dump of the remote database
  3. Compresses the dump on the remote system
  4. Transfers the compressed dump to your local system
  5. Extracts the dump locally
  6. Wipes your local database (with safeguards for production environments)
  7. Imports the dump into your local database
  8. Runs migrations

Security Notes

  • This command wipes your local database before import! In production environments, additional confirmation is requested.
  • Ensure your SSH credentials are secure.
  • Avoid using production systems as the target destination.

Troubleshooting

If the command fails, check the following points:

  1. Are all required commands available on both local and remote systems?
  2. Do you have access to the remote server via SSH?
  3. Does the SSH user have sufficient permissions for database access?
  4. Are the database connection settings in your .env file correctly configured?

Related Packages

joselfonseca/lighthouse-graphql-passport-auth

Add GraphQL types and mutations for login and recover password functionalities

819,812 229
fandogh/graphql

Facebook GraphQL for Laravel

15 0
aimeos/aimeos-laravel

Cloud native, API first Laravel eCommerce package with integrated AI for ultra-f...

233,627 8,692
rebing/graphql-laravel

Laravel wrapper for PHP GraphQL

8,176,090 2,220
nuwave/lighthouse

A framework for serving GraphQL from Laravel

12,578,011 3,501