149 lines
4.8 KiB
Markdown
149 lines
4.8 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`):
|
||
|
|
|
||
|
|
- `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.
|