Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Projects/hello_ros/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ services:
working_dir: /workspace
tty: true
volumes:
- "/Users/trieutran/BROS/Projects/hello_ros/workspace:/workspace"
- "/Users/trieutran/BROS2/Projects/hello_ros/workspace:/workspace"
109 changes: 87 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ docker ps
## 🧱 First-Time Setup

```bash
git clone https://github.com/nhathout/BROS.git
cd BROS
git clone https://github.com/nhathout/BROS2.git
cd BROS2
./apps/desktop-app/scripts/bootstrap.sh
```

Expand All @@ -41,20 +41,54 @@ It launches the packaged app once everything compiles. If the script adds an `nv

## ⏳ Daily Development

From a bootstrapped workspace, start the dev environment from the desktop app folder:
1. **Select Node 20.19.x** (every new shell resets your `nvm` version):

```bash
cd apps/desktop-app
node node_modules/electron/install.js
pnpm dev
```
```bash
source ~/.nvm/nvm.sh
nvm use 20.19.0
```

2. **Refresh dependencies** after pulling changes:

```bash
pnpm install -r
```

3. **Build the workspace libraries** so their `.d.ts` files exist for the Electron main process. Run each filter separately from the repo root (brace expansion is not supported):

```bash
pnpm --filter @bros2/runtime build
pnpm --filter @bros2/shared build
pnpm --filter @bros2/ui build
pnpm --filter @bros2/validation build
pnpm --filter @bros2/runner build
```

4. **Emit the desktop main + preload bundle** (run from the repo root so the filter resolves):

```bash
pnpm --filter ./apps/desktop-app build:main
```

(Optional) Build the renderer bundle for production checks — also from the repo root:

```bash
pnpm --filter ./apps/desktop-app build:renderer
```

5. **Start the dev environment** (Electron main + Vite renderer):

```bash
pnpm --filter ./apps/desktop-app dev
```

`pnpm dev` runs the Electron main process (`dev:main`) and the Vite renderer (`dev:renderer`) concurrently. Keep this terminal open while developing. You can also run the same command from the repo root with `pnpm --filter ./apps/desktop-app dev`.
Keep this process running while you iterate. You can still `cd apps/desktop-app && pnpm dev`, but the filtered form avoids path mistakes.

If you pull dependency changes later, refresh them with:
If Electron complains about missing binaries, reinstall them once:

```bash
pnpm install -r
cd apps/desktop-app
node node_modules/electron/install.js
```

## 🤖 ROS 2 Dev Notes
Expand Down Expand Up @@ -98,23 +132,54 @@ const { errors, warnings } = await window.ir.validate(ir);
console.log({ issues, errors, warnings });
```

## 🧹 Cleaning
### Runtime bridge & ArrowKey publisher smoke test

Wipe compiled artifacts across every workspace when you need a fresh build:
The preload now exposes `window.runtime` alongside the runner and IR bridges. With the dev app running:

```bash
pnpm -r clean
```js
typeof window.runtime; // "object"
const id = window.runtime.create("ArrowKeyPub", { topic: "keys/arrows" });
window.runtime.start(id);
// Press arrow keys while the Electron window is focused:
// [publish] keys/arrows <- { key: "left", ts: ... }
// [node:ArrowKeyPub_1] pressed: left
window.runtime.stop(id);
window.runtime.list(); // ["ArrowKeyPub_1"]
```

To reset dependencies as well:
If `window.runtime` is missing, run `pnpm --filter ./apps/desktop-app build:main` again to regenerate the preload bridges.

```bash
pnpm store prune
rm -rf node_modules
pnpm install -r
```
## 🧹 Cleaning & Full Rebuild

1. Remove build outputs everywhere (this clears `dist/` folders and `tsconfig.main.tsbuildinfo`, ensuring the desktop main bundle re-emits `dist/main.js`):

```bash
pnpm -r clean
```

2. Reset dependencies if things get out of sync:

```bash
pnpm store prune # optional
rm -rf node_modules
pnpm install -r
```

3. Rebuild the workspaces and desktop app using the daily workflow above. When `build:main` succeeds you should have:

```
apps/desktop-app/dist/main.js
apps/desktop-app/dist/preload.js
apps/desktop-app/dist/remote/runtime-bridge.cjs
```

4. (Optional) Produce installers:

```bash
pnpm -r build
```

After cleaning, rerun `pnpm dev` (or `./apps/desktop-app/scripts/bootstrap.sh`) to rebuild the app.
You may ignore macOS code-sign warnings on local development machines.

## 💡 Tips
- Keep Docker running whenever you use `window.runner.*`; the runner manages containers in `Projects/`.
Expand Down
20 changes: 11 additions & 9 deletions apps/desktop-app/package.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
{
"name": "bros-desktop",
"name": "2-desktop",
"private": true,
"version": "0.1.0",
"description": "BROS Desktop — Electron + React (Vite) app for visual ROS2 development",
"description": "BROS2 Desktop — Electron + React (Vite) app for visual ROS2 development",
"main": "dist/main.js",
"type": "commonjs",
"scripts": {
"dev": "concurrently \"pnpm dev:main\" \"pnpm dev:renderer\"",
"dev:main": "cross-env NODE_ENV=development TS_NODE_PROJECT=tsconfig.main.json electron ./electron-main.cjs",
"dev:renderer": "vite --config src/renderer/vite.config.ts",
"build": "pnpm clean && pnpm build:main && pnpm build:renderer && electron-builder",
"build:main": "tsc -p tsconfig.main.json",
"build:main": "tsc -p tsconfig.main.json && tsc -p tsconfig.runtime.json",
"build:renderer": "vite build --config src/renderer/vite.config.ts",
"start": "cross-env NODE_ENV=production electron ./dist/main.js",
"clean": "rimraf dist release",
"clean": "rimraf dist release tsconfig.main.tsbuildinfo",
"typecheck": "pnpm tsc -b tsconfig.main.json && pnpm tsc --noEmit -p tsconfig.renderer.json",
"postinstall": "electron-builder install-app-deps"
},
"build": {
"appId": "com.bros.desktop",
"productName": "BROS Desktop",
"appId": "com.bros2.desktop",
"productName": "BROS2 Desktop",
"directories": {
"output": "release"
},
Expand Down Expand Up @@ -66,9 +66,11 @@
"vite": "^7.1.7"
},
"dependencies": {
"@bros/runner": "workspace:*",
"@bros/ui": "workspace:*",
"@bros/validation": "workspace:*",
"@bros2/runtime": "workspace:*",
"@bros2/shared": "workspace:*",
"@bros2/runner": "workspace:*",
"@bros2/ui": "workspace:*",
"@bros2/validation": "workspace:*",
"bootstrap": "^5.3.8",
"dotenv": "^17.2.3",
"express": "^5.1.0",
Expand Down
8 changes: 4 additions & 4 deletions apps/desktop-app/scripts/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -euo pipefail

# -------------------------------
# BROS Bootstrap Script
# BROS2 Bootstrap Script
# -------------------------------
# 1. Ensures NVM is installed
# 2. Uses Node 20.19.0
Expand All @@ -16,7 +16,7 @@ PNPM_VERSION="10.17.1"
NVM_INSTALL_URL="https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh"
AUTO_NVM_CONFIGURED=0

echo "Bootstrapping BROS development environment..."
echo "Bootstrapping BROS2 development environment..."

# --- Install / Load NVM ---
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
Expand Down Expand Up @@ -50,7 +50,7 @@ AUTO_NVM_SNIPPET="nvm use $NODE_VERSION"
if [ -w "$ZSHRC_PATH" ] && ! grep -Fq "$AUTO_NVM_SNIPPET" "$ZSHRC_PATH"; then
echo "ℹ️ Enabling automatic 'nvm use $NODE_VERSION' in $ZSHRC_PATH"
{
echo "\n# BROS bootstrap: ensure Node $NODE_VERSION via nvm"
echo "\n# BROS2 bootstrap: ensure Node $NODE_VERSION via nvm"
echo "if [ -s \"$NVM_DIR/nvm.sh\" ]; then"
echo " . \"$NVM_DIR/nvm.sh\""
echo " nvm use $NODE_VERSION >/dev/null"
Expand Down Expand Up @@ -113,7 +113,7 @@ echo "Building renderer assets..."
pnpm --filter ./apps/desktop-app build:renderer

# --- Launch packaged Electron binary ---
echo "Launching BROS desktop (Electron)…"
echo "Launching BROS2 desktop (Electron)…"
pnpm --filter ./apps/desktop-app start

echo "Bootstrap complete!"
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop-app/src/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ async function loginWithGitHub() {
console.error("❌ No access_token returned from GitHub OAuth exchange.");
return;
}
await keytar_1.default.setPassword("BROS", "github", token.access_token);
await keytar_1.default.setPassword("BROS2", "github", token.access_token);
console.log("✅ Token stored in keychain");
}
async function openOAuthWindow(authUrl, redirectUri) {
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop-app/src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export async function loginWithGitHub(): Promise<void> {
return;
}

await keytar.setPassword("BROS", "github", token.access_token);
await keytar.setPassword("BROS2", "github", token.access_token);
console.log("✅ Token stored in keychain");
}

Expand Down
6 changes: 3 additions & 3 deletions apps/desktop-app/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { fileURLToPath } from "node:url";
import { app, BrowserWindow, ipcMain, shell } from "electron";
import express from "express";
import dotenv from "dotenv";
import { Runner } from "@bros/runner";
import { buildIR } from "@bros/ui";
import { validateIR } from "@bros/validation";
import { Runner } from "@bros2/runner";
import { buildIR } from "@bros2/ui";
import { validateIR } from "@bros2/validation";
// --- Setup ---
dotenv.config();
const __filename = fileURLToPath(import.meta.url);
Expand Down
Loading