RunContext refactor + sync updates

This commit is contained in:
Joe 2026-01-30 08:12:04 -06:00
parent c7cddb72c2
commit d3cc11659a
79 changed files with 1415 additions and 626 deletions

View file

@ -0,0 +1,272 @@
---
name: Script Naming Refactor
overview: Remove the `emitLegacyScripts` option entirely and implement a new, deterministic script naming convention where each script type has exactly one file extension. Add period encoding to the Windows encoding system and default that setting to true.
todos:
- id: path-encoding
content: Add %DOT% to CHAR_ENCODINGS, add %% escape for literal %, default encoding to true
status: completed
- id: middleware-enum
content: Add LocalScript, LegacyScript, LocalScriptDir, LegacyScriptDir middleware variants
status: completed
- id: script-type
content: Simplify ScriptType enum and update snapshot_lua logic
status: completed
- id: sync-rules
content: Add .local.lua/.luau and .legacy.lua/.luau sync rules and init paths
status: completed
- id: remove-emit-legacy
content: Remove emitLegacyScripts from Project, InstanceContext, and all usages
status: completed
- id: syncback-runcontext
content: Update get_best_middleware to check RunContext for Script class
status: completed
- id: file-extensions
content: Update extension_for_middleware with new script types
status: completed
- id: meta-suffixes
content: Add .local and .legacy to meta file suffix stripping
status: completed
- id: web-api
content: Update web/api.rs for new script naming conventions
status: completed
- id: update-tests
content: Update snapshot files and test cases
status: completed
isProject: false
---
# Script Naming Convention Refactor
## New File Extension Mapping
| Script Type | File Extension |
| -------------------------- | -------------- |
| Script (RunContext.Server) | `.server.luau` |
| Script (RunContext.Client) | `.client.luau` |
| Script (RunContext.Plugin) | `.plugin.luau` |
| Script (RunContext.Legacy) | `.legacy.luau` |
| LocalScript | `.local.luau` |
| ModuleScript | `.luau` |
## Key Changes
### 1. Add Period Encoding, Percent Escaping, and Default to True
Update `[src/path_encoding.rs](src/path_encoding.rs)`:
1. Add `(".", "%DOT%")` to `CHAR_ENCODINGS`
2. Add `%%` as escape sequence for literal `%` (encode first, decode last)
```rust
const CHAR_ENCODINGS: &[(&str, &str)] = &[
(".", "%DOT%"), // NEW
("<", "%LT%"),
// ... rest unchanged
];
pub fn encode_path_name(name: &str) -> String {
// ... handle leading/trailing spaces ...
// FIRST: Escape existing % as %% (before adding new % signs)
let mut encoded_middle = middle.replace("%", "%%");
// THEN: Encode special characters (which add new % signs)
for (char, encoded) in CHAR_ENCODINGS {
encoded_middle = encoded_middle.replace(char, encoded);
}
// ...
}
pub fn decode_path_name(name: &str) -> String {
// ...
// FIRST: Decode %NAME% patterns
for (char, encoded) in CHAR_ENCODINGS {
result = result.replace(encoded, char);
}
// LAST: Unescape %% back to %
result = result.replace("%%", "%");
// ...
}
```
This ensures round-tripping works correctly:
- `My%DOT%Thing` encodes to `My%%DOT%%Thing`, decodes back to `My%DOT%Thing`
- `My.Thing` encodes to `My%DOT%Thing`, decodes back to `My.Thing`
Change the default for `encode_windows_invalid_chars` to `true` in `[src/syncback/mod.rs](src/syncback/mod.rs)` `SyncbackRules::encode_windows_invalid_chars()`:
```rust
pub fn encode_windows_invalid_chars(&self) -> bool {
self.encode_windows_invalid_chars.unwrap_or(true) // Changed from false to true
}
```
Also update the `decode_windows_invalid_chars` logic in `[src/serve_session.rs](src/serve_session.rs)` to default to `true`.
### 2. Add New Middleware Variants
In `[src/snapshot_middleware/mod.rs](src/snapshot_middleware/mod.rs)`, add new variants:
- `LocalScript` - for `.local.lua/.luau` files (LocalScript class)
- `LegacyScript` - for `.legacy.lua/.luau` files (Script with RunContext.Legacy)
- `LocalScriptDir` - for `init.local.lua/.luau` directories
- `LegacyScriptDir` - for `init.legacy.lua/.luau` directories
### 3. Update ScriptType Enum
In `[src/snapshot_middleware/lua.rs](src/snapshot_middleware/lua.rs)`, simplify to:
```rust
pub enum ScriptType {
Server, // Script + RunContext.Server
Client, // Script + RunContext.Client
Plugin, // Script + RunContext.Plugin
Legacy, // Script + RunContext.Legacy
Local, // LocalScript
Module, // ModuleScript
}
```
Remove `LegacyServer`, `LegacyClient`, `RunContextServer`, `RunContextClient` - these were for the dual-mode system.
### 4. Update Default Sync Rules
In `[src/snapshot_middleware/mod.rs](src/snapshot_middleware/mod.rs)` `default_sync_rules()`:
```rust
vec![
sync_rule!("*.server.lua", ServerScript, ".server.lua"),
sync_rule!("*.server.luau", ServerScript, ".server.luau"),
sync_rule!("*.client.lua", ClientScript, ".client.lua"),
sync_rule!("*.client.luau", ClientScript, ".client.luau"),
sync_rule!("*.plugin.lua", PluginScript, ".plugin.lua"),
sync_rule!("*.plugin.luau", PluginScript, ".plugin.luau"),
sync_rule!("*.legacy.lua", LegacyScript, ".legacy.lua"), // NEW
sync_rule!("*.legacy.luau", LegacyScript, ".legacy.luau"), // NEW
sync_rule!("*.local.lua", LocalScript, ".local.lua"), // NEW
sync_rule!("*.local.luau", LocalScript, ".local.luau"), // NEW
sync_rule!("*.{lua,luau}", ModuleScript), // Unchanged - catches remaining
// ... rest unchanged
]
```
### 5. Update Init Path Handling
In `[src/snapshot_middleware/mod.rs](src/snapshot_middleware/mod.rs)` `get_dir_middleware()`:
```rust
vec![
(Middleware::ModuleScriptDir, "init.luau"),
(Middleware::ModuleScriptDir, "init.lua"),
(Middleware::ServerScriptDir, "init.server.luau"),
(Middleware::ServerScriptDir, "init.server.lua"),
(Middleware::ClientScriptDir, "init.client.luau"),
(Middleware::ClientScriptDir, "init.client.lua"),
(Middleware::LocalScriptDir, "init.local.luau"), // NEW
(Middleware::LocalScriptDir, "init.local.lua"), // NEW
(Middleware::LegacyScriptDir, "init.legacy.luau"), // NEW
(Middleware::LegacyScriptDir, "init.legacy.lua"), // NEW
(Middleware::CsvDir, "init.csv"),
]
```
### 6. Remove emitLegacyScripts Entirely
Files to modify:
- `[src/project.rs](src/project.rs)` - Remove `emit_legacy_scripts` field from `Project`
- `[src/snapshot/metadata.rs](src/snapshot/metadata.rs)` - Remove from `InstanceContext`, remove `with_emit_legacy_scripts()`
- `[src/snapshot_middleware/util.rs](src/snapshot_middleware/util.rs)` - Remove `emit_legacy_scripts_default()`
- `[src/snapshot_middleware/project.rs](src/snapshot_middleware/project.rs)` - Remove `set_emit_legacy_scripts()` call
- `[src/serve_session.rs](src/serve_session.rs)` - Remove emit_legacy_scripts usage
### 7. Update Syncback Middleware Selection
In `[src/syncback/mod.rs](src/syncback/mod.rs)` `get_best_middleware()`:
```rust
middleware = match inst.class.as_str() {
"Script" => {
// Check RunContext to determine which middleware
match inst.properties.get(&ustr("RunContext")) {
Some(Variant::Enum(e)) => match e.to_u32() {
// Legacy = 0, Server = 1, Client = 2, Plugin = 3
0 => Middleware::LegacyScript,
1 => Middleware::ServerScript,
2 => Middleware::ClientScript,
3 => Middleware::PluginScript,
_ => Middleware::ServerScript, // fallback
},
_ => Middleware::LegacyScript, // No RunContext = Legacy behavior
}
}
"LocalScript" => Middleware::LocalScript,
"ModuleScript" => Middleware::ModuleScript,
// ... rest unchanged
}
```
### 8. Update File Name Extensions
In `[src/syncback/file_names.rs](src/syncback/file_names.rs)` `extension_for_middleware()`:
```rust
Middleware::ServerScript => "server.luau",
Middleware::ClientScript => "client.luau",
Middleware::PluginScript => "plugin.luau",
Middleware::LegacyScript => "legacy.luau", // NEW
Middleware::LocalScript => "local.luau", // NEW
Middleware::ModuleScript => "luau",
```
### 9. Update Meta File Suffix Stripping
In `[src/snapshot_middleware/lua.rs](src/snapshot_middleware/lua.rs)` `syncback_lua()` and `[src/snapshot_middleware/meta_file.rs](src/snapshot_middleware/meta_file.rs)`:
Add `.local` and `.legacy` to the suffix stripping logic.
### 10. Update Web API (Two-Way Sync)
In `[src/web/api.rs](src/web/api.rs)`:
- Update script handling to use new naming conventions
- Remove all `emit_legacy_scripts` references and conditional logic
### 11. Update Test Files
- Delete test projects in `rojo-test/build-tests/nested_runcontext/` that test emitLegacyScripts
- Update all snapshot files (`.snap`) that contain `emit_legacy_scripts: true/false`
- Update test cases in `src/snapshot_middleware/lua.rs` to use the new single behavior
### 12. Clean Up Comments
Remove all legacy references and comments about the old dual-mode system throughout the codebase.
## Files to Modify (Summary)
Core changes:
- `src/path_encoding.rs` - Add period encoding (`%DOT%`) and `%%` escape for literal `%`
- `src/syncback/mod.rs` - Default encode_windows_invalid_chars to true, update middleware selection
- `src/serve_session.rs` - Default decode_windows_invalid_chars to true
- `src/snapshot_middleware/mod.rs` - Add middleware variants, update sync rules
- `src/snapshot_middleware/lua.rs` - Simplify ScriptType, update logic
- `src/snapshot/metadata.rs` - Remove emit_legacy_scripts
- `src/project.rs` - Remove emit_legacy_scripts field
- `src/syncback/mod.rs` - Update middleware selection with RunContext check
- `src/syncback/file_names.rs` - Add new extensions
- `src/snapshot_middleware/util.rs` - Remove emit_legacy_scripts_default
- `src/snapshot_middleware/project.rs` - Remove emit_legacy_scripts propagation
- `src/serve_session.rs` - Remove emit_legacy_scripts usage
- `src/web/api.rs` - Update for new conventions
- `src/snapshot_middleware/meta_file.rs` - Add new suffix handling
Test updates:
- ~40 snapshot files need `emit_legacy_scripts` line removed and `decode_windows_invalid_chars` changed to `true`
- Test functions need updating to not pass emit_legacy_scripts parameter