LaravelPackages.net
Acme Inc.
Toggle sidebar
snowsoft/cdn-laravel-adapter

Laravel Storage adapter for CDN Services Node.js backend

191
0
v0.06
About snowsoft/cdn-laravel-adapter

snowsoft/cdn-laravel-adapter is a Laravel package for laravel storage adapter for cdn services node.js backend. It currently has 0 GitHub stars and 191 downloads on Packagist (latest version v0.06). Install it with composer require snowsoft/cdn-laravel-adapter. Discover more Laravel packages by snowsoft or browse all Laravel packages to compare alternatives.

Last updated

CDN Services Laravel Adapter

Latest Version on Packagist Total Downloads PHP from Packagist

Laravel Storage adapter for CDN Services Node.js backend. Use CDN Services as a Laravel filesystem disk (Laravel 9, 10, 11, 12). Domain Driven Design (DDD) uyumlu yapı: Domain (value objects, port interfaces), Application (use case services), Infrastructure (HTTP gateway).

Özellikler

| Özellik | Açıklama | |--------|----------| | Storage disk | Storage::disk('cdn-services') ile put/get/delete/url, caption, tags, folder, visibility | | CdnServicesAuth | Kayıt (registration token), giriş, tokenForUser ile JWT | | Depolama kotası | QuotaExceededException, getQuotaRemaining(), usage() ile quotaBytes/quotaMB | | CdnServicesPdf | PDF yükleme, HTML'den PDF oluşturma (generateFromHtml), session ile süreli erişim, DDD (PdfDocument, PdfSession) | | CdnServicesApi | Meta, list, usage, import, placeholder, signed URL, processedUrl, Cloudflare cloudflareProcessedUrl | | CdnApi / CdnBulk | Toplu işlem: CdnApi::upload, importBatch, bulkDelete; CdnBulk::uploadMany; Artisan: cdn:bulk-upload, cdn:import-urls, cdn:bulk-delete | | CdnMinify | JS/CSS sıkıştırma (minify), publish (ledger + kalıcı asset), ledger doğrulama; DDD (MinifyPublishResult, LedgerVerification). |


DDD yapısı

| Katman | Açıklama | |--------|----------| | Domain | Domain\Pdf\PdfDocument, PdfSession (value objects); PdfStorageGatewayInterface (port). Minify: Domain\Minify\MinifyPublishResult, LedgerVerification; MinifyGatewayInterface (port). | | Application | Application\Pdf\PdfStorageService – PDF use case'leri. Minify: Application\Minify\MinifyService – minifyJs, minifyCss, publishJs, publishCss, assetUrl, verifyLedger. | | Infrastructure | Infrastructure\Http\PdfStorageGateway – backend /api/pdf/*. Minify: Infrastructure\Http\MinifyGateway – backend /api/minify/*. | | Bulk (Contracts/Services) | Contracts\CdnApiClientInterface, CdnBulkUploadServiceInterface; Services\CdnApiClient, CdnBulkUploadService; DTOs: BulkUploadResult, BatchImportResult, BulkDeleteResult. |

Bağımlılık Domain → Application → Infrastructure yönünde; uygulama PdfStorageGatewayInterface / MinifyGatewayInterface ile tip bağımlılığı kurar, implementasyon ServiceProvider'da bağlanır.

Minify (DDD)

Backend’de Minify servisi açıksa (MINIFY_SERVICE_URL), CdnMinify facade ile JS/CSS sıkıştırma, yayınlama (ledger + asset) ve ledger doğrulama kullanılır:

use CdnServices\Facades\CdnMinify;
use CdnServices\Domain\Minify\MinifyPublishResult;

// Sadece sıkıştır (kaydetmez)
$minifiedJs = CdnMinify::minifyJs($rawJs);
$minifiedCss = CdnMinify::minifyCss($rawCss);

// Yayınla: sıkıştır + ledger'a yaz + kalıcı asset URL
$result = CdnMinify::publishJs($rawJs);  // MinifyPublishResult: assetId, url, kind, size
$result = CdnMinify::publishCss($rawCss);

// Asset erişim URL'i (script/link ile kullanılır)
$url = CdnMinify::assetUrl($result->assetId);

// Ledger zincir doğrulama
$verification = CdnMinify::verifyLedger();  // LedgerVerification: valid, message, entries

if (CdnMinify::isAvailable()) {
    // Minify servisi kullanılabilir
}

Toplu işlem (DDD: CdnApi, CdnBulk, Artisan)

Servisler: CdnApiClientInterface (upload, importBatch, bulkDelete), CdnBulkUploadServiceInterface (uploadMany). Facades: CdnApi, CdnBulk (alias'ları eklemek için config/app.php veya composer extra.laravel.aliases içine CdnApiCdnServices\Facades\CdnApi, CdnBulkCdnServices\Facades\CdnBulk ekleyin).

Artisan komutları:

# Toplu dosya yükleme (dizin veya tek dosya)
php artisan cdn:bulk-upload /path/to/products --bucket=local --folder=ürünler --tags=ürün,yeni

# URL listesinden import (--file= veya argüman)
php artisan cdn:import-urls --file=urls.txt --bucket=local

# Toplu silme
php artisan cdn:bulk-delete --file=ids.txt

Kod örneği:

use CdnServices\Contracts\CdnBulkUploadServiceInterface;
use CdnServices\Facades\CdnApi;
use CdnServices\DTOs\BatchImportResult;
use CdnServices\DTOs\BulkDeleteResult;

// Toplu yükleme (controller'da inject)
$result = app(CdnBulkUploadServiceInterface::class)->uploadMany(
    ['/path/to/1.jpg', '/path/to/2.png'],
    ['bucket' => 'local', 'folder' => 'ürünler']
);
$result->uploadedIds();

// URL import
$res = CdnApi::importBatch(['https://example.com/1.jpg'], ['bucket' => 'local']);
$result = BatchImportResult::fromApiResponse($res);

// Toplu silme
$res = CdnApi::bulkDelete(['id1', 'id2']);
$result = BulkDeleteResult::fromApiResponse($res);

Requirements

  • PHP 8.0+
  • Laravel 9.x, 10.x, 11.x or 12.x
  • CDN Services Node.js backend

Installation

Install via Composer (Packagist):

composer require snowsoft/cdn-laravel-adapter

Service provider and aliases are auto-discovered. Publish config:

php artisan vendor:publish --tag=cdn-services-config

Install from GitHub (development)

Add the VCS repository to composer.json, then require the package:

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/snowsoft/cdn-laravel-adapter"
        }
    ]
}
composer require snowsoft/cdn-laravel-adapter

Manual install

  1. Clone the repo into your project (e.g. packages/cdn-laravel-adapter).
  2. Add PSR-4 autoload: "CdnServices\\": "packages/cdn-laravel-adapter/src/".
  3. Register CdnServices\CdnServicesServiceProvider in config/app.php or bootstrap/providers.php.
  4. Run php artisan vendor:publish --tag=cdn-services-config.

Configuration

Environment (.env)

CDN_SERVICES_BASE_URL=http://localhost:3012 CDN_SERVICES_TOKEN=your-jwt-token-here # Backend'de REGISTRATION_TOKEN zorunluysa; kayıt için (CdnServicesAuth::register) CDN_SERVICES_REGISTRATION_TOKEN= CDN_SERVICES_DISK=local CDN_SERVICES_DEFAULT_DISK=local CDN_SERVICES_TIMEOUT=30

Filesystem (config/filesystems.php)

'disks' => [
    // ...
    'cdn-services' => [
        'driver' => 'cdn-services',
        'base_url' => env('CDN_SERVICES_BASE_URL', 'http://localhost:3012'),
        'token' => env('CDN_SERVICES_TOKEN'),
        'disk' => env('CDN_SERVICES_DISK', 'local'),
    ],
],

Usage

Storage facade

use Illuminate\Support\Facades\Storage;

// Upload (optional: caption, tags, folder, visibility)
Storage::disk('cdn-services')->put('images/photo.jpg', $fileContents, [
    'caption' => 'Açıklama',
    'tags' => ['ürün', 'kampanya'],
    'folder' => 'galeri',
    'visibility' => 'public', // public|private|unlisted
]);

// Read, exists, delete, url, copy, move
$contents = Storage::disk('cdn-services')->get('images/photo.jpg');
$exists = Storage::disk('cdn-services')->exists('images/photo.jpg');
Storage::disk('cdn-services')->delete('images/photo.jpg');
$url = Storage::disk('cdn-services')->url('images/photo.jpg');
Storage::disk('cdn-services')->copy('images/photo.jpg', 'images/photo-copy.jpg');
Storage::disk('cdn-services')->move('images/photo.jpg', 'images/new-photo.jpg');

CdnServicesAuth – kayıt, giriş, token

Backend'de kullanıcı kaydı (registration token zorunlu olabilir), giriş ve CDN işlemleri için JWT almak:

use CdnServices\Facades\CdnServicesAuth;

// Kayıt (registration token config'ten veya 2. parametre ile)
$result = CdnServicesAuth::register([
    'email' => '[email protected]',
    'password' => 'secret123',
    'name' => 'Ad Soyad',
]);
// $result['token'] → JWT (CDN_SERVICES_TOKEN olarak kullanılabilir)
// $result['user'] → id, email, name, role, createdAt

// Giriş
$result = CdnServicesAuth::login('[email protected]', 'secret123');
if ($result) {
    $jwt = $result['token'];
}

// Sunucu tarafında bir kullanıcı için JWT üret (CDN işlemleri için)
$tokenPayload = CdnServicesAuth::tokenForUser($userId, '[email protected]', 'user');
$jwt = $tokenPayload['token'] ?? null;

// Kayıt için token zorunlu mu?
if (CdnServicesAuth::requiresRegistrationToken()) {
    // Config'te CDN_SERVICES_REGISTRATION_TOKEN tanımlı
}

CdnServices facade

use CdnServices\Facades\CdnServices;

CdnServices::put('images/photo.jpg', $fileContents);
$contents = CdnServices::get('images/photo.jpg');
$url = CdnServices::url('images/photo.jpg');

Upload with UploadedFile

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

public function upload(Request $request)
{
    $request->validate(['image' => 'required|image|max:51200']); // 50MB

    $path = Storage::disk('cdn-services')->put('images', $request->file('image'));
    return response()->json([
        'success' => true,
        'path' => $path,
        'url' => Storage::disk('cdn-services')->url($path),
    ]);
}

CdnServicesApi – meta, list, usage (kota), import, placeholder, signed URL, processed URL

use CdnServices\Facades\CdnServicesApi;

$info = CdnServicesApi::getInfo($imageId);
$images = CdnServicesApi::listImages(['tag' => 'ürün', 'favorite' => true]);
CdnServicesApi::updateMeta($imageId, ['caption' => 'Yeni başlık', 'visibility' => 'private']);
CdnServicesApi::replace($imageId, $request->file('image'));
$usage = CdnServicesApi::usage(); // fileCount, totalSize, totalSizeMB, viewCountTotal, quotaBytes?, quotaMB?
$quotaRemaining = CdnServicesApi::getQuotaRemaining(); // null if no quota
$file = CdnServicesApi::importFromUrl('https://example.com/photo.jpg');
$file = CdnServicesApi::createPlaceholder(['width' => 800, 'height' => 600, 'text' => 'Placeholder']);
$result = CdnServicesApi::bulkDelete(['id1', 'id2']);
$signed = CdnServicesApi::getSignedUrl($imageId, 3600);
$url = CdnServicesApi::processedUrl($imageId, '800x600', 'webp', [
    'quality' => 80, 'fit' => 'cover', 'filter' => 'sepia', 'crop' => 'smart', 'watermark' => true,
]);

Different backend disks (S3, Azure, etc.)

Storage::disk('cdn-services')->put('images/photo.jpg', $fileContents, ['disk' => 's3']);
Storage::disk('cdn-services')->put('images/photo.jpg', $fileContents, ['disk' => 'azure']);

Processed image URLs

$originalUrl = Storage::disk('cdn-services')->url($imageId);
$thumb = CdnServicesApi::processedUrl($imageId, 'thumbnail', 'jpeg');
$custom = CdnServicesApi::processedUrl($imageId, '800x600', 'webp', ['quality' => 75, 'watermark' => true]);

Cloudflare Image Resizing

Backend’de Cloudflare Image Resizing açıksa, edge’de resize/format/quality için URL alınır:

$url = CdnServicesApi::cloudflareProcessedUrl($imageId, '800x600', 'webp', [
    'quality' => 80, 'fit' => 'cover', 'crop' => 'smart',
]);
// Backend GET /api/image/{id}/cloudflare-url ile aynı parametreler

Detay: CDN Services docs/CLOUDFLARE_IMAGE_RESIZING.md.

CdnServicesPdf – PDF depolama (blockchain, süreli session)

Backend'de PDF_STORAGE_ENABLED=true ise kullanılır; resim alanından bağımsızdır.

use CdnServices\Facades\CdnServicesPdf;
use CdnServices\Domain\Pdf\PdfDocument;
use CdnServices\Domain\Pdf\PdfSession;

if (!CdnServicesPdf::isEnabled()) {
    return; // PDF storage kapalı
}

// Yükle (value object döner)
// Yükleme veya HTML'den oluşturma (backend'de PDF_GENERATE_SERVICE_URL gerekir)
$doc = CdnServicesPdf::upload($request->file('pdf'));
// veya: $doc = CdnServicesPdf::generateFromHtml('<html><body><h1>Rapor</h1></body></html>', 'rapor.pdf');
if ($doc instanceof PdfDocument) {
    $id = $doc->id;
}

// Listele
$documents = CdnServicesPdf::list(); // list<PdfDocument>

// Süreli erişim session'ı al
$session = CdnServicesPdf::createSession($doc->id);
if ($session instanceof PdfSession) {
    $url = CdnServicesPdf::sessionUrl($session); // GET ile PDF açılır
    // veya: $session->url(config('cdn-services.base_url'));
}

// Sil
CdnServicesPdf::delete($doc->id);

Constructor injection (DDD): Uygulama sınıflarında port kullanmak için:

use CdnServices\Domain\Pdf\PdfStorageGatewayInterface;

class MyController extends Controller
{
    public function __construct(
        private PdfStorageGatewayInterface $pdfStorage
    ) {}
}

Customization

Custom base URL: set base_url in config/filesystems.php for the cdn-services disk.

Dynamic token: in your service provider, when extending the disk, get config and call $adapter->setToken(auth()->user()->cdn_token) (or your logic) before returning the adapter.


Storage quota and exceptions

When the backend has USER_STORAGE_QUOTA_BYTES set, uploads (Storage put, API replace, importFromUrl, createPlaceholder) may return 413. The adapter throws CdnServices\Exceptions\QuotaExceededException so you can catch and show a friendly message:

use CdnServices\Exceptions\QuotaExceededException;

try {
    Storage::disk('cdn-services')->put('images/photo.jpg', $contents);
} catch (QuotaExceededException $e) {
    return back()->with('error', 'Depolama limitiniz doldu.');
}

CdnServicesApi::usage() includes quotaBytes and quotaMB when a quota is set; use getQuotaRemaining() to show remaining space.


Troubleshooting

| Problem | Check | |--------|------| | Connection refused | Backend running: curl http://localhost:3012/health | | Unauthorized | Valid JWT in CDN_SERVICES_TOKEN; create token via backend /api/auth/token | | File not found | Use image ID (not path) when calling URL/meta APIs | | QuotaExceededException | Backend USER_STORAGE_QUOTA_BYTES limit reached; free space or increase quota |


API quick reference

Storage put() options: disk, caption, tags, folder, visibility

CdnServicesAuth: register, login, tokenForUser, getRegistrationToken, requiresRegistrationToken

CdnServicesPdf (DDD): upload(UploadedFile), generateFromHtml(html, filename), list(), createSession(documentId), sessionUrl(PdfSession), delete(documentId), isEnabled()

CdnServicesApi: getInfo, listImages, updateMeta, replace, usage, getQuotaBytes, getQuotaRemaining, importFromUrl, createPlaceholder, bulkDelete, getSignedUrl, processedUrl, cloudflareProcessedUrl

Disk methods: exists, get, put, delete, copy, move, size, lastModified, mimeType, url, temporaryUrl, readStream, writeStream, files


License

MIT

Comments