mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-03 07:03:18 +00:00
feat(app): add an experimental native desktop target
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import path from "node:path";
|
||||
import { cpSync, mkdirSync, readFileSync } from "node:fs";
|
||||
|
||||
const root = fileURLToPath(new URL("..", import.meta.url));
|
||||
const project = path.join(root, "packages/app/gpui");
|
||||
const action = process.argv[2] ?? "run";
|
||||
const extra = process.argv.slice(3);
|
||||
const artifacts = path.join(root, ".artifacts/gpui");
|
||||
mkdirSync(artifacts, { recursive: true });
|
||||
function run(command, args, env = {}) {
|
||||
const result = spawnSync(command, args, {
|
||||
cwd: project,
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
PASEO_RENDERER: "gpui",
|
||||
CARGO_BUILD_JOBS: process.env.CARGO_BUILD_JOBS ?? "4",
|
||||
...env,
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
if (result.status !== 0) process.exit(result.status ?? 1);
|
||||
}
|
||||
if (action === "install") {
|
||||
run("npm", ["install", "--workspaces=false"]);
|
||||
// npm copies file: packages. Refresh vendored source even when its version
|
||||
// did not change, so edits to the native renderer reach the next Cargo build.
|
||||
const manifest = JSON.parse(readFileSync(path.join(project, "package.json"), "utf8"));
|
||||
for (const [name, spec] of Object.entries({
|
||||
...manifest.dependencies,
|
||||
...manifest.devDependencies,
|
||||
})) {
|
||||
if (spec.startsWith("file:"))
|
||||
cpSync(path.resolve(project, spec.slice(5)), path.join(project, "node_modules", name), {
|
||||
recursive: true,
|
||||
preserveTimestamps: true,
|
||||
});
|
||||
}
|
||||
} else if (action === "bundle") {
|
||||
run("node", [
|
||||
"node_modules/react-native/cli.js",
|
||||
"bundle",
|
||||
"--platform",
|
||||
"desktop",
|
||||
"--entry-file",
|
||||
"index.js",
|
||||
"--config",
|
||||
"desktop/metro.config.js",
|
||||
"--bundle-output",
|
||||
path.join(root, ".artifacts/gpui/paseo.bundle"),
|
||||
"--sourcemap-output",
|
||||
path.join(artifacts, "paseo.bundle.map"),
|
||||
"--assets-dest",
|
||||
path.join(artifacts, "assets"),
|
||||
"--max-workers",
|
||||
"2",
|
||||
...extra,
|
||||
]);
|
||||
const map = JSON.parse(readFileSync(path.join(artifacts, "paseo.bundle.map"), "utf8"));
|
||||
const sources = map.sections
|
||||
? map.sections.flatMap((section) => section.map.sources)
|
||||
: map.sources;
|
||||
if (sources.some((source) => source.includes("/react-native-webview/")))
|
||||
throw new Error("GPUI bundle must not include WebView modules");
|
||||
for (const route of [
|
||||
"src/app/_layout.tsx",
|
||||
"src/app/open-project.tsx",
|
||||
"src/app/h/[serverId]/workspace/[workspaceId]/index.tsx",
|
||||
]) {
|
||||
if (!sources.some((source) => source.endsWith(route)))
|
||||
throw new Error(`GPUI bundle is missing Paseo route: ${route}`);
|
||||
}
|
||||
} else if (action === "build" || action === "run") {
|
||||
run(process.execPath, [fileURLToPath(import.meta.url), "bundle", "--dev", "false"]);
|
||||
run("node", ["node_modules/@react-native-gpui/cli/bin/react-native-gpui.js", "autolink"]);
|
||||
run("cargo", [action, "--manifest-path", "desktop/Cargo.toml", ...extra], {
|
||||
RN_GPUI_AUTOLINK_MANIFEST: path.join(project, "desktop/autolink/autolink.json"),
|
||||
RN_GPUI_AUTOLINK_CMAKE: path.join(project, "desktop/autolink/autolink.cmake"),
|
||||
RN_GPUI_DEV_MODE: "0",
|
||||
RN_GPUI_ASSETS_DIR: path.join(artifacts, "assets/assets"),
|
||||
RN_GPUI_BUNDLE: path.join(root, ".artifacts/gpui/paseo.bundle"),
|
||||
});
|
||||
} else {
|
||||
throw new Error(`Unknown GPUI action: ${action}`);
|
||||
}
|
||||
Reference in New Issue
Block a user