diff --git a/.env.example b/.env.example index 55b822b..86f1819 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,22 @@ -# Connection string for local development and tests. +# Copy to .env for local development: cp .env.example .env +# These defaults match the services in docker-compose.yml. + +# PostgreSQL connection string (used for local dev and the test suite). # The role must be allowed to CREATE DATABASE (sqlx::test provisions temp DBs). DATABASE_URL=postgres://postgres:postgres@localhost:5432/cms_dev + +# HTTP bind address. BIND_ADDR=0.0.0.0:8080 + +# User-facing product name (OpenAPI title, page title). Set the real name at deploy time. APP_NAME=Collection Management System + +# Local development is plain HTTP. Browsers drop `Secure` cookies on http://localhost, +# so the session cookie must NOT be Secure-only or login will silently fail. Set this +# back to `true` (the default) for any HTTPS deployment. +SESSION_COOKIE_SECURE=false + +# Meilisearch (matches docker-compose.yml). Both must be set to enable search; +# leave them unset to run with search disabled. +MEILI_URL=http://localhost:7700 +MEILI_MASTER_KEY=masterKey diff --git a/README.md b/README.md index d42d99a..d1f8c28 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,83 @@ # Biggus Dickus ![Biggus Dickus](docs/biggus-dickus.jpg) + +A museum collection-management system: a Rust (axum + sqlx + Postgres) API with a +React + TypeScript admin SPA and optional Meilisearch-backed full-text search. + +## Running locally + +The whole backing stack runs from one `docker compose` file (PostgreSQL + Meilisearch). + +### Prerequisites +- Docker (PostgreSQL + Meilisearch) +- Rust (stable; plus a nightly toolchain for `cargo +nightly fmt`) +- Node.js and [`pnpm`](https://pnpm.io/) (web frontend) +- [`just`](https://github.com/casey/just) — optional, for the shortcuts below + +### 1. Start the backing services +```bash +docker compose up -d +``` +PostgreSQL listens on `localhost:5432` (database `cms_dev`) and Meilisearch on +`localhost:7700`. Give them a few seconds to become healthy on first start. + +### 2. Configure the environment +```bash +cp .env.example .env +``` +The defaults already match the compose services. Note **`SESSION_COOKIE_SECURE=false`**: +local development is plain HTTP, and browsers drop `Secure` cookies on `http://localhost`, +so leaving it `true` would make login silently fail. Set it back to `true` for any HTTPS +deployment. + +### 3. Run the API server +```bash +just run # or: cargo run -p server +``` +On startup the server connects to PostgreSQL, **runs database migrations automatically**, +ensures the Meilisearch index exists, and listens on `http://localhost:8080`. (If the +`MEILI_*` variables are unset, search is disabled and everything else still works.) + +### 4. Create a login user +There is no seeded account — create one (you'll be prompted for a password, minimum 8 +characters): +```bash +cargo run -p server -- create-user --email you@example.com --role admin +# non-interactive: +BOOTSTRAP_PASSWORD=changeme123 cargo run -p server -- create-user --email you@example.com --role editor +``` +Roles are `admin` or `editor`. + +### 5. Run the web frontend +The API server serves JSON only; in development the SPA is served by Vite, which proxies +`/api` to `:8080`: +```bash +cd web +pnpm install +pnpm dev # http://localhost:5173 +``` +Open **http://localhost:5173** and sign in with the user from step 4. + +### Single-binary alternative +To serve the built SPA and the API from one process (no Vite), build the web assets and +enable the `embed-web` feature: +```bash +cd web && pnpm build # outputs web/dist +cargo run -p server --features embed-web # SPA + API on http://localhost:8080 +``` +Assets are embedded at compile time, so rebuild `web/dist` and recompile after frontend +changes. + +## Running tests + +Backend tests reuse the same compose services — PostgreSQL provisions a throwaway database +per test (`sqlx::test`) and Meilisearch tests use isolated, unique index names, so they +don't touch your dev data. With `docker compose up -d` running and `.env` in place: +```bash +just test # cargo test --workspace (reads .env via dotenv) +cd web && pnpm test # frontend tests (Vitest + MSW; no services needed) +``` +`just check` runs format + lint + the Rust test suite. Run `cargo test` directly only if +`DATABASE_URL`/`MEILI_URL`/`MEILI_MASTER_KEY` are exported in your shell — the Meilisearch +tests require them; `just` loads them from `.env` for you. diff --git a/docker-compose.yml b/docker-compose.yml index 6fd7983..6484789 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,24 @@ services: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 3s + retries: 10 + + meilisearch: + image: getmeili/meilisearch:v1.12 + environment: + # Development mode relaxes the production master-key length requirement and + # enables the search-preview UI. The key below is for local use only. + MEILI_ENV: development + MEILI_MASTER_KEY: masterKey + ports: + - "7700:7700" + volumes: + - meilidata:/meili_data volumes: pgdata: + meilidata: