# Dev setup

How to get `@mac-sync` running on a development machine.

## Prerequisites

- macOS 13+ (matches `Package.swift:7` platform requirement)
- Xcode command-line tools (`swift --version` >= 5.9, per `Package.swift:1`)
- [Bun](https://bun.sh) — server and web runtime (`src/server/package.json:7-10`, `web/package.json:7-10`)
- PostgreSQL 14+ with `gen_random_uuid()` available (used in
  `SendQueueRepo.ts:152`)
- For the Linux server target: systemd (`app.manifest.yaml:42`)

## Clone and resolve packages

```sh
cd ~/Code/@applications
git clone <repo> @mac-sync
cd @mac-sync
swift package resolve   # pulls GRDB, Alamofire, SwiftyJSON, Swifter
```

Local SwiftPM dependencies (`Package.swift:9-15`) live in
`~/Code/@packages/@swift/`:
- `agent-core`, `menu-bar`, `sync-framework`, `logging`, `settings`
- `@tray/tray-resources`

If `swift package resolve` complains about a missing local package, clone the
corresponding repo into `~/Code/@packages/@swift/<scope>/<name>/`.

## Build the Mac client

```sh
make build       # Makefile:59-61 -> swift build --product MacSyncApp
make run         # Makefile:78-79 -> .build/debug/MacSyncApp
```

`make build` produces `.build/debug/MacSyncApp`. The app is a menu-bar
executable; it stays in the dock-less tray once running. Look for the
`MacSyncShared/Storage/ActivityLog` entries in stderr to confirm modules are
ticking.

Tests:

```sh
make test        # Makefile:71-73 -> swift test (all test targets in Package.swift:113-157)
```

## Boot the server

```sh
cd src/server
cp .env.example .env       # if present; otherwise set vars manually
bun install
bun run dev                # src/server/package.json:7
```

Required environment (read by `src/server/src/app/config.ts`):

- `DATABASE_URL=postgres://…/icloud`
- `SSO_VALIDATE_URL` — endpoint hit by the `ssoRequired` middleware for `/my/*`
  (`src/server/src/app/server.ts:79`)
- `SERVICE_TOKEN` — bearer for `/admin/*`
  (`src/server/src/app/server.ts:83`)

The server listens on the port from `app.manifest.yaml:44` (3201 in prod).
First boot runs all migrations in order:
`src/server/src/app/server.ts:36-52`.

Health checks:

```sh
curl http://localhost:3201/health         # server.ts:56
curl http://localhost:3201/health/deep    # server.ts:57-66 — also pings the DB
```

## Boot the web SPA

```sh
cd web
bun install
bun run dev       # vite --port 5200 (web/package.json:7)
```

The dev server hot-reloads against the API on `localhost:3201`. For production
the SPA is built (`bun run build`) into `web/dist/` and that directory is
shipped inside the Mac app bundle (`webapp/` subresource) or served by the
server.

## Wire the Mac to the server

`LocalWebServer` (`@packages/shared/Sources/MacSyncShared/WebServer/LocalWebServer.swift:42-110`)
exposes the dev SPA on `http://localhost:8765` and an editable settings
endpoint:

```sh
curl http://localhost:8765/api/settings
# {"serverURL":"http://10.0.0.11:3201","webServerPort":8765, …}

curl -X PUT http://localhost:8765/api/settings \
  -H 'content-type: application/json' \
  -d '{"serverURL":"http://localhost:3201"}'
```

For local end-to-end work, set `serverURL` to `http://localhost:3201` and
restart `MacSyncApp` so `DeviceRegistration` re-registers against the local
backend.

## Permissions to grant on first run

Each module needs an OS permission. Approve when prompted:

- **iMessage**: Full Disk Access (to read `~/Library/Messages/chat.db`).
  Module surfaces `.fullDiskAccessRequired` if missing
  (`@packages/imessage/Sources/IMessageSync/SyncManager.swift:36`).
- **iPhoto**: Photos library access (`PHPhotoLibrary`). Modal handled by
  `IPhotoSync.requestAuthorization()`.
- **iMail**: Automation > Mail.
- **iCal**: Calendars (`EKEventStore.requestFullAccessToEvents`).
- **iReminders**: Reminders (`EKEventStore.requestFullAccessToReminders`).
- **iNotes**: Automation > Notes
  (`@packages/inotes/Sources/INoteSync/SyncManager.swift:96-100`).

If you decline, the module sets its error state (e.g.
`.calendarAccessRequired`) and skips cycles until you re-grant. Click the
menu-bar status row to deep-link into System Settings.

## Running a single test target

```sh
swift test --filter MacSyncSharedTests
swift test --filter IMessageSyncTests
swift test --filter ICalSyncTests
```

All test targets are declared in `Package.swift:113-157`.

## Common dev problems

- **`make build` fails with "no such package"**: the local SwiftPM siblings
  under `~/Code/@packages/@swift/` are missing. Clone them, then
  `swift package resolve` again.
- **`bun run dev` (server) fails on `gen_random_uuid()`**: enable the
  `pgcrypto` extension on the Postgres database (or use Postgres 13+).
- **The Mac app starts but the menu icon never appears**: check stderr for
  `LocalWebServer: webapp directory not found`
  (`LocalWebServer.swift:151`). In dev, the resolver expects
  `<repo>/web/dist/`; run `cd web && bun run build` once.
