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:
@@ -9,8 +9,9 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { spawn } from "node:child_process";
|
||||
import { gitAddAll, gitCommit } from "../utils/git_utils";
|
||||
import { simpleSpawn } from "../utils/simpleSpawn";
|
||||
|
||||
const logger = log.scope("app_upgrade_handlers");
|
||||
export const logger = log.scope("app_upgrade_handlers");
|
||||
const handle = createLoggedHandler(logger);
|
||||
|
||||
const availableUpgrades: Omit<AppUpgrade, "isNeeded">[] = [
|
||||
@@ -21,6 +22,13 @@ const availableUpgrades: Omit<AppUpgrade, "isNeeded">[] = [
|
||||
"Installs the Dyad component tagger Vite plugin and its dependencies.",
|
||||
manualUpgradeUrl: "https://dyad.sh/docs/upgrades/select-component",
|
||||
},
|
||||
{
|
||||
id: "capacitor",
|
||||
title: "Upgrade to hybrid mobile app with Capacitor",
|
||||
description:
|
||||
"Adds Capacitor to your app lets it run on iOS and Android in addition to the web.",
|
||||
manualUpgradeUrl: "https://dyad.sh/docs/guides/mobile-app#upgrade-your-app",
|
||||
},
|
||||
];
|
||||
|
||||
async function getApp(appId: number) {
|
||||
@@ -33,6 +41,13 @@ async function getApp(appId: number) {
|
||||
return app;
|
||||
}
|
||||
|
||||
function isViteApp(appPath: string): boolean {
|
||||
const viteConfigPathJs = path.join(appPath, "vite.config.js");
|
||||
const viteConfigPathTs = path.join(appPath, "vite.config.ts");
|
||||
|
||||
return fs.existsSync(viteConfigPathTs) || fs.existsSync(viteConfigPathJs);
|
||||
}
|
||||
|
||||
function isComponentTaggerUpgradeNeeded(appPath: string): boolean {
|
||||
const viteConfigPathJs = path.join(appPath, "vite.config.js");
|
||||
const viteConfigPathTs = path.join(appPath, "vite.config.ts");
|
||||
@@ -55,6 +70,29 @@ function isComponentTaggerUpgradeNeeded(appPath: string): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
function isCapacitorUpgradeNeeded(appPath: string): boolean {
|
||||
// Check if it's a Vite app first
|
||||
if (!isViteApp(appPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if Capacitor is already installed
|
||||
const capacitorConfigJs = path.join(appPath, "capacitor.config.js");
|
||||
const capacitorConfigTs = path.join(appPath, "capacitor.config.ts");
|
||||
const capacitorConfigJson = path.join(appPath, "capacitor.config.json");
|
||||
|
||||
// If any Capacitor config exists, the upgrade is not needed
|
||||
if (
|
||||
fs.existsSync(capacitorConfigJs) ||
|
||||
fs.existsSync(capacitorConfigTs) ||
|
||||
fs.existsSync(capacitorConfigJson)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function applyComponentTagger(appPath: string) {
|
||||
const viteConfigPathJs = path.join(appPath, "vite.config.js");
|
||||
const viteConfigPathTs = path.join(appPath, "vite.config.ts");
|
||||
@@ -157,6 +195,59 @@ async function applyComponentTagger(appPath: string) {
|
||||
}
|
||||
}
|
||||
|
||||
async function applyCapacitor({
|
||||
appName,
|
||||
appPath,
|
||||
}: {
|
||||
appName: string;
|
||||
appPath: string;
|
||||
}) {
|
||||
// Install Capacitor dependencies
|
||||
await simpleSpawn({
|
||||
command:
|
||||
"pnpm add @capacitor/core @capacitor/cli @capacitor/ios @capacitor/android || npm install @capacitor/core @capacitor/cli @capacitor/ios @capacitor/android --legacy-peer-deps",
|
||||
cwd: appPath,
|
||||
successMessage: "Capacitor dependencies installed successfully",
|
||||
errorPrefix: "Failed to install Capacitor dependencies",
|
||||
});
|
||||
|
||||
// Initialize Capacitor
|
||||
await simpleSpawn({
|
||||
command: `npx cap init "${appName}" "com.example.${appName.toLowerCase().replace(/[^a-z0-9]/g, "")}" --web-dir=dist`,
|
||||
cwd: appPath,
|
||||
successMessage: "Capacitor initialized successfully",
|
||||
errorPrefix: "Failed to initialize Capacitor",
|
||||
});
|
||||
|
||||
// Add iOS and Android platforms
|
||||
await simpleSpawn({
|
||||
command: "npx cap add ios && npx cap add android",
|
||||
cwd: appPath,
|
||||
successMessage: "iOS and Android platforms added successfully",
|
||||
errorPrefix: "Failed to add iOS and Android platforms",
|
||||
});
|
||||
|
||||
// Commit changes
|
||||
try {
|
||||
logger.info("Staging and committing Capacitor changes");
|
||||
await gitAddAll({ path: appPath });
|
||||
await gitCommit({
|
||||
path: appPath,
|
||||
message: "[dyad] add Capacitor for mobile app support",
|
||||
});
|
||||
logger.info("Successfully committed Capacitor changes");
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
`Failed to commit changes. This may happen if the project is not in a git repository, or if there are no changes to commit.`,
|
||||
err,
|
||||
);
|
||||
throw new Error(
|
||||
"Failed to commit Capacitor changes. Please commit them manually. Error: " +
|
||||
err,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function registerAppUpgradeHandlers() {
|
||||
handle(
|
||||
"get-app-upgrades",
|
||||
@@ -168,6 +259,8 @@ export function registerAppUpgradeHandlers() {
|
||||
let isNeeded = false;
|
||||
if (upgrade.id === "component-tagger") {
|
||||
isNeeded = isComponentTaggerUpgradeNeeded(appPath);
|
||||
} else if (upgrade.id === "capacitor") {
|
||||
isNeeded = isCapacitorUpgradeNeeded(appPath);
|
||||
}
|
||||
return { ...upgrade, isNeeded };
|
||||
});
|
||||
@@ -188,6 +281,8 @@ export function registerAppUpgradeHandlers() {
|
||||
|
||||
if (upgradeId === "component-tagger") {
|
||||
await applyComponentTagger(appPath);
|
||||
} else if (upgradeId === "capacitor") {
|
||||
await applyCapacitor({ appName: app.name, appPath });
|
||||
} else {
|
||||
throw new Error(`Unknown upgrade id: ${upgradeId}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user