Open History to see the last commit
1const fs = require("node:fs");
2const path = require("node:path");
3const { pathToFileURL } = require("node:url");
4const { getDefaultConfig } = require("expo/metro-config");
5const { withUniwindConfig } = require("uniwind/metro");
6const extraThemes = require("./generated-uniwind-theme-names.json");
7
8/** @type {import("expo/metro-config").MetroConfig} */
9const config = getDefaultConfig(__dirname);
10const workspaceRoot = path.resolve(__dirname, "../..");
11const generatedLicenseModuleRoot = path.join(__dirname, ".generated", "third-party-licenses");
12const licenseGeneratorSource = path.join(
13 workspaceRoot,
14 "scripts",
15 "lib",
16 "third-party-licenses.ts",
17);
18const escapedWorkspaceRoot = workspaceRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
19const generatedDeviceStreamRoot = path.join(__dirname, ".generated", "device-stream");
20const generatedPreviewStreamRoot = path.join(__dirname, ".generated", "preview-stream");
21
22config.watchFolders = [...new Set([...(config.watchFolders ?? []), workspaceRoot])];
23config.resolver = {
24 ...config.resolver,
25 blockList: [
26 ...(Array.isArray(config.resolver?.blockList)
27 ? config.resolver.blockList
28 : config.resolver?.blockList
29 ? [config.resolver.blockList]
30 : []),
31 new RegExp(`${escapedWorkspaceRoot}[/\\\\]\\.t3[/\\\\].*`),
32 ],
33 extraNodeModules: {
34 ...config.resolver?.extraNodeModules,
35 "@t3tools/mobile-third-party-licenses": generatedLicenseModuleRoot,
36 "@t3tools/mobile-device-stream": generatedDeviceStreamRoot,
37 "@t3tools/mobile-preview-stream": generatedPreviewStreamRoot,
38 },
39};
40
41async function writeFileIfChanged(filePath, contents) {
42 try {
43 if ((await fs.promises.readFile(filePath, "utf8")) === contents) return;
44 } catch (error) {
45 if (error?.code !== "ENOENT") throw error;
46 }
47 await fs.promises.writeFile(filePath, contents, "utf8");
48}
49
50async function generateMobileThirdPartyLicenses() {
51 await fs.promises.mkdir(generatedLicenseModuleRoot, { recursive: true });
52 const generatorVersion = (await fs.promises.stat(licenseGeneratorSource)).mtimeMs;
53 const { generateThirdPartyLicenseManifest } = await import(
54 `${pathToFileURL(licenseGeneratorSource).href}?version=${String(generatorVersion)}`
55 );
56 const manifest = await generateThirdPartyLicenseManifest({
57 configFile: path.join(workspaceRoot, "third-party-licenses.config.json"),
58 packageManifests: [{ bundle: "mobile", path: path.join(__dirname, "package.json") }],
59 });
60
61 await Promise.all([
62 writeFileIfChanged(
63 path.join(generatedLicenseModuleRoot, "index.js"),
64 `module.exports = ${JSON.stringify(manifest)};\n`,
65 ),
66 writeFileIfChanged(
67 path.join(generatedLicenseModuleRoot, "package.json"),
68 '{"main":"index.js"}\n',
69 ),
70 ]);
71}
72
73async function prepareStreamScripts() {
74 const { generateDeviceStreamScript, generatePreviewStreamScript } = await import(
75 pathToFileURL(path.join(__dirname, "scripts", "generate-device-stream.mts")).href
76 );
77 const generateAll = () =>
78 Promise.all([generateDeviceStreamScript(), generatePreviewStreamScript()]);
79 await generateAll();
80 if (process.env.NODE_ENV !== "production") {
81 let rebuild = Promise.resolve();
82 for (const [directory, files, generate] of [
83 [
84 "apps/mobile/src/features/devices",
85 ["device-stream.browser.ts"],
86 generateDeviceStreamScript,
87 ],
88 [
89 "apps/mobile/src/features/browser",
90 ["preview-stream.browser.ts"],
91 generatePreviewStreamScript,
92 ],
93 ["packages/client-runtime/src/device", ["stream.ts", "hubAccess.ts"], generateAll],
94 [
95 "packages/client-runtime/src/preview",
96 ["serverBrowserStream.ts"],
97 generatePreviewStreamScript,
98 ],
99 ]) {
100 fs.watch(path.join(workspaceRoot, directory), { persistent: false }, (_event, filename) => {
101 if (filename && !files.includes(String(filename))) return;
102 rebuild = rebuild
103 .then(generate)
104 .then(() => undefined)
105 .catch((error) => {
106 console.error("Could not rebuild a WebView stream script:", error);
107 });
108 });
109 }
110 }
111}
112
113module.exports = Promise.all([generateMobileThirdPartyLicenses(), prepareStreamScripts()]).then(
114 () =>
115 withUniwindConfig(config, {
116 cssEntryFile: "./global.css",
117 extraThemes,
118 polyfills: { rem: 14 },
119 }),
120);