Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Duo Laravel Package

joshcirre/duo

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require joshcirre/duo
    npm install duo
    

    Add the Vite plugin to your vite.config.ts:

    import duo from 'duo/vite';
    export default defineConfig({
      plugins: [duo()],
    });
    
  2. Enable Duo for a Livewire Component Add the Duo trait to your Livewire component:

    use Joshcirre\Duo\Livewire\Duo;
    
    class UserList extends Component {
        use Duo;
    
        public function mount() {
            $this->syncModel(User::class);
        }
    }
    
  3. First Use Case

    • Access cached data offline:
      $this->getCachedUsers(); // Returns IndexedDB data if offline
      
    • Sync automatically when online:
      $this->syncModel(User::class, ['id' => 1]); // Force sync for a specific record
      

Where to Look First

  • Livewire Component Trait: Joshcirre\Duo\Livewire\Duo
  • Vite Plugin Docs: node_modules/duo/docs/vite.md
  • TypeScript Types: Auto-generated in resources/js/types/duo.d.ts

Implementation Patterns

Core Workflow

  1. Model Syncing

    // In Livewire component
    use Duo;
    
    public function mount() {
        $this->syncModel(User::class); // Syncs entire table
        $this->syncModel(User::class, ['id' => 1]); // Syncs specific record
    }
    
  2. Offline-First Data Access

    // Returns cached data if offline, otherwise fetches fresh
    $users = $this->getCachedUsers();
    
  3. Optimistic UI Updates

    // Update UI instantly, syncs in background
    $this->updateUserOptimistically(1, ['name' => 'New Name']);
    

Integration Tips

  • Volt Components: Duo works with Volt out-of-the-box. Add the trait to your Volt class:

    use Joshcirre\Duo\Volt\Duo;
    
    class UserVolt extends Component {
        use Duo;
    }
    
  • Custom Sync Logic Override syncModel() to add pre/post hooks:

    protected function syncModel(string $model, ?array $where = null): void {
        // Custom logic before sync
        parent::syncModel($model, $where);
    
        // Custom logic after sync
    }
    
  • TypeScript Usage Access generated types in your frontend:

    import { User } from '@/types/duo';
    
    const users: User[] = await duo.get('users');
    
  • Manual Sync Triggers Force sync via Alpine.js:

    <button @click="duo.sync('users')">Refresh Data</button>
    

Common Patterns

Pattern Implementation Example
Initial Load syncModel() in mount() $this->syncModel(User::class);
Optimistic Update updateOptimistically() $this->updateUserOptimistically(1, [...]);
Offline Detection duo.isOnline() in Alpine.js <span x-text="duo.isOnline() ? 'Online' : 'Offline'">
Sync Status <x-duo::sync-status /> Blade component Automatically shows sync state

Gotchas and Tips

Pitfalls

  1. Schema Mismatches

    • Issue: IndexedDB schema may drift if your database schema changes.
    • Fix: Run php artisan duo:schema:update to regenerate types.
    • Tip: Use migrations carefully—Duo will throw errors if the schema doesn’t match.
  2. Livewire Property Conflicts

    • Issue: Duo auto-generates properties (e.g., $duoCachedUsers). Conflicts may arise with existing Livewire properties.
    • Fix: Prefix your properties or use protected scope:
      protected $duoCachedUsers;
      
  3. Offline Sync Queue

    • Issue: Large sync queues may cause performance issues when coming back online.
    • Fix: Limit sync batch size in config/duo.php:
      'sync_batch_size' => 50,
      
  4. TypeScript Errors

    • Issue: Types may not update after schema changes.
    • Fix: Delete resources/js/types/duo.d.ts and run:
      npm run duo:types
      
  5. Vite Hot Reload

    • Issue: Duo’s Vite plugin may interfere with HMR.
    • Fix: Exclude Duo files from HMR in vite.config.ts:
      optimizeDeps({
        exclude: ['duo'],
      }),
      

Debugging

  • Enable Logging Add to .env:

    DUO_LOG_LEVEL=debug
    

    Logs appear in browser console and Laravel logs.

  • Check Sync Status Use the built-in debug component:

    <x-duo::debug />
    
  • Clear IndexedDB For testing, clear Duo’s IndexedDB store via:

    php artisan duo:clear
    

    Or in browser dev tools: IndexedDB > Duo > Clear.

Extension Points

  1. Custom Sync Handlers Override Joshcirre\Duo\Sync\SyncHandler to add custom logic:

    namespace App\Duo;
    
    use Joshcirre\Duo\Sync\SyncHandler as BaseHandler;
    
    class CustomSyncHandler extends BaseHandler {
        protected function beforeSync() {
            // Custom logic
        }
    }
    

    Register in config/duo.php:

    'sync_handler' => App\Duo\CustomSyncHandler::class,
    
  2. Custom IndexedDB Schema Extend the schema generator:

    namespace App\Duo;
    
    use Joshcirre\Duo\Schema\SchemaGenerator;
    
    class CustomSchemaGenerator extends SchemaGenerator {
        protected function getCustomFields() {
            return ['custom_field' => 'string'];
        }
    }
    

    Register in config/duo.php:

    'schema_generator' => App\Duo\CustomSchemaGenerator::class,
    
  3. Alpine.js Extensions Extend Duo’s Alpine.js functionality:

    duo.extend({
      async customMethod() {
        return await duo.get('custom_data');
      }
    });
    

Configuration Quirks

  • Automatic Sync Interval Defaults to 5 minutes when offline. Adjust in config/duo.php:

    'offline_sync_interval' => 300, // seconds
    
  • Model Whitelisting Duo syncs all models by default. Restrict to specific models:

    'enabled_models' => [
        'App\Models\User',
        'App\Models\Post',
    ],
    
  • Volt Integration Ensure your Volt components extend Duo trait before Component:

    use Joshcirre\Duo\Volt\Duo;
    use Livewire\Component;
    
    class UserVolt extends Component {
        use Duo; // Must come before Component
    }
    

Performance Tips

  • Lazy-Load Large Tables Use pagination in your sync:

    $this->syncModel(User::class, [], ['limit' => 100]);
    
  • Debounce Rapid Updates Add a debounce layer for frequent updates:

    import { debounce } from 'lodash';
    
    duo.on('update', debounce(async (data) => {
      await duo.sync('users');
    }, 500));
    
  • Compress Payloads Enable payload compression in config/duo.php:

    'compress_payloads' => true,
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle