# Development Guide This guide covers the usual path for adding or changing a Forge module. ## Local Checks Before running storage-backed workflows locally, complete [SurrealDB Setup](/getting-started/surrealdb-setup). Run these before pushing Rust or extension changes: ```powershell cargo fmt --check cargo check cargo test cargo build cargo clippy --all-targets --all-features -- -D warnings ``` Run this after changing browser UI sources: ```powershell npm run build:webui ``` Build Arma packages with: ```powershell .\build-arma.ps1 ``` ## Module Boundaries Keep each layer responsible for one kind of work: | Layer | Owns | Avoid | | --- | --- | --- | | `lib/models` | Data structures, serde defaults, validation helpers. | Database calls, SQF-specific context. | | `lib/repositories` | Repository traits and in-memory stores. | SurrealDB-specific code. | | `lib/services` | Business rules, workflow orchestration, structured results. | Arma engine calls, extension transport details. | | `arma/server/extension` | Command parsing, context resolution, SurrealDB implementations, serialization to SQF. | Business rules that belong in services. | | `arma/server/addons` | Server SQF lifecycle, game-object integration, calls into `forge_server`. | Direct database logic. | | `arma/client/addons` | Client UI, keybinds, local UI events. | Authoritative persistence. | ## Adding a Domain Module 1. Add the model in `lib/models/src/.rs`. 2. Export the model from `lib/models/src/lib.rs`. 3. Add repository traits in `lib/repositories/src/.rs`. 4. Add in-memory repository support if the service needs tests or hot state. 5. Export the traits from `lib/repositories/src/lib.rs`. 6. Add service logic in `lib/services/src/.rs`. 7. Add focused unit tests for service behavior. 8. Export the service from `lib/services/src/lib.rs`. 9. Add a SurrealDB schema module under `arma/server/extension/src/schema`. 10. Add the concrete storage adapter under `arma/server/extension/src/storage`. 11. Register the storage adapter in `arma/server/extension/src/storage.rs`. 12. Add an extension command group under `arma/server/extension/src/.rs`. 13. Register the command group in `arma/server/extension/src/lib.rs`. 14. Add server addon functions under `arma/server/addons/` if SQF needs a module-level API. 15. Add client addon or browser UI files under `arma/client/addons/` if the module has player-facing UI. 16. Add documentation in `docs/` and module-level READMEs. ## Extension Command Rules Commands should return one of these forms: - JSON string for structured results. - `"true"` or `"false"` for simple existence and boolean operations. - `"OK"` for successful destructive operations with no response body. - `"Error: "` for failures. Prefer stable JSON shapes over ad hoc strings. SQF callers should always check for the `"Error:"` prefix before parsing JSON. Example: ```sqf private _result = "forge_server" callExtension ["actor:get", [getPlayerUID player]]; private _payload = _result select 0; if (_payload find "Error:" == 0) exitWith { systemChat format ["Actor request failed: %1", _payload]; }; private _actor = fromJSON _payload; ``` ## Persistence Rules SurrealDB is the durable store. Keep database-specific mapping in the extension storage adapters, not in services or repository traits. When changing persisted data: - Update or add the matching `.surql` schema module. - Update the concrete storage adapter. - Preserve existing records when possible through serde defaults or migration logic. - Add tests at the service level for behavior, and add storage tests only when database mapping is the risk. ## Hot-State Rules Use hot state for data that is read or mutated frequently during a player session. Hot-state modules usually provide: - `init` to load durable state into memory. - `get` to read the runtime copy. - `override` or focused mutation commands to update the runtime copy. - `save` to write the runtime copy back to SurrealDB. - `remove` to evict the runtime copy. Do not assume hot state is durable until `save` succeeds. ## Web UI Rules Browser UI source files live under each client addon. Built assets usually land under that addon's `ui/_site` directory. Use the existing common bridge in `arma/client/addons/common` when a UI needs to send events back to SQF. Keep UI state and rendering in JavaScript, and keep server-authoritative decisions in server SQF or Rust services. ## Documentation Checklist When adding or changing a module, update: - `docs/MODULE_REFERENCE.md` for framework-level inventory. - A module-specific README in the addon directory when SQF or UI usage changes. - `arma/server/docs/api-reference.md` when extension commands change. - Existing usage guides when payload shapes or workflows change.