Move mode detection from Rsx_Mode to Rsx class

Simplify ajax batching to be mode-based instead of configurable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-01-14 22:33:49 +00:00
parent c83cae5a92
commit 2489997e42
13 changed files with 217 additions and 234 deletions

View File

@@ -61,4 +61,3 @@ GATEKEEPER_SUBTITLE="This is a restricted development preview site. Please enter
SSR_FPC_ENABLED=true SSR_FPC_ENABLED=true
LOG_BROWSER_ERRORS=false LOG_BROWSER_ERRORS=false
AJAX_DISABLE_BATCHING=false

View File

@@ -3,7 +3,7 @@
namespace App\RSpade\Commands\Rsx; namespace App\RSpade\Commands\Rsx;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use App\RSpade\Core\Mode\Rsx_Mode; use App\RSpade\Core\Rsx;
/** /**
* Set the application mode (development, debug, or production) * Set the application mode (development, debug, or production)
@@ -23,9 +23,9 @@ class Mode_Set_Command extends Command
// Normalize mode aliases // Normalize mode aliases
$normalized = match (strtolower($mode)) { $normalized = match (strtolower($mode)) {
'dev', 'development' => Rsx_Mode::DEVELOPMENT, 'dev', 'development' => Rsx::MODE_DEVELOPMENT,
'debug' => Rsx_Mode::DEBUG, 'debug' => Rsx::MODE_DEBUG,
'prod', 'production' => Rsx_Mode::PRODUCTION, 'prod', 'production' => Rsx::MODE_PRODUCTION,
default => null, default => null,
}; };
@@ -54,7 +54,7 @@ class Mode_Set_Command extends Command
$this->_update_env_mode($normalized); $this->_update_env_mode($normalized);
// Clear the cached mode so subsequent calls see the new value // Clear the cached mode so subsequent calls see the new value
Rsx_Mode::clear_cache(); Rsx::clear_mode_cache();
// Step 2: Clear all caches // Step 2: Clear all caches
$this->line(' [2/3] Clearing caches...'); $this->line(' [2/3] Clearing caches...');
@@ -68,7 +68,7 @@ class Mode_Set_Command extends Command
// Step 3: Build appropriate assets // Step 3: Build appropriate assets
$this->line(' [3/3] Building assets...'); $this->line(' [3/3] Building assets...');
if ($normalized === Rsx_Mode::DEVELOPMENT) { if ($normalized === Rsx::MODE_DEVELOPMENT) {
// In development, pre-warm the bundle cache // In development, pre-warm the bundle cache
// Explicitly pass RSX_MODE to ensure subprocess uses correct mode // Explicitly pass RSX_MODE to ensure subprocess uses correct mode
passthru("RSX_MODE={$normalized} php artisan rsx:bundle:compile", $exit_code); passthru("RSX_MODE={$normalized} php artisan rsx:bundle:compile", $exit_code);
@@ -100,7 +100,7 @@ class Mode_Set_Command extends Command
{ {
$env_path = base_path('.env'); $env_path = base_path('.env');
if (!file_exists($env_path)) { if (!file_exists($env_path)) {
return Rsx_Mode::DEVELOPMENT; return Rsx::MODE_DEVELOPMENT;
} }
$contents = file_get_contents($env_path); $contents = file_get_contents($env_path);
@@ -108,7 +108,7 @@ class Mode_Set_Command extends Command
return trim($matches[1]); return trim($matches[1]);
} }
return Rsx_Mode::DEVELOPMENT; return Rsx::MODE_DEVELOPMENT;
} }
/** /**

View File

@@ -5,7 +5,7 @@ namespace App\RSpade\Commands\Rsx;
use App\RSpade\Core\Bundle\BundleCompiler; use App\RSpade\Core\Bundle\BundleCompiler;
use App\RSpade\Core\Bundle\Minifier; use App\RSpade\Core\Bundle\Minifier;
use App\RSpade\Core\Manifest\Manifest; use App\RSpade\Core\Manifest\Manifest;
use App\RSpade\Core\Mode\Rsx_Mode; use App\RSpade\Core\Rsx;
use Exception; use Exception;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -25,9 +25,7 @@ class Prod_Build_Command extends Command
public function handle(): int public function handle(): int
{ {
$mode = Rsx_Mode::get(); if (Rsx::is_development()) {
if ($mode === Rsx_Mode::DEVELOPMENT) {
$this->warn('Warning: Building production assets in development mode.'); $this->warn('Warning: Building production assets in development mode.');
$this->line('Assets will be built but will not be used until you switch modes:'); $this->line('Assets will be built but will not be used until you switch modes:');
$this->line(' php artisan rsx:mode:set debug'); $this->line(' php artisan rsx:mode:set debug');
@@ -62,7 +60,7 @@ class Prod_Build_Command extends Command
$this->line('[2/3] Compiling bundles...'); $this->line('[2/3] Compiling bundles...');
// Force restart minify server to pick up any code changes // Force restart minify server to pick up any code changes
if (Rsx_Mode::is_production()) { if (Rsx::is_production()) {
Minifier::force_restart(); Minifier::force_restart();
} }
@@ -157,7 +155,7 @@ class Prod_Build_Command extends Command
$this->newLine(); $this->newLine();
$this->info("[OK] Production build complete ({$elapsed}s)"); $this->info("[OK] Production build complete ({$elapsed}s)");
if ($mode === Rsx_Mode::DEVELOPMENT) { if (Rsx::is_development()) {
$this->newLine(); $this->newLine();
$this->line('To use these assets, switch to production mode:'); $this->line('To use these assets, switch to production mode:');
$this->line(' php artisan rsx:mode:set production'); $this->line(' php artisan rsx:mode:set production');

View File

@@ -13,7 +13,7 @@ use App\RSpade\Core\Bundle\Rsx_Asset_Bundle_Abstract;
use App\RSpade\Core\Bundle\Rsx_Module_Bundle_Abstract; use App\RSpade\Core\Bundle\Rsx_Module_Bundle_Abstract;
use App\RSpade\Core\Locks\RsxLocks; use App\RSpade\Core\Locks\RsxLocks;
use App\RSpade\Core\Manifest\Manifest; use App\RSpade\Core\Manifest\Manifest;
use App\RSpade\Core\Mode\Rsx_Mode; use App\RSpade\Core\Rsx;
/** /**
* BundleCompiler - Compiles RSX bundles into JS and CSS files * BundleCompiler - Compiles RSX bundles into JS and CSS files
@@ -124,10 +124,10 @@ class BundleCompiler
public function compile(string $bundle_class, array $options = []): array public function compile(string $bundle_class, array $options = []): array
{ {
$this->bundle_name = $this->_get_bundle_name($bundle_class); $this->bundle_name = $this->_get_bundle_name($bundle_class);
$this->is_production = Rsx_Mode::is_production_like(); $this->is_production = Rsx::is_production();
$force_build = $options['force_build'] ?? false; $force_build = $options['force_build'] ?? false;
console_debug('BUNDLE', "Compiling {$this->bundle_name} (mode: " . Rsx_Mode::get() . ')'); console_debug('BUNDLE', "Compiling {$this->bundle_name} (mode: " . Rsx::get_mode() . ')');
// Step 1: In production-like modes, require pre-built bundles (unless force_build) // Step 1: In production-like modes, require pre-built bundles (unless force_build)
if ($this->is_production && !$force_build) { if ($this->is_production && !$force_build) {
@@ -443,7 +443,7 @@ class BundleCompiler
$bundle_dir = storage_path('rsx-build/bundles'); $bundle_dir = storage_path('rsx-build/bundles');
// Look for split vendor/app files (current output format) // Look for split vendor/app files (current output format)
// Future: support merged files when Rsx_Mode::should_merge_bundles() // Future: support merged files when Manifest::_should_merge_bundles()
$vendor_js_pattern = "{$bundle_dir}/{$this->bundle_name}__vendor.*.js"; $vendor_js_pattern = "{$bundle_dir}/{$this->bundle_name}__vendor.*.js";
$app_js_pattern = "{$bundle_dir}/{$this->bundle_name}__app.*.js"; $app_js_pattern = "{$bundle_dir}/{$this->bundle_name}__app.*.js";
$vendor_css_pattern = "{$bundle_dir}/{$this->bundle_name}__vendor.*.css"; $vendor_css_pattern = "{$bundle_dir}/{$this->bundle_name}__vendor.*.css";
@@ -1951,8 +1951,8 @@ implode("\n", array_map(fn ($f) => ' - ' . str_replace(base_path() . '/', '',
$js_content = $this->_compile_js_files($js_files); $js_content = $this->_compile_js_files($js_files);
// Minify JS in production mode only (strips sourcemaps) // Minify JS in strict production only (strips sourcemaps, debug keeps them)
if (Rsx_Mode::is_production()) { if (Rsx::is_production() && !Rsx::is_debug()) {
$js_content = Minifier::minify_js($js_content, "{$this->bundle_name}__{$type}.js"); $js_content = Minifier::minify_js($js_content, "{$this->bundle_name}__{$type}.js");
} }
@@ -1970,8 +1970,8 @@ implode("\n", array_map(fn ($f) => ' - ' . str_replace(base_path() . '/', '',
$css_content = $this->_compile_css_files($css_files); $css_content = $this->_compile_css_files($css_files);
// Minify CSS in production mode only (strips sourcemaps) // Minify CSS in strict production only (strips sourcemaps, debug keeps them)
if (Rsx_Mode::is_production()) { if (Rsx::is_production() && !Rsx::is_debug()) {
$css_content = Minifier::minify_css($css_content, "{$this->bundle_name}__{$type}.css"); $css_content = Minifier::minify_css($css_content, "{$this->bundle_name}__{$type}.css");
} }

View File

@@ -6,7 +6,7 @@ use RuntimeException;
use App\RSpade\CodeQuality\RuntimeChecks\BundleErrors; use App\RSpade\CodeQuality\RuntimeChecks\BundleErrors;
use App\RSpade\Core\Bundle\BundleCompiler; use App\RSpade\Core\Bundle\BundleCompiler;
use App\RSpade\Core\Manifest\Manifest; use App\RSpade\Core\Manifest\Manifest;
use App\RSpade\Core\Mode\Rsx_Mode; use App\RSpade\Core\Rsx;
use App\RSpade\Core\Session\Session; use App\RSpade\Core\Session\Session;
/** /**
@@ -128,7 +128,7 @@ abstract class Rsx_Bundle_Abstract
\App\RSpade\Core\Debug\Debugger::dump_console_debug_messages_to_html(); \App\RSpade\Core\Debug\Debugger::dump_console_debug_messages_to_html();
// In development mode, validate path coverage // In development mode, validate path coverage
if (Rsx_Mode::is_development()) { if (Rsx::is_development()) {
static::__validate_path_coverage($bundle_class); static::__validate_path_coverage($bundle_class);
} }
@@ -229,7 +229,7 @@ abstract class Rsx_Bundle_Abstract
} }
// Expect vendor/app split files (merging not yet implemented) // Expect vendor/app split files (merging not yet implemented)
// Future: check Rsx_Mode::should_merge_bundles() for combined files // Future: check Manifest::_should_merge_bundles() for combined files
if (!isset($compiled['vendor_js_bundle_path']) && if (!isset($compiled['vendor_js_bundle_path']) &&
!isset($compiled['app_js_bundle_path']) && !isset($compiled['app_js_bundle_path']) &&
!isset($compiled['vendor_css_bundle_path']) && !isset($compiled['vendor_css_bundle_path']) &&
@@ -260,16 +260,14 @@ abstract class Rsx_Bundle_Abstract
} }
// Add runtime data // Add runtime data
$rsxapp_data['debug'] = Rsx_Mode::is_development(); $rsxapp_data['debug'] = Rsx::is_development();
$rsxapp_data['current_controller'] = \App\RSpade\Core\Rsx::get_current_controller(); $rsxapp_data['current_controller'] = Rsx::get_current_controller();
$rsxapp_data['current_action'] = \App\RSpade\Core\Rsx::get_current_action(); $rsxapp_data['current_action'] = Rsx::get_current_action();
$rsxapp_data['is_auth'] = Session::is_logged_in(); $rsxapp_data['is_auth'] = Session::is_logged_in();
$rsxapp_data['is_spa'] = \App\RSpade\Core\Rsx::is_spa(); $rsxapp_data['is_spa'] = Rsx::is_spa();
// Only include ajax_disable_batching in development mode // Enable ajax batching in debug/production modes, disable in development for easier debugging
if (Rsx_Mode::is_development()) { $rsxapp_data['ajax_batching'] = !Rsx::is_development();
$rsxapp_data['ajax_disable_batching'] = config('rsx.development.ajax_disable_batching', false);
}
// Add current params (always set to reduce state variations) // Add current params (always set to reduce state variations)
$current_params = \App\RSpade\Core\Rsx::get_current_params(); $current_params = \App\RSpade\Core\Rsx::get_current_params();
@@ -301,7 +299,7 @@ abstract class Rsx_Bundle_Abstract
$rsxapp_data['user_timezone'] = \App\RSpade\Core\Time\Rsx_Time::get_user_timezone(); $rsxapp_data['user_timezone'] = \App\RSpade\Core\Time\Rsx_Time::get_user_timezone();
// Add console_debug config only in development mode // Add console_debug config only in development mode
if (Rsx_Mode::should_include_debug_info()) { if (Manifest::_should_include_debug_info()) {
$console_debug_config = config('rsx.console_debug', []); $console_debug_config = config('rsx.console_debug', []);
// Build console_debug settings // Build console_debug settings

View File

@@ -74,7 +74,8 @@ class Ajax {
/** /**
* Make an AJAX call to an RSX controller action * Make an AJAX call to an RSX controller action
* *
* All calls are automatically batched unless window.rsxapp.ajax_disable_batching is true. * Calls are batched when window.rsxapp.ajax_batching is true (debug/production modes).
* In development mode, batching is disabled for easier debugging.
* *
* @param {string|object|function} url - The Ajax URL (e.g., '/_ajax/Controller_Name/action_name') or an object/function with a .path property * @param {string|object|function} url - The Ajax URL (e.g., '/_ajax/Controller_Name/action_name') or an object/function with a .path property
* @param {object} params - Parameters to send to the action * @param {object} params - Parameters to send to the action
@@ -98,12 +99,12 @@ class Ajax {
console.log('Ajax:', controller, action, params); console.log('Ajax:', controller, action, params);
// Check if batching is disabled for debugging // Batch calls in debug/production mode, direct calls in development mode
let promise; let promise;
if (window.rsxapp && window.rsxapp.ajax_disable_batching) { if (window.rsxapp && window.rsxapp.ajax_batching) {
promise = Ajax._call_direct(controller, action, params);
} else {
promise = Ajax._call_batch(controller, action, params); promise = Ajax._call_batch(controller, action, params);
} else {
promise = Ajax._call_direct(controller, action, params);
} }
// Track this promise for unhandled rejection detection // Track this promise for unhandled rejection detection

View File

@@ -25,7 +25,7 @@ use App\RSpade\Core\Manifest\_Manifest_PHP_Reflection_Helper;
use App\RSpade\Core\Manifest\_Manifest_Quality_Helper; use App\RSpade\Core\Manifest\_Manifest_Quality_Helper;
use App\RSpade\Core\Manifest\_Manifest_Reflection_Helper; use App\RSpade\Core\Manifest\_Manifest_Reflection_Helper;
use App\RSpade\Core\Manifest\_Manifest_Scanner_Helper; use App\RSpade\Core\Manifest\_Manifest_Scanner_Helper;
use App\RSpade\Core\Mode\Rsx_Mode; use App\RSpade\Core\Rsx;
/** /**
* Manifest - RSX File Discovery and Metadata Management System * Manifest - RSX File Discovery and Metadata Management System
@@ -680,7 +680,7 @@ class Manifest
// Check both the static flag and the environment variable (set before process starts) // Check both the static flag and the environment variable (set before process starts)
// Also auto-allow for safe commands that don't need manifest (e.g., rsx:clean) // Also auto-allow for safe commands that don't need manifest (e.g., rsx:clean)
$force_build = self::$_force_build || env('RSX_FORCE_BUILD', false) || self::_is_safe_command(); $force_build = self::$_force_build || env('RSX_FORCE_BUILD', false) || self::_is_safe_command();
if (Rsx_Mode::is_production_like() && !$force_build) { if (Rsx::is_production() && !$force_build) {
if (!$loaded_cache) { if (!$loaded_cache) {
throw new \RuntimeException( throw new \RuntimeException(
'Manifest not built for production mode. Run: php artisan rsx:prod:build' 'Manifest not built for production mode. Run: php artisan rsx:prod:build'
@@ -839,6 +839,80 @@ class Manifest
static::$_needs_manifest_restart = true; static::$_needs_manifest_restart = true;
} }
// =========================================================================
// Build Mode Semantic Helpers
// =========================================================================
/**
* Check if manifest/bundles should auto-rebuild on file changes
*
* Only in development mode.
*/
public static function _should_auto_rebuild(): bool
{
return \App\RSpade\Core\Rsx::is_development();
}
/**
* Check if JS/CSS should be minified
*
* In debug and production modes.
*/
public static function _should_minify(): bool
{
return \App\RSpade\Core\Rsx::is_production();
}
/**
* Check if JS/CSS should be merged into single files
*
* Only in strict production mode (not debug - keeps files separate for debugging).
*/
public static function _should_merge_bundles(): bool
{
return \App\RSpade\Core\Rsx::is_production() && !\App\RSpade\Core\Rsx::is_debug();
}
/**
* Check if inline sourcemaps should be included
*
* In development and debug modes (not strict production).
*/
public static function _should_inline_sourcemaps(): bool
{
return \App\RSpade\Core\Rsx::is_development() || \App\RSpade\Core\Rsx::is_debug();
}
/**
* Check if CDN assets should be cached locally and bundled
*
* Only in strict production mode.
*/
public static function _should_cache_cdn(): bool
{
return \App\RSpade\Core\Rsx::is_production() && !\App\RSpade\Core\Rsx::is_debug();
}
/**
* Check if console_debug() calls should be stripped from source
*
* Only in strict production mode.
*/
public static function _should_strip_console_debug(): bool
{
return \App\RSpade\Core\Rsx::is_production() && !\App\RSpade\Core\Rsx::is_debug();
}
/**
* Check if debug info should be included in window.rsxapp
*
* Only in development mode.
*/
public static function _should_include_debug_info(): bool
{
return \App\RSpade\Core\Rsx::is_development();
}
/** /**
* Normalize class name to simple name (strip namespace qualifiers) * Normalize class name to simple name (strip namespace qualifiers)
* *

View File

@@ -4,7 +4,7 @@ namespace App\RSpade\Core\Manifest;
use App\RSpade\Core\Kernels\ManifestKernel; use App\RSpade\Core\Kernels\ManifestKernel;
use App\RSpade\Core\Manifest\Manifest; use App\RSpade\Core\Manifest\Manifest;
use App\RSpade\Core\Mode\Rsx_Mode; use App\RSpade\Core\Rsx;
/** /**
* _Manifest_Cache_Helper - Persistence, loading, and validation * _Manifest_Cache_Helper - Persistence, loading, and validation
@@ -138,8 +138,8 @@ class _Manifest_Cache_Helper
$php_content .= '// Files: ' . count(Manifest::$data['data']['files']) . "\n"; $php_content .= '// Files: ' . count(Manifest::$data['data']['files']) . "\n";
$php_content .= '// Hash: ' . Manifest::$data['hash'] . "\n\n"; $php_content .= '// Hash: ' . Manifest::$data['hash'] . "\n\n";
// Use compact format in production mode, pretty format in dev/debug // Use compact format in strict production only, pretty format in dev/debug
if (Rsx_Mode::is_production()) { if (Rsx::is_production() && !Rsx::is_debug()) {
$php_content .= 'return ' . self::_compact_var_export(Manifest::$data) . ";\n"; $php_content .= 'return ' . self::_compact_var_export(Manifest::$data) . ";\n";
} else { } else {
$php_content .= 'return ' . var_export(Manifest::$data, true) . ";\n"; $php_content .= 'return ' . var_export(Manifest::$data, true) . ";\n";

View File

@@ -1,182 +0,0 @@
<?php
namespace App\RSpade\Core\Mode;
/**
* Rsx_Mode - Centralized application mode detection
*
* RSX_MODE is the authoritative source of truth for application mode,
* taking precedence over Laravel's APP_ENV setting.
*
* Three modes:
* - development: Auto-rebuild, full debugging, sourcemaps
* - debug: Production optimizations with sourcemaps for debugging
* - production: Full optimization, minification, merging, CDN bundling
*
* @see php artisan rsx:man app_mode
*/
class Rsx_Mode
{
public const DEVELOPMENT = 'development';
public const DEBUG = 'debug';
public const PRODUCTION = 'production';
private static ?string $_cached_mode = null;
/**
* Get the current application mode
*
* @return string One of: development, debug, production
*/
public static function get(): string
{
if (self::$_cached_mode !== null) {
return self::$_cached_mode;
}
$mode = env('RSX_MODE', self::DEVELOPMENT);
// Normalize aliases
if ($mode === 'dev') {
$mode = self::DEVELOPMENT;
} elseif ($mode === 'prod') {
$mode = self::PRODUCTION;
}
// Validate
if (!in_array($mode, [self::DEVELOPMENT, self::DEBUG, self::PRODUCTION], true)) {
throw new \RuntimeException(
"Invalid RSX_MODE '{$mode}'. Must be: development, debug, or production"
);
}
self::$_cached_mode = $mode;
return $mode;
}
/**
* Check if running in development mode
*/
public static function is_development(): bool
{
return self::get() === self::DEVELOPMENT;
}
/**
* Check if running in debug mode
*/
public static function is_debug(): bool
{
return self::get() === self::DEBUG;
}
/**
* Check if running in production mode
*/
public static function is_production(): bool
{
return self::get() === self::PRODUCTION;
}
/**
* Check if running in a production-like mode (debug or production)
*
* Use this for checks that apply to both debug and production,
* such as requiring pre-built assets.
*/
public static function is_production_like(): bool
{
return self::get() !== self::DEVELOPMENT;
}
/**
* Check if manifest/bundles should auto-rebuild on file changes
*
* Only in development mode.
*/
public static function should_auto_rebuild(): bool
{
return self::is_development();
}
/**
* Check if JS/CSS should be minified
*
* In debug and production modes.
*/
public static function should_minify(): bool
{
return self::is_production_like();
}
/**
* Check if JS/CSS should be merged into single files
*
* Only in production mode (not debug - keeps files separate for debugging).
*/
public static function should_merge_bundles(): bool
{
return self::is_production();
}
/**
* Check if inline sourcemaps should be included
*
* In development and debug modes.
*/
public static function should_inline_sourcemaps(): bool
{
return !self::is_production();
}
/**
* Check if CDN assets should be cached locally and bundled
*
* Only in production mode.
*/
public static function should_cache_cdn(): bool
{
return self::is_production();
}
/**
* Check if console_debug() calls should be stripped from source
*
* Only in production mode.
*/
public static function should_strip_console_debug(): bool
{
return self::is_production();
}
/**
* Check if debug info should be included in window.rsxapp
*
* Only in development mode.
*/
public static function should_include_debug_info(): bool
{
return self::is_development();
}
/**
* Clear the cached mode (for use after .env changes)
*/
public static function clear_cache(): void
{
self::$_cached_mode = null;
}
/**
* Get human-readable mode label
*/
public static function get_label(): string
{
return match (self::get()) {
self::DEVELOPMENT => 'Development',
self::DEBUG => 'Debug',
self::PRODUCTION => 'Production',
};
}
}

View File

@@ -22,6 +22,16 @@ use App\RSpade\Core\Manifest\Manifest;
*/ */
class Rsx class Rsx
{ {
// Application mode constants
public const MODE_DEVELOPMENT = 'development';
public const MODE_DEBUG = 'debug';
public const MODE_PRODUCTION = 'production';
/**
* Cached application mode
*/
private static ?string $_cached_mode = null;
/** /**
* Current controller being executed * Current controller being executed
* @var string|null * @var string|null
@@ -106,6 +116,89 @@ class Rsx
return static::$current_route_type === 'spa'; return static::$current_route_type === 'spa';
} }
// =========================================================================
// Application Mode Detection
// =========================================================================
/**
* Get the current application mode
*
* @return string One of: development, debug, production
*/
public static function get_mode(): string
{
if (self::$_cached_mode !== null) {
return self::$_cached_mode;
}
$mode = env('RSX_MODE', self::MODE_DEVELOPMENT);
// Normalize aliases
if ($mode === 'dev') {
$mode = self::MODE_DEVELOPMENT;
} elseif ($mode === 'prod') {
$mode = self::MODE_PRODUCTION;
}
// Validate
if (!in_array($mode, [self::MODE_DEVELOPMENT, self::MODE_DEBUG, self::MODE_PRODUCTION], true)) {
throw new \RuntimeException(
"Invalid RSX_MODE '{$mode}'. Must be: development, debug, or production"
);
}
self::$_cached_mode = $mode;
return $mode;
}
/**
* Check if running in development mode
*/
public static function is_development(): bool
{
return self::get_mode() === self::MODE_DEVELOPMENT;
}
/**
* Check if running in debug mode
*/
public static function is_debug(): bool
{
return self::get_mode() === self::MODE_DEBUG;
}
/**
* Check if running in production mode (debug or production)
*
* Returns true for both debug and production modes.
* Use is_production() && !is_debug() for strictly production-only checks.
*/
public static function is_production(): bool
{
return self::get_mode() !== self::MODE_DEVELOPMENT;
}
/**
* Clear the cached mode (for use after .env changes)
*/
public static function clear_mode_cache(): void
{
self::$_cached_mode = null;
}
/**
* Get human-readable mode label
*/
public static function get_mode_label(): string
{
return match (self::get_mode()) {
self::MODE_DEVELOPMENT => 'Development',
self::MODE_DEBUG => 'Debug',
self::MODE_PRODUCTION => 'Production',
};
}
/** /**
* Clear the current controller and action tracking * Clear the current controller and action tracking
*/ */

View File

@@ -176,9 +176,12 @@ WINDOW.RSXAPP IN PRODUCTION
window.rsxapp output: window.rsxapp output:
- console_debug configuration - console_debug configuration
- ajax_disable_batching flag
- Other debug-only properties - Other debug-only properties
The ajax_batching flag is always present but mode-dependent:
- development: false (direct calls for easier debugging)
- debug/production: true (batched calls for efficiency)
Core functionality (user, site, csrf, params, etc.) remains Core functionality (user, site, csrf, params, etc.) remains
available for application code. available for application code.

View File

@@ -93,7 +93,11 @@ OBJECT STRUCTURE
console_debug Object. Console debug configuration. console_debug Object. Console debug configuration.
Controls console_debug() output filtering. Controls console_debug() output filtering.
ajax_disable_batching Boolean. When true, Ajax calls bypass batching. Mode-Dependent:
ajax_batching Boolean. When true, Ajax calls are batched.
Set automatically: true in debug/production,
false in development for easier debugging.
Optional: Optional:

View File

@@ -348,11 +348,6 @@ return [
// Show route matching details in error pages // Show route matching details in error pages
'show_route_details' => env('RSX_SHOW_ROUTE_DETAILS', env('APP_DEBUG', false)), 'show_route_details' => env('RSX_SHOW_ROUTE_DETAILS', env('APP_DEBUG', false)),
// Disable AJAX request batching for easier debugging
// When true, each Ajax.call() makes an immediate individual request
// When false (default), requests are batched using setTimeout(0)
'ajax_disable_batching' => env('AJAX_DISABLE_BATCHING', false),
], ],
/* /*