167 lines
6 KiB
Markdown
167 lines
6 KiB
Markdown
# 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`):
|
|
|
|
- `QUINN_MACSYNC_DB_URL=postgres://…` — Postgres connection string
|
|
- `SERVICE_TOKEN` — bearer for `/my/*` and `/admin/*`
|
|
(`src/server/src/app/server.ts:136,140`)
|
|
- `SSO_VALIDATE_URL` — endpoint for the alternative `ssoRequired` gate on `/my/*`
|
|
- `MODEL_BOSS_EMBED_URL` — embedding inference endpoint (**required, no default** —
|
|
fails fast rather than dialing a baked LAN host)
|
|
|
|
Object storage (photo/attachment blobs), selected by `STORAGE_BACKEND`:
|
|
|
|
- `STORAGE_BACKEND=local` (dev default) → blobs under `STORAGE_LOCAL_PATH`
|
|
(`./data/blobs`). No other vars needed.
|
|
- `STORAGE_BACKEND=s3` → any S3-compatible store (MinIO / DO Spaces / AWS / R2),
|
|
always signed (SigV4). Set `S3_ENDPOINT`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`,
|
|
`S3_BUCKET`, `S3_REGION` (default `us-east-1`), `S3_FORCE_PATH_STYLE`
|
|
(`true` for MinIO **and** the `lilith-quinn-media` Spaces bucket),
|
|
`S3_PRESIGN_TTL_SECONDS` (default `900`). Dev MinIO is provided by
|
|
`docker-compose.dev.yml`.
|
|
|
|
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`, an editable settings endpoint,
|
|
plus dedicated diagnostics for calls:
|
|
|
|
- `GET /api/calls?limit=20` — recent call logs (address, direction, answered,
|
|
duration, callType, serviceProvider, startedAt).
|
|
- `/api/diagnostics` now includes `callHistoryDb` (and the existing `iMessageDb`).
|
|
|
|
```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 / iCalls**: Full Disk Access (to read `~/Library/Messages/chat.db` and
|
|
`~/Library/Application Support/CallHistoryDB/CallHistory.storedata`). iMessage
|
|
surfaces `.fullDiskAccessRequired`; iCalls uses the same grant (no separate
|
|
prompt). The LocalWebServer also exposes `http://localhost:8765/api/calls`
|
|
(structured recent calls) and includes `callHistoryDb` in `/api/diagnostics`.
|
|
- **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 ICallsSyncTests
|
|
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.
|