Initial commit
This commit is contained in:
156
AGENTS.md
Executable file
156
AGENTS.md
Executable file
@@ -0,0 +1,156 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Build, Lint, and Test Commands
|
||||
|
||||
### Backend (Rust)
|
||||
```bash
|
||||
cd backend && cargo build # Build project
|
||||
cd backend && cargo test # Run all tests
|
||||
cd backend && cargo test my_test # Run test matching pattern
|
||||
cd backend && cargo test -- --exact # Run exact test name
|
||||
cd backend && cargo test -- --test-threads=1 # Run tests sequentially
|
||||
cd backend && cargo test -- --nocapture # Show test output
|
||||
cd backend && cargo test --lib # Library tests only
|
||||
cd backend && cargo fmt # Format code
|
||||
cd backend && cargo fmt --check # Check formatting
|
||||
cd backend && cargo clippy # Lint code
|
||||
```
|
||||
|
||||
### Frontend (React + TypeScript)
|
||||
```bash
|
||||
cd frontend && npm install # Install dependencies
|
||||
cd frontend && npm run dev # Start dev server (port 3000)
|
||||
cd frontend && npm run build # Build for production (tsc + vite)
|
||||
cd frontend && npm run lint # Lint with ESLint
|
||||
cd frontend && npx tsc --noEmit # Type check only
|
||||
cd frontend && npm test # Run Jest tests
|
||||
cd frontend && npm run test:watch # Run tests in watch mode
|
||||
```
|
||||
|
||||
### Docker
|
||||
```bash
|
||||
docker-compose up -d # Start all services
|
||||
docker-compose logs -f backend # View backend logs
|
||||
docker-compose logs -f frontend # View frontend build/logs
|
||||
docker-compose down # Stop all services
|
||||
docker cp frontend/dist/. sap-sync-frontend:/usr/share/nginx/html/ # Update frontend in container
|
||||
docker exec sap-sync-frontend nginx -s reload # Reload nginx
|
||||
```
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### Rust Backend
|
||||
|
||||
**Imports** — Alphabetical order, grouped with blank lines: `std` → external → local. Use full paths: `crate::handlers::sync`. Avoid wildcard imports.
|
||||
|
||||
**Naming** — Types: `PascalCase`. Functions: `snake_case`. Constants: `SCREAMING_SNAKE_CASE`. Modules: `snake_case`.
|
||||
|
||||
**Error Handling** — Use `thiserror::Error` for typed errors. Use `ApiError` in HTTP handlers. Log with `tracing::{info, error}` macros. Never use `unwrap()`; prefer `?`, `match`, or `unwrap_or_else()`. Convert errors to `String` for `ApiError::Database`.
|
||||
|
||||
**Types** — `i32` for DB IDs, `f64` for decimals. `String` for owned text, `&str` for borrowed. `Option<T>` for nullable, `Vec<T>` for collections. `Arc<T>` for shared state.
|
||||
|
||||
**Handlers** — Return `impl IntoResponse`. Use `build_response()` helper for consistent JSON responses. Extract DB connections via `state.pool.get()` with error handling.
|
||||
|
||||
**Database** — Use `r2d2` connection pooling. Parameterized queries (`$1`, `$2`). Always handle pool errors.
|
||||
|
||||
### React Frontend
|
||||
|
||||
**Imports** — Alphabetical, grouped: external → lib → components → pages. Named imports preferred.
|
||||
|
||||
**Formatting** — 2-space indent, single quotes, no semicolons, 100-char line limit (Prettier).
|
||||
|
||||
**Naming** — Components: `PascalCase`. Hooks: `useCamelCase`. Variables: `camelCase`.
|
||||
|
||||
**TypeScript** — Strict mode enabled. Avoid `any`; use `unknown` or generics. Define interfaces for API responses. Prefer `type` over `interface` for unions.
|
||||
|
||||
**Error Handling** — Use try/catch for async ops. Log with `logger.error()`. Show user feedback via `toast.success()`/`toast.error()`. Use MUI Dialogs for confirmations, not `window.confirm`.
|
||||
|
||||
**Components** — Functional components with hooks. `useCallback` for handlers, `useMemo` for expensive calcs. Avoid inline functions in JSX props.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
SAP-PLEX-SYNC/
|
||||
├── backend/src/
|
||||
│ ├── lib.rs # Library exports
|
||||
│ ├── main.rs # Entry point (rouille HTTP server)
|
||||
│ ├── handlers_sync.rs # Sync API handlers (axum - not currently used)
|
||||
│ ├── handlers.rs # Other HTTP handlers (legacy)
|
||||
│ ├── models.rs # Data models
|
||||
│ ├── state.rs # AppState (r2d2 pool)
|
||||
│ ├── errors.rs # ApiError enum
|
||||
│ ├── response.rs # Response helpers
|
||||
│ ├── sync.rs # Sync types & structs
|
||||
│ ├── plesk_client.rs # Plesk API client
|
||||
│ ├── sap_client.rs # SAP API client
|
||||
│ ├── config.rs # Configuration
|
||||
│ └── ...
|
||||
├── frontend/src/
|
||||
│ ├── pages/ # Page components
|
||||
│ ├── components/ # Reusable components
|
||||
│ ├── lib/api.ts # API client (apiJson)
|
||||
│ ├── lib/hooks.ts # usePolling, formatDate
|
||||
│ ├── lib/logger.ts # Logging utility
|
||||
│ └── contexts/ # React contexts
|
||||
├── database/ # Migrations and seeds
|
||||
└── docker-compose.yml
|
||||
```
|
||||
|
||||
## Cursor Rules (.cursorrules)
|
||||
|
||||
- Follow `cargo fmt` and `cargo clippy` before committing
|
||||
- Use `anyhow::Result` for error propagation, `ApiError` for HTTP
|
||||
- Return `impl IntoResponse` for axum handlers (note: main server uses rouille)
|
||||
- Functional components with hooks; avoid inline JSX functions
|
||||
- Use `useCallback`/`useMemo` for performance
|
||||
- Test user interactions with React Testing Library, not implementation details
|
||||
- Always check for unsafe `unwrap()` calls and replace with proper error handling
|
||||
- Use proper logging instead of `console.log` in frontend
|
||||
- Keep functions small and focused
|
||||
- Use meaningful variable and function names
|
||||
- Add comments for complex logic
|
||||
|
||||
## API Response Format
|
||||
|
||||
Backend returns flat JSON (no `data` wrapper):
|
||||
```json
|
||||
{ "is_running": false, "stats": { "running": 0 }, "jobs": [...] }
|
||||
```
|
||||
|
||||
For server listings, returns direct array: `[{ "id": 1, "name": "test", ... }]`
|
||||
|
||||
Frontend uses `apiJson<T>()` from `lib/api.ts` for typed API calls.
|
||||
Frontend proxy: `/api` → `http://localhost:3001` (configured in `vite.config.ts`).
|
||||
|
||||
## Testing
|
||||
|
||||
**Backend** — Tests in `#[cfg(test)] mod tests` blocks. Use `#[test]` for sync, `#[tokio::test]` for async. Test both happy paths and error cases. Mock external deps with `mockall`.
|
||||
|
||||
To run a specific test: `cd backend && cargo test test_function_name -- --exact`
|
||||
To run tests matching a pattern: `cd backend && cargo test pattern_name`
|
||||
To run tests sequentially: `cd backend && cargo test -- --test-threads=1`
|
||||
To see test output: `cd backend && cargo test -- --nocapture`
|
||||
|
||||
**Frontend** — Jest + React Testing Library. Use `screen.getByRole`/`getByText`. Test user interactions, not implementation. Mock API with `jest.mock()`.
|
||||
|
||||
To run frontend tests: `cd frontend && npm test`
|
||||
To run tests in watch mode: `cd frontend && npm run test:watch`
|
||||
|
||||
## Git Workflow
|
||||
|
||||
Commits: `type(scope): description` (e.g., `fix(handlers): resolve API mismatch`).
|
||||
Types: `feat`, `fix`, `docs`, `refactor`, `chore`.
|
||||
Branches: `feature/`, `bugfix/`, `hotfix/`.
|
||||
|
||||
## Key Reminders
|
||||
|
||||
1. Build and lint before committing: `cargo build --lib`, `cargo fmt`, `cargo clippy`, `npm run build`
|
||||
2. Update Docker container after frontend changes: `docker cp frontend/dist/. sap-sync-frontend:/usr/share/nginx/html/`
|
||||
3. Test API endpoints with `curl http://localhost/api/...` to verify response format
|
||||
4. Use `tracing::{info, error}` for backend logging, `logger.error()` for frontend
|
||||
5. Never use `unwrap()` in production code; use `?` or proper error handling
|
||||
6. Avoid `any` in TypeScript; use `unknown` or proper types
|
||||
7. Use MUI Dialogs for confirmations, not `window.confirm`
|
||||
8. Use `toast.success()`/`toast.error()` for user feedback, not `alert()`
|
||||
9. Remember that the main HTTP server uses rouille (not axum) in `main.rs`
|
||||
10. Database column for passwords is named `password_hash`, not `password`
|
||||
Reference in New Issue
Block a user