Fix bin/publish: copy docs.dist from project root

Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-10-21 02:08:33 +00:00
commit f6fac6c4bc
79758 changed files with 10547827 additions and 0 deletions

1308
app/RSpade/Core/Debug/Debugger.php Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
<?php
namespace App\RSpade\Core\Debug;
use Illuminate\Http\Request;
use App\RSpade\Core\Controller\Rsx_Controller_Abstract;
use App\RSpade\Core\Debug\Debugger;
/**
* Debugger_Controller - API endpoints for debugging features
*
* Handles AJAX requests from JavaScript for console_debug and error logging.
* Delegates to the Debugger utility class for actual implementation.
*/
class Debugger_Controller extends Rsx_Controller_Abstract
{
/**
* Ajax endpoint to log console_debug messages from JavaScript
*
* @param \Illuminate\Http\Request $request
* @param array $params
* @return array
*/
#[Ajax_Endpoint]
public static function log_console_messages(Request $request, array $params = []): array
{
return Debugger::log_console_messages($request, $params);
}
/**
* Ajax endpoint to log browser errors from JavaScript
*
* @param \Illuminate\Http\Request $request
* @param array $params
* @return array
*/
#[Ajax_Endpoint]
public static function log_browser_errors(Request $request, array $params = []): array
{
return Debugger::log_browser_errors($request, $params);
}
}

View File

@@ -0,0 +1,143 @@
<?php
/**
* CODING CONVENTION:
* This file follows the coding convention where variable_names and function_names
* use snake_case (underscore_wherever_possible).
*/
namespace App\RSpade\Core\Debug;
use Illuminate\Http\Request;
use Log;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
use App\RSpade\Core\Debug\Debugger;
use App\RSpade\Core\Dispatch\Dispatcher;
use App\RSpade\Core\Exceptions\Rsx_Exception_Handler_Abstract;
/**
* Playwright_ExceptionHandler - Handle exceptions during Playwright test execution
*
* PRIORITY: 30
*
* This handler processes exceptions when the request is from a Playwright test
* (identified by X-Playwright-Test header). It provides plain text error output
* suitable for automated testing, including:
* - Error message, file, and line
* - Stack trace (last 10 calls)
* - Console debug messages (if enabled)
* - Special 404 handling (tries RSX dispatch first)
*
* This handler only runs in non-production environments for security.
*/
class Playwright_Exception_Handler extends Rsx_Exception_Handler_Abstract
{
/**
* Get priority - Playwright handlers run after AJAX but before general web
*
* @return int
*/
public static function get_priority(): int
{
return 30;
}
/**
* Handle exception if request is from Playwright test
*
* @param Throwable $e
* @param Request $request
* @return mixed Plain text response if Playwright request, null otherwise
*/
public function handle(Throwable $e, Request $request)
{
// Only process Playwright test requests in non-production environments
if (app()->environment('production') || !$request->header('X-Playwright-Test')) {
return null;
}
Log::debug('Exception handler triggered for Playwright test, exception: ' . get_class($e));
console_debug('DISPATCH', 'Exception handler triggered for Playwright test, exception:', get_class($e));
// Special handling for 404s - check RSX routes first
if ($e instanceof NotFoundHttpException) {
// Get the requested path
$path = '/' . ltrim($request->path(), '/');
Log::debug("Exception handler: attempting RSX dispatch for path: $path");
console_debug('DISPATCH', 'Exception handler: attempting RSX dispatch for', $path);
// Try RSX dispatch
$response = Dispatcher::dispatch($path, $request->method(), [], $request);
Log::debug('RSX dispatch returned: ' . ($response ? 'response' : 'null'));
// If RSX found a route, return the response
if ($response !== null) {
return $response;
}
// No RSX route found - return 404 as plain text
return response('404 Not Found', 404)
->header('Content-Type', 'text/plain');
}
// Build error output
$error_output = 'Error: ' . $e->getMessage() . "\n";
$error_output .= 'File: ' . $e->getFile() . "\n";
$error_output .= 'Line: ' . $e->getLine() . "\n";
$error_output .= "\n";
$error_output .= "Stack Trace (last 10 calls):\n";
// Get stack trace
$trace = $e->getTrace();
$count = 0;
foreach ($trace as $frame) {
if ($count >= 10) {
break;
}
$file = $frame['file'] ?? 'unknown';
$line = $frame['line'] ?? 0;
$function = $frame['function'] ?? 'unknown';
$class = $frame['class'] ?? '';
$type = $frame['type'] ?? '';
if ($class) {
$function = $class . $type . $function;
}
$error_output .= sprintf(
" #%d %s:%d %s()\n",
$count,
$file,
$line,
$function
);
$count++;
}
// Output console debug messages if enabled
$show_console = env('SHOW_CONSOLE_DEBUG_HTTP', true) ||
(isset($_SERVER['HTTP_X_PLAYWRIGHT_CONSOLE_DEBUG']) && $_SERVER['HTTP_X_PLAYWRIGHT_CONSOLE_DEBUG'] === '1');
if (!app()->environment('production') && $show_console) {
$console_messages = Debugger::_get_console_messages();
if (!empty($console_messages)) {
$error_output .= "\nConsole Debug Messages:\n";
foreach ($console_messages as $message) {
// Messages are now arrays with 'message' key
if (is_array($message) && isset($message['message'])) {
$error_output .= ' ' . $message['message'] . "\n";
} elseif (is_string($message)) {
$error_output .= ' ' . $message . "\n";
}
}
}
}
// Return plain text response
return response($error_output, 500)
->header('Content-Type', 'text/plain');
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace App\RSpade\Core\Debug;
use RuntimeException;
use Throwable;
/**
* Exception that reports error location from the caller's perspective
*
* Automatically walks back the stack trace to show the error at the calling code's location
* instead of where the exception was thrown. Useful for utility methods that validate inputs
* and want errors to point to the caller's location.
*
* Common use cases:
* - Rsx::Route() when controller class doesn't exist - show the blade template line
* - Validation helpers that want to show caller's code as error source
* - Any utility method where the bug is in the caller's usage, not the utility itself
*
* Example:
* ```php
* // In Rsx.php
* throw new Rsx_Caller_Exception("Class {$class_name} not found in manifest");
* // Error shows: frontend_layout.blade.php:23 instead of Rsx.php:242
* ```
*/
#[Instantiatable]
class Rsx_Caller_Exception extends RuntimeException
{
/**
* Create a new Rsx_Caller_Exception
*
* Automatically determines the caller's file and line by walking back the stack trace.
* By default, goes back 1 frame (immediate caller). Increase $frames_back for deeper utilities.
*
* @param string $message The detailed error message
* @param int $frames_back Number of stack frames to walk back (default: 1 = immediate caller)
* @param int $code Optional error code (default: 0)
* @param Throwable|null $previous Optional previous exception for chaining
*/
public function __construct(string $message = '', int $frames_back = 1, int $code = 0, ?Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
// Get the stack trace to find the caller
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, $frames_back + 2);
// Walk back to the desired frame
// Frame 0 is this constructor
// Frame 1 is the immediate caller (default)
// Frame 2+ is deeper callers
$target_frame = $trace[$frames_back] ?? null;
if ($target_frame !== null) {
// Override file and line to point to the caller
if (isset($target_frame['file'])) {
$this->file = $target_frame['file'];
}
if (isset($target_frame['line'])) {
$this->line = $target_frame['line'];
}
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace App\RSpade\Core\Debug;
use RuntimeException;
use Throwable;
/**
* Exception for errors at a specific file and line number
*
* Used to represent errors that occur at a specific file location different
* from where the exception is thrown. Common use cases:
* - Syntax errors detected in custom parsers/linters
* - Template compilation errors pointing to template files
* - Configuration file validation errors
* - Any custom validation where the error location differs from detection location
*
* The file and line parameters override the exception's built-in file/line tracking,
* allowing error handlers (like Ignition) to show the correct file preview.
*/
#[Instantiatable]
class Rsx_File_Exception extends RuntimeException
{
/**
* Create a new Rsx_File_Exception
*
* @param string $message The detailed error message
* @param int $code Optional error code (default: 0)
* @param Throwable|null $previous Optional previous exception for chaining
* @param string|null $file Optional file path to show as the error source
* @param int|null $line Optional line number to show as the error source
*/
public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null, ?string $file = null, ?int $line = null)
{
parent::__construct($message, $code, $previous);
// Override the file and line if provided
if ($file !== null) {
$this->file = $file;
}
if ($line !== null) {
$this->line = $line;
}
}
}