Add Capacitor support (#483)

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
Will Chen
2025-06-24 14:35:05 -07:00
committed by GitHub
parent 4ec35f1d6e
commit 47f3ec460a
12 changed files with 8432 additions and 4 deletions

View File

@@ -0,0 +1,121 @@
import { createLoggedHandler } from "./safe_handle";
import log from "electron-log";
import { db } from "../../db";
import { apps } from "../../db/schema";
import { eq } from "drizzle-orm";
import { getDyadAppPath } from "../../paths/paths";
import fs from "node:fs";
import path from "node:path";
import { simpleSpawn } from "../utils/simpleSpawn";
import { IS_TEST_BUILD } from "../utils/test_utils";
const logger = log.scope("capacitor_handlers");
const handle = createLoggedHandler(logger);
async function getApp(appId: number) {
const app = await db.query.apps.findFirst({
where: eq(apps.id, appId),
});
if (!app) {
throw new Error(`App with id ${appId} not found`);
}
return app;
}
function isCapacitorInstalled(appPath: string): boolean {
const capacitorConfigJs = path.join(appPath, "capacitor.config.js");
const capacitorConfigTs = path.join(appPath, "capacitor.config.ts");
const capacitorConfigJson = path.join(appPath, "capacitor.config.json");
return (
fs.existsSync(capacitorConfigJs) ||
fs.existsSync(capacitorConfigTs) ||
fs.existsSync(capacitorConfigJson)
);
}
export function registerCapacitorHandlers() {
handle(
"is-capacitor",
async (_, { appId }: { appId: number }): Promise<boolean> => {
const app = await getApp(appId);
const appPath = getDyadAppPath(app.path);
return isCapacitorInstalled(appPath);
},
);
handle(
"sync-capacitor",
async (_, { appId }: { appId: number }): Promise<void> => {
const app = await getApp(appId);
const appPath = getDyadAppPath(app.path);
if (!isCapacitorInstalled(appPath)) {
throw new Error("Capacitor is not installed in this app");
}
await simpleSpawn({
command: "npm run build",
cwd: appPath,
successMessage: "App built successfully",
errorPrefix: "Failed to build app",
});
await simpleSpawn({
command: "npx cap sync",
cwd: appPath,
successMessage: "Capacitor sync completed successfully",
errorPrefix: "Failed to sync Capacitor",
});
},
);
handle("open-ios", async (_, { appId }: { appId: number }): Promise<void> => {
const app = await getApp(appId);
const appPath = getDyadAppPath(app.path);
if (!isCapacitorInstalled(appPath)) {
throw new Error("Capacitor is not installed in this app");
}
if (IS_TEST_BUILD) {
// In test mode, just log the action instead of actually opening Xcode
logger.info("Test mode: Simulating opening iOS project in Xcode");
return;
}
await simpleSpawn({
command: "npx cap open ios",
cwd: appPath,
successMessage: "iOS project opened successfully",
errorPrefix: "Failed to open iOS project",
});
});
handle(
"open-android",
async (_, { appId }: { appId: number }): Promise<void> => {
const app = await getApp(appId);
const appPath = getDyadAppPath(app.path);
if (!isCapacitorInstalled(appPath)) {
throw new Error("Capacitor is not installed in this app");
}
if (IS_TEST_BUILD) {
// In test mode, just log the action instead of actually opening Android Studio
logger.info(
"Test mode: Simulating opening Android project in Android Studio",
);
return;
}
await simpleSpawn({
command: "npx cap open android",
cwd: appPath,
successMessage: "Android project opened successfully",
errorPrefix: "Failed to open Android project",
});
},
);
}