Fixed: basePath self→static binding, namespace detection, event wiring,
SQLite cache, file cache driver. All Mod Boot classes converted to
$listens pattern for lifecycle event discovery.
Working endpoints:
- /v1/explorer/info — live chain height, difficulty, aliases
- /v1/explorer/stats — formatted chain statistics
- /v1/names/directory — alias directory grouped by type
- /v1/names/available/{name} — name availability check
- /v1/names/lookup/{name} — name details
Co-Authored-By: Charon <charon@lethean.io>
198 lines
5.8 KiB
PHP
198 lines
5.8 KiB
PHP
<?php
|
|
|
|
/*
|
|
* Core PHP Framework
|
|
*
|
|
* Licensed under the European Union Public Licence (EUPL) v1.2.
|
|
* See LICENSE file for details.
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Core\Cdn\Console;
|
|
|
|
use Core\Cdn\Services\FluxCdnService;
|
|
use Core\Cdn\Services\StorageUrlResolver;
|
|
use Core\Plug\Storage\Bunny\VBucket;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\File;
|
|
|
|
class PushAssetsToCdn extends Command
|
|
{
|
|
protected $signature = 'cdn:push-assets
|
|
{--domain=host.uk.com : Workspace domain for vBucket scoping}
|
|
{--flux : Push Flux UI assets only}
|
|
{--fontawesome : Push Font Awesome assets only}
|
|
{--js : Push JavaScript assets only}
|
|
{--all : Push all static assets (default)}
|
|
{--dry-run : Show what would be uploaded without uploading}';
|
|
|
|
protected $description = 'Push static assets to CDN storage zone for edge delivery';
|
|
|
|
protected StorageUrlResolver $cdn;
|
|
|
|
/**
|
|
* VBucket instance (Core\Plug\Storage\Bunny\VBucket when available).
|
|
*/
|
|
protected ?object $vbucket = null;
|
|
|
|
protected bool $dryRun = false;
|
|
|
|
protected int $uploadCount = 0;
|
|
|
|
protected int $failCount = 0;
|
|
|
|
public function handle(FluxCdnService $flux, StorageUrlResolver $cdn): int
|
|
{
|
|
if (! class_exists(VBucket::class)) {
|
|
$this->error('Push assets to CDN requires Core\Plug\Storage\Bunny\VBucket class. Plug module not installed.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$this->cdn = $cdn;
|
|
$this->dryRun = $this->option('dry-run');
|
|
|
|
// Create vBucket for workspace isolation
|
|
$domain = $this->option('domain');
|
|
$this->vbucket = VBucket::public($domain);
|
|
|
|
$pushFlux = $this->option('flux');
|
|
$pushFontawesome = $this->option('fontawesome');
|
|
$pushJs = $this->option('js');
|
|
$pushAll = $this->option('all') || (! $pushFlux && ! $pushFontawesome && ! $pushJs);
|
|
|
|
$this->info("Pushing assets to CDN storage zone for {$domain}...");
|
|
$this->line("vBucket: {$this->vbucket->id()}");
|
|
$this->newLine();
|
|
|
|
if ($pushAll || $pushFlux) {
|
|
$this->pushFluxAssets($flux);
|
|
}
|
|
|
|
if ($pushAll || $pushFontawesome) {
|
|
$this->pushFontAwesomeAssets();
|
|
}
|
|
|
|
if ($pushAll || $pushJs) {
|
|
$this->pushJsAssets();
|
|
}
|
|
|
|
$this->newLine();
|
|
|
|
if ($this->dryRun) {
|
|
$this->info("Dry run complete. Would upload {$this->uploadCount} files.");
|
|
} else {
|
|
$this->info("Upload complete. {$this->uploadCount} files uploaded, {$this->failCount} failed.");
|
|
$this->line('CDN URL: '.config('cdn.urls.cdn'));
|
|
}
|
|
|
|
return $this->failCount > 0 ? self::FAILURE : self::SUCCESS;
|
|
}
|
|
|
|
protected function pushFluxAssets(FluxCdnService $flux): void
|
|
{
|
|
$this->components->info('Flux UI assets');
|
|
|
|
$assets = $flux->getCdnAssetPaths();
|
|
|
|
foreach ($assets as $sourcePath => $cdnPath) {
|
|
$this->uploadFile($sourcePath, $cdnPath);
|
|
}
|
|
}
|
|
|
|
protected function pushFontAwesomeAssets(): void
|
|
{
|
|
$this->components->info('Font Awesome assets');
|
|
|
|
$basePath = public_path('vendor/fontawesome');
|
|
|
|
if (! File::isDirectory($basePath)) {
|
|
$this->warn(' Font Awesome directory not found at public/vendor/fontawesome');
|
|
|
|
return;
|
|
}
|
|
|
|
// Push CSS files
|
|
$cssPath = "{$basePath}/css";
|
|
if (File::isDirectory($cssPath)) {
|
|
foreach (File::files($cssPath) as $file) {
|
|
$cdnPath = 'vendor/fontawesome/css/'.$file->getFilename();
|
|
$this->uploadFile($file->getPathname(), $cdnPath);
|
|
}
|
|
}
|
|
|
|
// Push webfonts
|
|
$webfontsPath = "{$basePath}/webfonts";
|
|
if (File::isDirectory($webfontsPath)) {
|
|
foreach (File::files($webfontsPath) as $file) {
|
|
$cdnPath = 'vendor/fontawesome/webfonts/'.$file->getFilename();
|
|
$this->uploadFile($file->getPathname(), $cdnPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function pushJsAssets(): void
|
|
{
|
|
$this->components->info('JavaScript assets');
|
|
|
|
$jsPath = public_path('js');
|
|
|
|
if (! File::isDirectory($jsPath)) {
|
|
$this->warn(' JavaScript directory not found at public/js');
|
|
|
|
return;
|
|
}
|
|
|
|
foreach (File::files($jsPath) as $file) {
|
|
if ($file->getExtension() === 'js') {
|
|
$cdnPath = 'js/'.$file->getFilename();
|
|
$this->uploadFile($file->getPathname(), $cdnPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function uploadFile(string $sourcePath, string $cdnPath): void
|
|
{
|
|
if (! file_exists($sourcePath)) {
|
|
$this->warn(" ✗ Source not found: {$sourcePath}");
|
|
$this->failCount++;
|
|
|
|
return;
|
|
}
|
|
|
|
$size = $this->formatBytes(filesize($sourcePath));
|
|
|
|
if ($this->dryRun) {
|
|
$this->line(" [DRY-RUN] {$cdnPath} ({$size})");
|
|
$this->uploadCount++;
|
|
|
|
return;
|
|
}
|
|
|
|
// Push directly to CDN storage zone via vBucket (workspace-isolated)
|
|
$contents = file_get_contents($sourcePath);
|
|
$result = $this->vbucket->putContents($cdnPath, $contents);
|
|
|
|
if ($result->isOk()) {
|
|
$this->line(" ✓ {$cdnPath} ({$size})");
|
|
$this->uploadCount++;
|
|
} else {
|
|
$this->error(" ✗ Failed: {$cdnPath}");
|
|
$this->failCount++;
|
|
}
|
|
}
|
|
|
|
protected function formatBytes(int $bytes): string
|
|
{
|
|
if ($bytes >= 1048576) {
|
|
return round($bytes / 1048576, 2).' MB';
|
|
}
|
|
|
|
if ($bytes >= 1024) {
|
|
return round($bytes / 1024, 2).' KB';
|
|
}
|
|
|
|
return $bytes.' bytes';
|
|
}
|
|
}
|