Skip to content

Commit 1393cad

Browse files
Format mobile
1 parent b87979c commit 1393cad

3 files changed

Lines changed: 100 additions & 34 deletions

File tree

app/mobile/app/login.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ import { useFocusEffect } from "@react-navigation/native";
22
import { Href, useRouter } from "expo-router";
33
import { Empty } from "google-protobuf/google/protobuf/empty_pb";
44
import { useCallback, useState } from "react";
5-
import {
6-
Appearance,
7-
BackHandler,
8-
Linking,
9-
useColorScheme,
10-
} from "react-native";
5+
import { Appearance, BackHandler, Linking, useColorScheme } from "react-native";
116
import { SafeAreaView } from "react-native-safe-area-context";
127
import { WebView } from "react-native-webview";
138

app/mobile/scripts/ota-serve.mjs

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const args = Object.fromEntries(
2020
process.argv.slice(2).reduce((acc, cur, i, a) => {
2121
if (cur.startsWith("--")) acc.push([cur.slice(2), a[i + 1]]);
2222
return acc;
23-
}, [])
23+
}, []),
2424
);
2525
const DIR = path.resolve(args.dir ?? "ota-out");
2626
const PORT = parseInt(args.port ?? "8099", 10);
@@ -43,23 +43,34 @@ const LOG_HEADERS = [
4343
function platforms() {
4444
return fs
4545
.readdirSync(DIR, { withFileTypes: true })
46-
.filter((d) => d.isDirectory() && fs.existsSync(path.join(DIR, d.name, "manifest.json")))
46+
.filter(
47+
(d) =>
48+
d.isDirectory() &&
49+
fs.existsSync(path.join(DIR, d.name, "manifest.json")),
50+
)
4751
.map((d) => d.name);
4852
}
4953

5054
function loadManifest(platform, host) {
51-
const raw = JSON.parse(fs.readFileSync(path.join(DIR, platform, "manifest.json"), "utf8"));
55+
const raw = JSON.parse(
56+
fs.readFileSync(path.join(DIR, platform, "manifest.json"), "utf8"),
57+
);
5258
const rewrite = (u) => `http://${host}${new URL(u).pathname}`;
5359
raw.launchAsset.url = rewrite(raw.launchAsset.url);
5460
raw.assets = raw.assets.map((a) => ({ ...a, url: rewrite(a.url) }));
5561
return raw;
5662
}
5763

5864
function contentTypeMap(platform) {
59-
const m = JSON.parse(fs.readFileSync(path.join(DIR, platform, "manifest.json"), "utf8"));
65+
const m = JSON.parse(
66+
fs.readFileSync(path.join(DIR, platform, "manifest.json"), "utf8"),
67+
);
6068
const map = new Map();
6169
for (const a of m.assets) map.set(a.key, a.contentType);
62-
map.set(path.basename(new URL(m.launchAsset.url).pathname), m.launchAsset.contentType);
70+
map.set(
71+
path.basename(new URL(m.launchAsset.url).pathname),
72+
m.launchAsset.contentType,
73+
);
6374
return map;
6475
}
6576

@@ -71,8 +82,16 @@ function multipartBody(manifest) {
7182
`content-type: ${contentType}\r\n\r\n` +
7283
`${body}\r\n`;
7384
const body =
74-
part("manifest", JSON.stringify(manifest), "application/json; charset=utf-8") +
75-
part("extensions", JSON.stringify({ assetRequestHeaders: {} }), "application/json") +
85+
part(
86+
"manifest",
87+
JSON.stringify(manifest),
88+
"application/json; charset=utf-8",
89+
) +
90+
part(
91+
"extensions",
92+
JSON.stringify({ assetRequestHeaders: {} }),
93+
"application/json",
94+
) +
7695
`--${boundary}--\r\n`;
7796
return { body, contentType: `multipart/mixed; boundary=${boundary}` };
7897
}
@@ -89,7 +108,11 @@ function chooseFraming(req, url) {
89108
const q = url.searchParams.get("framing");
90109
if (q === "json" || q === "multipart") return q;
91110
const accept = req.headers["accept"] ?? "";
92-
if (accept.includes("multipart/mixed") || req.headers["expo-protocol-version"]) return "multipart";
111+
if (
112+
accept.includes("multipart/mixed") ||
113+
req.headers["expo-protocol-version"]
114+
)
115+
return "multipart";
93116
return "json";
94117
}
95118

@@ -155,14 +178,17 @@ const server = http.createServer((req, res) => {
155178
const { body, contentType } = multipartBody(manifest);
156179
// OTA_NO_PROTO_HEADERS mimics raw S3, which can set content-type but not
157180
// arbitrary response headers like expo-protocol-version / expo-sfv-version.
158-
const headers = { "content-type": contentType, "cache-control": "private, max-age=0" };
181+
const headers = {
182+
"content-type": contentType,
183+
"cache-control": "private, max-age=0",
184+
};
159185
if (!process.env.OTA_NO_PROTO_HEADERS) {
160186
headers["expo-protocol-version"] = "1";
161187
headers["expo-sfv-version"] = "0";
162188
}
163189
res.writeHead(200, headers);
164190
console.log(
165-
` -> 200 multipart (${body.length} bytes)${process.env.OTA_NO_PROTO_HEADERS ? " [no proto headers / S3-mimic]" : ""}`
191+
` -> 200 multipart (${body.length} bytes)${process.env.OTA_NO_PROTO_HEADERS ? " [no proto headers / S3-mimic]" : ""}`,
166192
);
167193
res.end(body);
168194
} else {
@@ -180,8 +206,10 @@ const server = http.createServer((req, res) => {
180206

181207
// bundle / assets
182208
let filePath = null;
183-
if (parts[1] === "bundle.hbc") filePath = path.join(DIR, platform, "bundle.hbc");
184-
else if (parts[1] === "assets" && parts[2]) filePath = path.join(DIR, platform, "assets", parts[2]);
209+
if (parts[1] === "bundle.hbc")
210+
filePath = path.join(DIR, platform, "bundle.hbc");
211+
else if (parts[1] === "assets" && parts[2])
212+
filePath = path.join(DIR, platform, "assets", parts[2]);
185213

186214
if (filePath && fs.existsSync(filePath)) {
187215
const name = path.basename(filePath);
@@ -197,6 +225,8 @@ const server = http.createServer((req, res) => {
197225
});
198226

199227
server.listen(PORT, "0.0.0.0", () => {
200-
console.log(`OTA test server on http://0.0.0.0:${PORT} (platforms: ${platforms().join(", ") || "none"})`);
228+
console.log(
229+
`OTA test server on http://0.0.0.0:${PORT} (platforms: ${platforms().join(", ") || "none"})`,
230+
);
201231
console.log(`Open on the phone: http://<this-mac-LAN-ip>:${PORT}/`);
202232
});

app/mobile/scripts/ota-stage.mjs

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,16 @@ function sha256HexToUuid(buf) {
6767
return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`;
6868
}
6969

70-
function assetMetadata({ distDir, filePath, ext, isLaunchAsset, baseUrl, platform, outDir, staged }) {
70+
function assetMetadata({
71+
distDir,
72+
filePath,
73+
ext,
74+
isLaunchAsset,
75+
baseUrl,
76+
platform,
77+
outDir,
78+
staged,
79+
}) {
7180
const abs = path.join(distDir, filePath);
7281
const buf = fs.readFileSync(abs);
7382
const key = md5Hex(buf);
@@ -112,13 +121,20 @@ function main() {
112121
const metadataBuf = fs.readFileSync(path.join(distDir, "metadata.json"));
113122
const metadata = JSON.parse(metadataBuf.toString("utf8"));
114123
const pf = metadata.fileMetadata?.[platform];
115-
if (!pf) throw new Error(`No fileMetadata for platform ${platform} in metadata.json`);
124+
if (!pf)
125+
throw new Error(
126+
`No fileMetadata for platform ${platform} in metadata.json`,
127+
);
116128

117129
let expoClient = {};
118130
if (args["expo-config"]) {
119-
expoClient = JSON.parse(fs.readFileSync(path.resolve(args["expo-config"]), "utf8"));
131+
expoClient = JSON.parse(
132+
fs.readFileSync(path.resolve(args["expo-config"]), "utf8"),
133+
);
120134
} else {
121-
console.warn("WARN: no --expo-config given; extra.expoClient will be empty {}");
135+
console.warn(
136+
"WARN: no --expo-config given; extra.expoClient will be empty {}",
137+
);
122138
}
123139

124140
const staged = new Set();
@@ -132,7 +148,7 @@ function main() {
132148
platform,
133149
outDir,
134150
staged,
135-
})
151+
}),
136152
);
137153
const launchAsset = assetMetadata({
138154
distDir,
@@ -155,7 +171,10 @@ function main() {
155171
extra: { expoClient },
156172
};
157173

158-
fs.writeFileSync(path.join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2));
174+
fs.writeFileSync(
175+
path.join(outDir, "manifest.json"),
176+
JSON.stringify(manifest, null, 2),
177+
);
159178

160179
// Emit the protocol-v1 multipart/mixed framing that the dev client requires, as
161180
// a static file S3 can serve verbatim, plus the content-type (with the matching
@@ -168,18 +187,30 @@ function main() {
168187
`content-type: ${ct}\r\n\r\n` +
169188
`${body}\r\n`;
170189
const multipart =
171-
part("manifest", JSON.stringify(manifest), "application/json; charset=utf-8") +
172-
part("extensions", JSON.stringify({ assetRequestHeaders: {} }), "application/json") +
190+
part(
191+
"manifest",
192+
JSON.stringify(manifest),
193+
"application/json; charset=utf-8",
194+
) +
195+
part(
196+
"extensions",
197+
JSON.stringify({ assetRequestHeaders: {} }),
198+
"application/json",
199+
) +
173200
`--${boundary}--\r\n`;
174201
fs.writeFileSync(path.join(outDir, "manifest"), multipart);
175-
fs.writeFileSync(path.join(outDir, "manifest.content-type"), `multipart/mixed; boundary=${boundary}`);
202+
fs.writeFileSync(
203+
path.join(outDir, "manifest.content-type"),
204+
`multipart/mixed; boundary=${boundary}`,
205+
);
176206

177207
// GitHub strips custom-scheme (couchers-devtool://) links from comments, so the PR
178208
// comment links to this https page, which redirects to the dev-launcher deep link
179209
// once opened on the device.
180210
const manifestUrl = `${baseUrl}/${platform}/manifest`;
181211
const deepLink =
182-
"couchers-devtool://expo-development-client/?url=" + encodeURIComponent(manifestUrl);
212+
"couchers-devtool://expo-development-client/?url=" +
213+
encodeURIComponent(manifestUrl);
183214
const openHtml = `<!doctype html>
184215
<html lang="en">
185216
<head>
@@ -198,11 +229,21 @@ function main() {
198229
console.log(`staged ${platform} -> ${outDir}`);
199230
console.log(` id ${manifest.id}`);
200231
console.log(` runtimeVersion ${runtimeVersion}`);
201-
console.log(` launchAsset ${launchAsset.key} (${launchAsset.contentType})`);
202-
console.log(` assets ${assets.length} entries, ${staged.size - 1} unique files`);
203-
console.log(` manifest.json ${path.join(outDir, "manifest.json")} (object, for local server)`);
204-
console.log(` manifest ${path.join(outDir, "manifest")} (multipart body, for S3)`);
205-
console.log(` open.html ${path.join(outDir, "open.html")} (https -> deep link redirect)`);
232+
console.log(
233+
` launchAsset ${launchAsset.key} (${launchAsset.contentType})`,
234+
);
235+
console.log(
236+
` assets ${assets.length} entries, ${staged.size - 1} unique files`,
237+
);
238+
console.log(
239+
` manifest.json ${path.join(outDir, "manifest.json")} (object, for local server)`,
240+
);
241+
console.log(
242+
` manifest ${path.join(outDir, "manifest")} (multipart body, for S3)`,
243+
);
244+
console.log(
245+
` open.html ${path.join(outDir, "open.html")} (https -> deep link redirect)`,
246+
);
206247
}
207248

208249
main();

0 commit comments

Comments
 (0)