macsync/docs/dev-setup.md

149 lines
4.8 KiB
Markdown
Raw Normal View History

# 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://localhost: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.