PHP with Laravel

Step 1: Create Blade TemplateCopied!

Add container element in your Blade view:

<!-- resources/views/rollout.blade.php -->
@extends('layouts.app')

@section('content')
    <h1>Your Application</h1>
    <div id="rollout-container"></div>
@endsection

@section('scripts')
    <script src="{{ mix('js/rollout.js') }}"></script>
@endsection

Step 2: Add JavaScript InitializationCopied!

Create a JavaScript file in your resources folder:

// resources/js/rollout.js
document.addEventListener('DOMContentLoaded', function() {
    const container = document.getElementById('rollout-container');
    const csrfToken = document.querySelector('meta[name="csrf-token"]').content;

    fetch('/rollout-token', {
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-TOKEN': csrfToken
        }
    })
    .then(response => response.json())
    .then(data => {
        const token = data.token;
        
        // Add required styles
        const styleLink = document.createElement('link');
        styleLink.rel = 'stylesheet';
        styleLink.href = 'https://esm.sh/@rollout/[email protected]/dist/style.css';
        document.body.appendChild(styleLink);

        // Dynamically load Rollout bundle
        import(/* webpackIgnore: true */ 'https://esm.sh/@rollout/[email protected]?bundle=all').then(
            ({ RolloutLinkProvider, CredentialsManager, createElement, createRoot }) => {
                const root = createRoot(container);
                
                root.render(
                    createElement(
                        RolloutLinkProvider,
                        { token },
                        createElement(CredentialsManager)
                    )
                );
            }
        );
    });
});

Step 3: Add Laravel RoutesCopied!

Add routes to your web.php file:

// routes/web.php
use App\Http\Controllers\RolloutController;

Route::get('/rollout-token', [RolloutController::class, 'generateToken']);
Route::post('/credential-webhook', [RolloutController::class, 'handleWebhook']);

Step 4: Create ControllerCopied!

Generate a controller and implement token generation:

// app/Http/Controllers/RolloutController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Firebase\JWT\JWT;

class RolloutController extends Controller
{
    public function generateToken(Request $request)
    {
        $now = time();

        $payload = [
            'iss' => getenv('ROLLOUT_CLIENT_ID'),
            'sub' => $userId,
            'iat' => $now,
            'exp' => $now + 900 // 15 minutes
        ];

        $token = JWT::encode(
            $payload,
            config('services.rollout.client_secret'),
            'HS512'
        );

        return response()->json(['token' => $token]);
    }

    public function handleWebhook(Request $request)
    {
        $validated = $request->validate([
            'id' => 'required|string',
            'appKey' => 'required|string'
        ]);

        // Store credential logic
        \Log::info('New credential added:', $validated);
        
        return response()->json(['status' => 'success']);
    }
}

Step 5 (Optional): Handle Credential EventsCopied!

Update the JavaScript to handle events:

// Update the import block
.then(({ RolloutLinkProvider, CredentialsManager, createElement, createRoot }) => {
    const handleCredentialAdded = ({ id, appKey }) => {
        fetch('/credential-webhook', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': csrfToken
            },
            body: JSON.stringify({
                id,
                appKey
            })
        });
    };

    const root = createRoot(container);
    root.render(
        createElement(
            RolloutLinkProvider,
            { token },
            createElement(CredentialsManager, {
                onCredentialAdded: handleCredentialAdded
            })
        )
    );
});

Step 6: Config ServicesCopied!

Add to config/services.php:

'rollout' => [
    'client_secret' => env('ROLLOUT_CLIENT_SECRET'),
],

Step 7: Update CSPCopied!

Create middleware or add headers in App\Http\Middleware\TrustProxies.php:

public function handle($request, Closure $next)
{
    $response = $next($request);
    
    $response->header('Content-Security-Policy', 
        "style-src 'self' https://esm.sh; " .
        "script-src 'self' https://esm.sh; " .
        "connect-src 'self' https://universal.rollout.com"
    );

    return $response;
}