Improve Jqhtml_Integration.js documentation with hydration system explanation Add jqhtml-laravel integration packages for traditional Laravel projects 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
Executable File
Manifest System - Developer Documentation
This documentation is for developers working on Manifest.php itself. For usage documentation, see the man pages via php artisan rsx:man manifest_api.
CRITICAL: Testing Manifest.php Changes
When modifying Manifest.php, you MUST run php artisan rsx:manifest:build --clean to test your changes.
The --clean flag performs both rsx:clean and a full manifest rebuild, ensuring your modifications are properly tested. Without this, the manifest may use cached or partially-built data that doesn't reflect your changes.
Architecture Overview
The Manifest is a compiled cache of all file metadata in the RSX application, stored at storage/rsx-build/manifest_data.php. It replaces Laravel's scattered discovery mechanisms with a unified system that enables path-agnostic class loading.
Core Data Structure
The manifest cache contains:
[
'generated' => '2025-09-28 05:02:15',
'hash' => '42b9d0efb5c547eec0fb2ca19bf922e0',
'data' => [
'files' => [...], // All indexed files with metadata
'js_classes' => [...], // JavaScript class map
'php_classes' => [...], // PHP class map
'autoloader_class_map' => [...], // Simple name to FQCN mapping
'models' => [...], // Database model metadata
'jqhtml' => [...] // jqhtml component registry
]
]
Schema Discovery Tool
Use php artisan rsx:manifest:schema_dump to inspect the manifest structure:
# Pretty-printed JSON for human reading
php artisan rsx:manifest:schema_dump
# Compact JSON for LLM parsing (saves tokens)
php artisan rsx:manifest:schema_dump --no-pretty-print
This tool deduplicates array structures, showing unique patterns with example values. Essential for understanding the actual data structure when writing code that directly accesses manifest data.
6-Phase Build Process
The build process in Manifest.php follows these phases:
Phase 1: File Discovery (__discover_files)
- Scans directories from
config('rsx.manifest.scan_directories') - Default:
['rsx', 'app/RSpade/Core/Js', 'app/RSpade/Core/Manifest/Modules'] - Excludes: vendor/, node_modules/, .git/, storage/, public/
- Returns array of file paths with basic stats (mtime, size)
Phase 2: Token Parsing (__extract_basic_metadata)
- Uses
token_get_all()for fast PHP parsing without loading - Extracts: namespace, class name, extends, implements
- Normalizes all class references to simple names (strips namespace qualifiers)
- Builds dependency graph for loading order
Phase 3: Dependency Loading (__load_changed_php_files)
- Loads PHP files in dependency order (parents before children)
- Uses
_load_class_hierarchy()to ensure parent classes exist - Critical for reflection to work properly
Phase 4: Reflection & Module Processing (__process_with_modules)
- Runs registered ManifestModule processors
- Core processors:
Php_ManifestModule: Extracts attributes, methods via reflectionBlade_ManifestModule: Parses Blade directivesJavascript_ManifestModule: Parses JS classes/methodsModel_ManifestSupport: Adds database schema to models
- Stores ALL attributes without validation (agnostic extraction)
Phase 5: Stub Generation (__generate_js_stubs, __generate_model_stubs)
- Creates JavaScript stub classes for:
- Controllers with
Ajax_Endpointmethods →storage/rsx-build/js-stubs/ - Models with
fetch()methods →storage/rsx-build/js-model-stubs/
- Controllers with
- Enables clean JavaScript API calls without manual Ajax wiring
Phase 6: Cache Writing (__write_manifest_cache)
- Serializes to PHP array format
- Writes to
storage/rsx-build/manifest_data.php - Uses
var_export()for fastinclude()loading
Key Implementation Details
Class Name Normalization Philosophy
CRITICAL: RSX enforces unique simple class names across the entire codebase. This architectural constraint allows the manifest to normalize ALL class references to simple names, eliminating an entire class of bugs related to namespace format variations.
The Problem: PHP allows multiple ways to reference classes:
\Rsx\Lib\DataGrid(leading backslash)Rsx\Lib\DataGrid(no leading backslash)DataGrid(simple name)
The Solution: Manifest::_normalize_class_name() strips namespace qualifiers:
public static function _normalize_class_name(string $class_name): string
{
// Strip leading backslash
$class_name = ltrim($class_name, '\\');
// Extract just the class name (last part after final backslash)
$parts = explode('\\', $class_name);
return end($parts);
}
Applied At:
- Token parsing -
Php_Parser::__extract_class_info()normalizesextendsat extraction - Parent lookups -
Manifest::_load_class_hierarchy()normalizes before comparison - All class name operations - Any code comparing class names uses normalization
Why This Works: RSX's unique simple class name enforcement means we only need FQCNs at actual include_once time. Throughout the manifest, simple names are sufficient and eliminate format inconsistencies.
Bug This Fixes: Previously, extends \Rsx\Lib\DataGrid (with leading \ from token parser) failed to match stored FQCN Rsx\Lib\DataGrid, causing parent class resolution failures.
Static State Management
The Manifest uses static properties for singleton behavior:
private static $_manifest = null; // Cached manifest data
private static $_is_initialized = false; // Initialization flag
private static $_manifest_loaded_at = null; // Load timestamp
Public API Methods
Initialization & Loading
init()- Ensures manifest is loaded (auto-rebuilds in dev mode)get_full_manifest()- Returns complete manifest structure with metadataclear()- Clears the in-memory cache
File Lookups
get_all()- Returns all files arrayget_file($path)- Get specific file metadata (throws if not found)get_files_by_dir($dir)- Get all files in directory
PHP Class Resolution
php_find_class($name)- Find by simple class namefind_php_fqcn($fqcn)- Find by fully qualified namephp_get_metadata_by_class($name)- Get metadata by class namephp_get_metadata_by_fqcn($fqcn)- Get metadata by FQCNphp_get_extending($parent)- Find all concrete classes extending parent (filters out abstract)php_is_subclass_of($sub, $super)- Check inheritance
JavaScript Class Resolution
js_find_class($name)- Find JavaScript class filejs_get_extending($parent)- Find extending JS classesjs_is_subclass_of($sub, $super)- Check JS inheritance
View Resolution
find_view($id)- Find by dot notation (e.g., 'frontend.index')find_view_by_rsx_id($id)- Find by @rsx_id value
Attribute & Route Discovery
get_with_attribute($attr)- Find all files with specific attributeget_routes()- Extract all route definitions from attributes
Utility Methods
get_build_key()- Get manifest hash for cache validationget_stats()- Get statistics (file counts, build time)get_autoloader_class_map()- Get class-to-file mappingsis_built()- Check if manifest exists_normalize_class_name($class_name)- Strip namespace qualifiers to get simple name
Attribute Extraction Philosophy
The manifest practices agnostic attribute extraction:
- No Validation - Stores all attributes without checking validity
- No Instantiation - Never creates attribute objects
- No Class Loading - Attributes don't need backing classes
- Raw Storage - Stores exactly what reflection provides
Example from _extract_php_metadata:
foreach ($method->getAttributes() as $attribute) {
$attributes[] = [
'name' => $attribute->getName(),
'arguments' => $attribute->getArguments()
];
}
Change Detection
Files are tracked by:
mtime- Modification time (primary)size- File size in bytes (secondary)hash- SHA1, only computed when mtime/size change
The __refresh_manifest() method compares these to detect changes.
Error Handling
All lookup methods throw RuntimeException when items not found:
if (!isset(self::$_manifest['data']['php_classes'][$class_name])) {
throw new RuntimeException("PHP class not found in manifest: {$class_name}");
}
This ensures fail-fast behavior - no silent failures.
Module System
Built-in Modules
Located in /app/RSpade/Core/Manifest/Modules/:
Php_ManifestModule- PHP reflection and attribute extractionBlade_ManifestModule- Blade directive parsingJavascript_ManifestModule- JS class/method extractionScss_ManifestModule- SCSS metadataModel_ManifestSupport- Database schema extractionJqhtml_ManifestSupport- jqhtml component registration
Creating Custom Modules
Implement the ManifestModule interface:
interface ManifestModule {
function get_name(): string;
function get_extensions(): array; // File extensions to handle
function process(string $file, array $metadata): array;
function post_process(array $manifest): void;
}
Register in config/rsx.php:
'manifest' => [
'modules' => [
App\MyModule::class
]
]
Performance Considerations
Caching Strategy
- Development: Auto-rebuilds via
__refresh_manifest()on file changes - Production: Manual rebuild required, loads from cache file
- Memory: Full manifest kept in static variable after first load
Optimization Points
- Token parsing avoids loading PHP files unnecessarily
- Dependency ordering minimizes class loading failures
- SHA1 hashing only when size/mtime indicate changes
var_export()format allows fast PHPinclude()
Common Issues & Solutions
Issue: "Class not found" during reflection
Cause: Parent class not loaded before child
Solution: Check _load_class_hierarchy() is working correctly
Issue: Parent class not found (extends mismatch)
Cause: Namespace format variations in extends declarations (e.g., \Rsx\Lib\DataGrid vs Rsx\Lib\DataGrid)
Solution: Use Manifest::_normalize_class_name() to strip namespace qualifiers before comparison
Fixed In: Version with class name normalization (2025-10-10)
Issue: Attributes not appearing in manifest
Cause: Method not public static Solution: Only public static methods are indexed
Issue: Manifest not updating
Cause: In production mode or file timestamps unchanged
Solution: Run php artisan rsx:manifest:build --force
Issue: JavaScript stubs not generating
Cause: Missing Ajax_Endpoint attribute or method not public static
Solution: Check method has attribute and correct visibility
Code Quality Integration
The manifest integrates with code quality checks via metadata storage. Rules that run during manifest scan store violations in code_quality_metadata field for each file.
Debugging
Enable verbose output:
Manifest::$_debug_options['verbose'] = true;
Or via command:
php artisan rsx:manifest:build --verbose
Testing Considerations
When testing manifest functionality:
- Use
Manifest::clear()between tests to reset state - Mock file system for predictable test data
- Test both scan() and rebuild() paths
- Verify exception throwing for not-found cases
- Check stub generation for API methods
Important Constants & Paths
- Cache file:
storage/rsx-build/manifest_data.php - JS stubs:
storage/rsx-build/js-stubs/ - Model stubs:
storage/rsx-build/js-model-stubs/ - Default scan dirs:
['rsx', 'app/RSpade/Core/Js', 'app/RSpade/Core/Manifest/Modules']
Direct Data Access
When bypassing helper methods to access manifest data directly:
$manifest = Manifest::get_full_manifest();
// Access files
$file_data = $manifest['data']['files']['path/to/file.php'];
// Access class maps
$class_file = $manifest['data']['php_classes']['ClassName'];
$js_class = $manifest['data']['js_classes']['JsClass'];
// Access models with schema
$model = $manifest['data']['models']['User_Model'];
$columns = $model['columns'];
Use rsx:manifest:schema_dump to understand the exact structure before writing direct access code.