Skip to content

Commit

Permalink
[menu-bar][electron] Implement local server (#178)
Browse files Browse the repository at this point in the history
* [menu-bar][electron] Implement local server

* Fix CORS

* Fix typescript checks

* Add changelog entry
  • Loading branch information
gabrieldonadel authored Feb 16, 2024
1 parent 56aae30 commit 2842cdb
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/lint-and-tsc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ jobs:
run: yarn tsc --noEmit
working-directory: apps/menu-bar

- name: 🏗️ TSC "Orbit" electron files
run: yarn tsc --noEmit
working-directory: apps/menu-bar/electron

- name: 🏗️ TSC "CLI" app files
run: yarn tsc --noEmit
working-directory: apps/cli
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
### 🎉 New features

- Add support for launching Expo updates. ([#134](https://github.com/expo/orbit/pull/134), [#137](https://github.com/expo/orbit/pull/137), [#138](https://github.com/expo/orbit/pull/138), [#144](https://github.com/expo/orbit/pull/144), [#148](https://github.com/expo/orbit/pull/148) by [@gabrieldonadel](https://github.com/gabrieldonadel))
- Add experimental support for Windows and Linux. ([#152](https://github.com/expo/orbit/pull/152), [#157](https://github.com/expo/orbit/pull/157), [#158](https://github.com/expo/orbit/pull/158), [#160](https://github.com/expo/orbit/pull/160), [#161](https://github.com/expo/orbit/pull/161), [#165](https://github.com/expo/orbit/pull/165), [#170](https://github.com/expo/orbit/pull/170), [#171](https://github.com/expo/orbit/pull/171), [#172](https://github.com/expo/orbit/pull/172), [#173](https://github.com/expo/orbit/pull/173), [#174](https://github.com/expo/orbit/pull/174), [#175](https://github.com/expo/orbit/pull/175), [#177](https://github.com/expo/orbit/pull/177) by [@gabrieldonadel](https://github.com/gabrieldonadel))
- Add experimental support for Windows and Linux. ([#152](https://github.com/expo/orbit/pull/152), [#157](https://github.com/expo/orbit/pull/157), [#158](https://github.com/expo/orbit/pull/158), [#160](https://github.com/expo/orbit/pull/160), [#161](https://github.com/expo/orbit/pull/161), [#165](https://github.com/expo/orbit/pull/165), [#170](https://github.com/expo/orbit/pull/170), [#171](https://github.com/expo/orbit/pull/171), [#172](https://github.com/expo/orbit/pull/172), [#173](https://github.com/expo/orbit/pull/173), [#174](https://github.com/expo/orbit/pull/174), [#175](https://github.com/expo/orbit/pull/175), [#177](https://github.com/expo/orbit/pull/177), [#178](https://github.com/expo/orbit/pull/178) by [@gabrieldonadel](https://github.com/gabrieldonadel))

### 🐛 Bug fixes

Expand Down
7 changes: 5 additions & 2 deletions apps/menu-bar/electron/package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"name": "orbit-electron",
"version": "0.0.1",
"version": "1.1.0",
"private": true,
"main": ".vite/build/main.js",
"scripts": {
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"lint": "eslint --ext .ts,.tsx ."
"lint": "eslint --ext .ts,.tsx .",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@electron-forge/cli": "^7.2.0",
Expand All @@ -17,6 +18,7 @@
"@electron-forge/maker-zip": "^7.2.0",
"@electron-forge/plugin-auto-unpack-natives": "^7.2.0",
"@electron-forge/plugin-vite": "^7.2.0",
"@types/express": "^4.17.21",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"electron": "28.2.0",
Expand All @@ -27,6 +29,7 @@
},
"dependencies": {
"electron-squirrel-startup": "^1.0.0",
"express": "^4.18.2",
"react-native-electron-modules": "1.0.0"
}
}
89 changes: 89 additions & 0 deletions apps/menu-bar/electron/src/LocalServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { app as electronApp } from 'electron';
import express, { Express } from 'express';

const PORTS = [35783, 47909, 44171, 50799];
const WHITELISTED_DOMAINS = ['expo.dev', 'expo.test', 'exp.host'];

export class LocalServer {
app: Express;

constructor() {
this.app = express();
this.setupMiddlewares();
this.setupRoutes();
}

setupMiddlewares() {
this.app.use((req, res, next) => {
const origin = req.get('origin');
const referer = req.get('referer');
if (!origin || !referer || !WHITELISTED_DOMAINS.includes(this.extractRootDomain(origin))) {
res.sendStatus(403);
return;
}

res.set('Access-Control-Allow-Origin', origin);
next();
});
}

setupRoutes() {
this.app.get('/orbit/status', (_, res) => {
res.json({ ok: true, version: electronApp.getVersion() });
});

this.app.get('/orbit/open', (req, res) => {
const urlParam = req.query.url as string | undefined;
if (!urlParam || !WHITELISTED_DOMAINS.includes(this.extractRootDomain(urlParam))) {
res.sendStatus(400);
return;
}

const deeplinkURL = urlParam
.replace('https://', 'expo-orbit://')
.replace('exp://', 'expo-orbit://');

electronApp.emit('open-url', null, deeplinkURL);
res.json({ ok: true });
});
}

start(port: number = PORTS[0]) {
this.app
.listen(port, () => {
console.log(`Local server running on port ${port}`);
})
.on('error', (err) => {
console.error(`Failed to start server on port ${port}: ${err.message}`);
const nextPort = PORTS[PORTS.indexOf(port) + 1];
if (nextPort) {
this.start(nextPort);
} else {
console.error(`Server start error: ${err.message}`);
}
});
}

extractRootDomain(urlString: string) {
try {
const originUrl = new URL(decodeURIComponent(urlString));
let hostName = originUrl.hostname;

if (!hostName) {
// Orbit deeplink may include specific routes in the URL e.g. /update, /snack, /download, etc.
const urlStringFromParams = originUrl.searchParams.get('url');
const urlFromParams = new URL(decodeURIComponent(urlStringFromParams));
hostName = urlFromParams.hostname;
}

if (!hostName.includes('.')) {
hostName = originUrl.pathname.split('/').filter(Boolean)[1];
}
const components = hostName.split('.');
return components.slice(-2).join('.');
} catch (error) {
console.error('Error extracting root domain:', error);
return '';
}
}
}
4 changes: 4 additions & 0 deletions apps/menu-bar/electron/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import os from 'os';
import path from 'path';
import { registerMainModules } from 'react-native-electron-modules';

import { LocalServer } from './LocalServer';
import TrayGenerator from './TrayGenerator';
import { MainModules } from '../modules/mainRegistry';

Expand Down Expand Up @@ -60,4 +61,7 @@ app.on('ready', () => {
const mainWindow = createMainWindow();
const Tray = new TrayGenerator(mainWindow);
Tray.createTray();

const server = new LocalServer();
server.start();
});
3 changes: 2 additions & 1 deletion apps/menu-bar/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"extends": "@react-native/typescript-config/tsconfig.json",
"compilerOptions": {
"lib": ["es2019", "dom"]
}
},
"exclude": ["node_modules", "electron"]
}
79 changes: 78 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6258,6 +6258,14 @@
dependencies:
"@babel/types" "^7.3.0"

"@types/body-parser@*":
version "1.19.5"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4"
integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==
dependencies:
"@types/connect" "*"
"@types/node" "*"

"@types/cacheable-request@^6.0.1":
version "6.0.3"
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183"
Expand All @@ -6268,6 +6276,13 @@
"@types/node" "*"
"@types/responselike" "^1.0.0"

"@types/connect@*":
version "3.4.38"
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858"
integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==
dependencies:
"@types/node" "*"

"@types/cookie@^0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d"
Expand All @@ -6280,6 +6295,26 @@
dependencies:
"@types/ms" "*"

"@types/express-serve-static-core@^4.17.33":
version "4.17.43"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz#10d8444be560cb789c4735aea5eac6e5af45df54"
integrity sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==
dependencies:
"@types/node" "*"
"@types/qs" "*"
"@types/range-parser" "*"
"@types/send" "*"

"@types/express@^4.17.21":
version "4.17.21"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d"
integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "^4.17.33"
"@types/qs" "*"
"@types/serve-static" "*"

"@types/fs-extra@^11.0.1":
version "11.0.1"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.1.tgz#f542ec47810532a8a252127e6e105f487e0a6ea5"
Expand Down Expand Up @@ -6322,6 +6357,11 @@
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4"
integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==

"@types/http-errors@*":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f"
integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==

"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
Expand Down Expand Up @@ -6402,6 +6442,16 @@
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.195.tgz#bafc975b252eb6cea78882ce8a7b6bf22a6de632"
integrity sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==

"@types/mime@*":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45"
integrity sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==

"@types/mime@^1":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690"
integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==

"@types/minimatch@*":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
Expand Down Expand Up @@ -6452,6 +6502,16 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==

"@types/qs@*":
version "6.9.11"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda"
integrity sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==

"@types/range-parser@*":
version "1.2.7"
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==

"@types/react-native-vector-icons@^6.4.13":
version "6.4.13"
resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.13.tgz#28b34d15094e040718beefb67cb3eff0c4994cb6"
Expand Down Expand Up @@ -6509,6 +6569,23 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==

"@types/send@*":
version "0.17.4"
resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a"
integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==
dependencies:
"@types/mime" "^1"
"@types/node" "*"

"@types/serve-static@*":
version "1.15.5"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033"
integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==
dependencies:
"@types/http-errors" "*"
"@types/mime" "*"
"@types/node" "*"

"@types/set-cookie-parser@^2.4.0":
version "2.4.7"
resolved "https://registry.yarnpkg.com/@types/set-cookie-parser/-/set-cookie-parser-2.4.7.tgz#4a341ed1d3a922573ee54db70b6f0a6d818290e7"
Expand Down Expand Up @@ -10042,7 +10119,7 @@ express-ws@^5.0.2:
dependencies:
ws "^7.4.6"

express@^4.17.1:
express@^4.17.1, express@^4.18.2:
version "4.18.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
Expand Down

0 comments on commit 2842cdb

Please sign in to comment.