Files
rspade_system/app/RSpade/man/coding_standards.txt
root 77b4d10af8 Refactor filename naming system and apply convention-based renames
Standardize settings file naming and relocate documentation files
Fix code quality violations from rsx:check
Reorganize user_management directory into logical subdirectories
Move Quill Bundle to core and align with Tom Select pattern
Simplify Site Settings page to focus on core site information
Complete Phase 5: Multi-tenant authentication with login flow and site selection
Add route query parameter rule and synchronize filename validation logic
Fix critical bug in UpdateNpmCommand causing missing JavaScript stubs
Implement filename convention rule and resolve VS Code auto-rename conflict
Implement js-sanitizer RPC server to eliminate 900+ Node.js process spawns
Implement RPC server architecture for JavaScript parsing
WIP: Add RPC server infrastructure for JS parsing (partial implementation)
Update jqhtml terminology from destroy to stop, fix datagrid DOM preservation
Add JQHTML-CLASS-01 rule and fix redundant class names
Improve code quality rules and resolve violations
Remove legacy fatal error format in favor of unified 'fatal' error type
Filter internal keys from window.rsxapp output
Update button styling and comprehensive form/modal documentation
Add conditional fly-in animation for modals
Fix non-deterministic bundle compilation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 19:10:02 +00:00

419 lines
16 KiB
Plaintext
Executable File

NAME
coding_standards - RSX framework coding conventions and standards
SYNOPSIS
Naming conventions, code organization, and design philosophy for RSX development
DESCRIPTION
The RSX framework enforces specific coding standards to maintain consistency,
readability, and framework compatibility. These standards ensure code is
maintainable and follows the framework's architectural principles.
NAMING CONVENTIONS
Methods and Variables:
- Use underscore_case for all methods and variables
- Examples: user_name, calculate_total(), get_user_data()
Constants:
- Use UPPERCASE_WITH_UNDERSCORES
- Examples: MAX_UPLOAD_SIZE, DEFAULT_TIMEOUT
Classes in /rsx/ Directory:
- Use Like_This_With_Underscores format
- Examples: Index_Controller, User_Model, Frontend_Bundle
- Matches RSX naming patterns for auto-discovery
Classes in /system/app/RSpade/ (Framework):
- Use Like_This_With_Underscores where appropriate
- Exception: When extending Laravel classes, use Laravel's PascalCase
- Default for framework internals: PascalCase (existing Laravel convention)
Critical Rule - Case-Sensitive Files:
NEVER create files with same name but different case in same directory.
Examples to avoid: Helpers.php and helpers.php
This breaks Windows/macOS compatibility and triggers critical errors.
FILENAME CONVENTIONS
Basic Rule:
Filenames in rsx/ should match their class/ID name (case-insensitive).
Example: class Frontend_Calendar → frontend_calendar.php
Short Name Pattern (Preferred):
When directory structure provides context, filenames can use "short names"
that omit prefix parts represented by the directory path.
Requirements for valid short names:
- Class/ID must have 3+ segments (2-segment names must use full filename)
- Short name must have 2+ segments minimum
- Directory path must contain the omitted prefix parts as contiguous sequence
Algorithm: Filename is valid if [directory parts] + [filename parts] = [class parts]
Example 1 - Clean prefix removal:
Class: Frontend_Calendar_Event
Directory: rsx/app/frontend/calendar/
Valid filenames:
- calendar_event.blade.php (removes 'frontend')
- frontend_calendar_event.blade.php (full name also valid)
Example 2 - Partial overlap pattern:
Class: Frontend_Settings_Account
Directory: rsx/app/frontend/settings/account/
Valid filenames:
- settings_account.blade.php (removes 'frontend', overlaps 'settings')
- frontend_settings_account.blade.php (full name also valid)
Why settings_account is valid:
- Directory contains: [rsx, app, frontend, settings, account]
- Filename parts: [settings, account]
- Can we reconstruct class from dir + filename? YES
→ Directory has 'frontend' prefix
→ Filename 'settings_account' matches remaining parts
→ frontend + settings_account = Frontend_Settings_Account ✓
Example 3 - Too short (invalid):
Class: Frontend_Calendar
Directory: rsx/app/frontend/calendar/
Invalid: calendar.blade.php (only 1 segment - not allowed)
Required: frontend_calendar.blade.php (must use full name)
Partial Overlap Rationale:
Allows semantic redundancy when it improves clarity. In nested directories,
repeating the immediate parent directory name in the filename provides
essential context without requiring the full prefix chain.
Example benefits:
- settings/account/settings_account.php is clearer than account/account.php
- Filename alone (settings_account) indicates it's account settings
- Maintains file prefix grouping for related files
FILENAME CONVENTION EXCEPTIONS
@FILENAME-CONVENTION-EXCEPTION Marker:
Add this marker anywhere in a file to exempt it from filename matching rules.
The framework will skip all filename convention checks for that file.
Use cases:
- Legacy files being migrated that cannot be renamed yet
- Special cases that require non-standard naming
- Files with intentional naming that violates conventions
Example:
<?php
// @FILENAME-CONVENTION-EXCEPTION
// This file has a non-standard name for legacy reasons
class User_Model { ... }
Note: File must contain this exact text (case-sensitive) anywhere in contents.
AUTOMATIC FILE RENAMING (DEVELOPMENT)
Configuration (config/rsx.php):
'development' => [
// Auto-rename files to match RSX naming conventions
'auto_rename_files' => false, // Set to true to enable
// Globally disable all filename convention checks
'ignore_filename_convention' => false, // Set to true to disable
]
Auto-Rename Behavior (auto_rename_files = true):
- During manifest build, files in ./rsx are automatically renamed
- Only renames if target filename doesn't already exist
- Manifest rebuilds after rename to reflect new file paths
- Files with @FILENAME-CONVENTION-EXCEPTION are never renamed
Examples of auto-renaming:
- TestComponent1.jqhtml → test_component_1.jqhtml
- UserController.php → user_controller.php
- MyView.blade.php → my_view.blade.php
If target exists: Normal violation thrown (conflict detected)
Global Disable (ignore_filename_convention = true):
- Disables ALL filename convention checks
- No violations thrown for any files
- Useful for projects with existing non-standard naming
- More aggressive than @FILENAME-CONVENTION-EXCEPTION marker
RSPADE FRAMEWORK INTERNAL METHOD NAMING
For files in /system/app/RSpade/ only:
Private and Protected Methods:
- MUST start with underscore: _internal_method()
- Purpose: Immediately identifies framework-internal methods
- Application code prohibition: Never call methods starting with _
Public API Methods:
- Must NOT start with underscore
- These are stable public API for applications
- Safe for RSX applications to use
Example:
// In /system/app/RSpade/Core/Something.php
public static function public_api_method() { } // OK for apps
private static function _internal_helper() { } // Framework only
protected static function _process_data() { } // Framework only
Rationale:
- Methods starting with _ may change without notice in updates
- Clear separation between stable API and internal implementation
- Prevents applications from depending on internal methods
CLASS DESIGN PHILOSOPHY
Static by Default:
- All classes should be static unless specific reason to instantiate
- Classes are namespacing tools, not OOP for the sake of OOP
- Direct access from anywhere without instantiation
Exceptions for Instances:
- ORM/Model records (represent database rows)
- Resource handles (file handles, connections)
- Service connectors needing mocking (AWS, payment gateways)
- Artisan commands
Avoid Dependency Injection:
- No DI patterns or factory classes
- Exception: Service connectors that need mocking for tests
- Utility classes, helpers, managers, processors should be static
STRING MANIPULATION PHILOSOPHY
For Source Code Analysis: NO REGEX
- Never use regex to parse PHP, JavaScript, or any programming language
- Why regex fails for source code:
* Cannot distinguish code from comments
* Cannot understand syntactic context (strings, blocks, nesting)
* Breaks when code formatting changes
* Creates unmaintainable parsing logic
- Use AST parsers instead: Extend PHP/JS AST functionality in manifest
system to generate metadata for runtime analysis
For General String Operations: Prefer Verbose Clarity
- Default approach: Use explicit string functions over regex
- Prefer readable multi-line operations:
// ✅ GOOD - Clear and maintainable
$parts = explode('/', $path);
$filename = end($parts);
$extension = substr($filename, strrpos($filename, '.') + 1);
// ❌ AVOID - Unreadable regex
preg_match('/\/([^\/]+)\.([^.]+)$/', $path, $matches);
When Simple Regex IS Appropriate:
- Well-established validation patterns using proven libraries
- Very simple matching: single character classes, basic patterns
- Performance-critical operations where regex proven faster AND simple
Implementation Process:
1. Always propose solution to user first before implementing regex
2. Justify why string functions aren't sufficient
3. Document regex purpose in plain English
4. Prefer library solutions over custom regex patterns
Source Code Analysis Guidelines:
- Extend manifest AST parsers to capture needed metadata
- Add metadata to manifest cache for runtime analysis
- Use reflection and AST data instead of pattern matching
- Consult user before any source code parsing implementation
FUNCTION ORGANIZATION PHILOSOPHY
Prefer Inline Code with Comments:
- Comment above a few lines better than separate methods
- Readability from clear comments and logical flow
- Not arbitrary function boundaries
Long Functions Are Acceptable:
- When steps are sequential and single-purpose
- Clear comments explain the flow
- Related logic stays together
Create Sub-Functions Only When:
- Code called from multiple places or multiple times
- Operation is significantly complex logical subset
- Code needs independent unit testing
- Abstraction genuinely improves understanding
Avoid Functions for the Sake of Functions:
- Don't create method to wrap file_get_contents($file)
- Don't split sequential operations arbitrarily
- Goal: Keep related logic together, not create maze of methods
Sequential Operations Belong Together:
- If step B always follows step A, same function with comments
- Not arbitrarily split across multiple methods
FILE STRUCTURE RESTRICTIONS
PHP Files Without Classes (in ./rsx directory):
PHP utility files without classes may only contain at global scope:
- Function definitions
- define() calls for constants
- namespace declarations
- use statements
- declare() directives
- Comments
NOT allowed at global scope:
- Control structures (if, for, while, switch)
- Function calls (except define())
- Variable assignments
- Object instantiation (new)
- Include/require statements
- Echo/print statements
- Exit/die statements
Rationale: Classless files are loaded on every request and should
only define functions/constants, not execute code. Code that runs
on every request should be in Main::init(), pre_dispatch() methods,
or implemented in Laravel outside RSX.
Example Valid PHP Utility File:
<?php
namespace App\Utils;
use App\Models\User;
declare(strict_types=1);
define('MAX_LENGTH', 255);
function format_name(string $name): string {
return ucfirst(trim($name)); // Any code allowed inside functions
}
PHP Files With Classes (in ./rsx directory):
PHP files with classes may only contain at global scope:
- namespace declarations
- use statements
- Comments
- include/require statements with path restrictions:
* Allowed: paths not starting with rsx/
* Allowed: paths containing /resource/
* NOT allowed: paths starting with rsx/ without /resource/
NOT allowed at global scope:
- Function definitions
- define() calls for constants
Example Valid PHP Class File:
<?php
namespace Rsx\App;
use App\Models\User;
require_once 'vendor/autoload.php'; // OK
include 'rsx/app/resource/config.php'; // OK - has /resource/
class MyClass {
// Class implementation
}
JavaScript Files Without Classes:
JavaScript utility files without ES6 classes may only contain:
- Function declarations (standard or arrow)
- Const variables with static values (no function calls)
- Functions marked with @decorator
Static values include:
- Literals (strings, numbers, booleans, null)
- Binary/unary expressions (e.g., 3 * 365)
- Static arrays and objects with literal values
Example Valid JavaScript Utility File:
// Valid constants - static values only
const DAYS_IN_YEAR = 365;
const MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
// Valid function
function formatName(name) {
return name.trim().toUpperCase();
}
// Invalid - function call at global scope
const timestamp = Date.now(); // NOT ALLOWED
Enforcement:
- Validated at manifest build time
- Clear error messages with line numbers
- Build fails on violations
- Ensures clean, predictable code structure
TEMPORARY FILES CONVENTION
Always Suffix with -temp:
- Pattern: filename-temp.extension
- Examples: test-temp.php, debug-script-temp.js, migration-fix-temp.sql
Applies To:
- One-off scripts
- Test files not part of test suite
- Temporary implementations or workarounds
- Debug utilities
- Any file that should be removed later
Rules:
- Purpose: Easy identification of files needing cleanup
- Never commit -temp files unless explicitly requested
- Helps prevent temporary code from becoming permanent
ROUTING RULES
Restricted HTTP Methods:
- Only GET and POST methods allowed
- PUT, PATCH, DELETE, OPTIONS throw exceptions
- Keeps routing simple and explicit
No Resource Routes:
- Route::resource() and Route::apiResource() throw exceptions
- Explicit route definitions only
- Each route defined individually for clarity
GIT WORKFLOW
Staging:
- Always use: git add -A
- Never selective staging
- Ensures all changes are included
Submodules:
- Located in /internal-libs/
- Examples: jqhtml, rsx-scss-lint
EXAMPLES
Correct Naming:
class User_Profile_Controller {
public static function show_profile(Request $request) {
$user_data = static::_get_user_info($request->user_id);
return view('profile', compact('user_data'));
}
private static function _get_user_info($user_id) {
// Framework internal method
}
}
String Processing:
// Preferred approach
$parts = explode('/', $path);
$filename = end($parts);
$extension = substr($filename, strrpos($filename, '.') + 1);
// Avoid unless necessary
preg_match('/\/([^\/]+)\.([^.]+)$/', $path, $matches);
Function Organization:
// Good: Related steps together with comments
public static function process_upload($file) {
// Validate file type and size
if (!in_array($file->extension(), ['jpg', 'png'])) {
throw new Exception('Invalid file type');
}
// Generate unique filename
$filename = uniqid() . '.' . $file->extension();
// Store file and create database record
$path = $file->storeAs('uploads', $filename);
Upload_Model::create(['filename' => $filename, 'path' => $path]);
return $filename;
}
SEE ALSO
error_handling - Error handling patterns and shouldnt_happen()
config_rsx - Framework configuration standards