Split codebase (#455)

This commit is contained in:
Gregory Schier
2026-05-07 15:50:10 -07:00
committed by GitHub
parent d2dc719cc6
commit 10559c8f4f
742 changed files with 7686 additions and 3249 deletions

View File

@@ -40,13 +40,19 @@ if (fs.existsSync(envLocalPath)) {
console.log("Detected new worktree - configuring ports in .env.local");
// Find the highest ports in use across all worktrees
// Main worktree (first in list) is assumed to use default ports 1420/64343
const CLIENT_PORT_BASE = 1420;
const PROXY_PORT_BASE = 2420; // Keep proxy +1000 from client to avoid cross-app conflicts
// Find the highest worktree index and MCP port in use across all worktrees.
// Main worktree (first in list) is assumed to use index 0:
// client=1420, proxy=2420, mcp=64343.
let maxMcpPort = 64343;
let maxDevPort = 1420;
let maxWorktreeIndex = 0;
try {
const worktreeList = execSync("git worktree list --porcelain", { encoding: "utf8" });
const worktreeList = execSync("git worktree list --porcelain", {
encoding: "utf8",
});
const worktreePaths = worktreeList
.split("\n")
.filter((line) => line.startsWith("worktree "))
@@ -68,24 +74,37 @@ try {
}
}
const devMatch = content.match(/^YAAK_DEV_PORT=(\d+)/m);
if (devMatch) {
const port = parseInt(devMatch[1], 10);
if (port > maxDevPort) {
maxDevPort = port;
const clientDevMatch = content.match(/^(?:YAAK_CLIENT_DEV_PORT|YAAK_DEV_PORT)=(\d+)/m);
if (clientDevMatch) {
const port = parseInt(clientDevMatch[1], 10);
const index = port - CLIENT_PORT_BASE;
if (index > maxWorktreeIndex) {
maxWorktreeIndex = index;
}
}
const proxyDevMatch = content.match(/^YAAK_PROXY_DEV_PORT=(\d+)/m);
if (proxyDevMatch) {
const port = parseInt(proxyDevMatch[1], 10);
const index = port - PROXY_PORT_BASE;
if (index > maxWorktreeIndex) {
maxWorktreeIndex = index;
}
}
}
}
// Increment to get the next available port
maxDevPort++;
// Increment MCP to get the next available port
maxMcpPort++;
} catch (err) {
console.error("Warning: Could not check other worktrees for port conflicts:", err.message);
// Continue with default ports
}
const nextWorktreeIndex = maxWorktreeIndex + 1;
const nextClientDevPort = CLIENT_PORT_BASE + nextWorktreeIndex;
const nextProxyDevPort = PROXY_PORT_BASE + nextWorktreeIndex;
// Get worktree name from current directory
const worktreeName = path.basename(process.cwd());
@@ -93,8 +112,11 @@ const worktreeName = path.basename(process.cwd());
const envContent = `# Auto-generated by git post-checkout hook
# This file configures ports for this worktree to avoid conflicts
# Vite dev server port (main worktree uses 1420)
YAAK_DEV_PORT=${maxDevPort}
# Vite dev server port for the client app (main worktree uses ${CLIENT_PORT_BASE})
YAAK_CLIENT_DEV_PORT=${nextClientDevPort}
# Vite dev server port for the proxy app (main worktree uses ${PROXY_PORT_BASE})
YAAK_PROXY_DEV_PORT=${nextProxyDevPort}
# MCP Server port (main worktree uses 64343)
YAAK_PLUGIN_MCP_SERVER_PORT=${maxMcpPort}
@@ -102,30 +124,58 @@ YAAK_PLUGIN_MCP_SERVER_PORT=${maxMcpPort}
fs.writeFileSync(envLocalPath, envContent, "utf8");
console.log(
`Created .env.local with YAAK_DEV_PORT=${maxDevPort} and YAAK_PLUGIN_MCP_SERVER_PORT=${maxMcpPort}`,
`Created .env.local with YAAK_CLIENT_DEV_PORT=${nextClientDevPort}, YAAK_PROXY_DEV_PORT=${nextProxyDevPort}, and YAAK_PLUGIN_MCP_SERVER_PORT=${maxMcpPort}`,
);
// Create tauri.worktree.conf.json with unique app identifier for complete isolation
// This gives each worktree its own app data directory, avoiding the need for DB path prefixes
const tauriWorktreeConfig = {
const clientTauriWorktreeConfig = {
identifier: `app.yaak.desktop.dev.${worktreeName}`,
productName: `Daak (${worktreeName})`,
};
const tauriConfigPath = path.join(
const clientTauriConfigPath = path.join(
process.cwd(),
"crates-tauri",
"yaak-app",
"yaak-app-client",
"tauri.worktree.conf.json",
);
fs.writeFileSync(tauriConfigPath, JSON.stringify(tauriWorktreeConfig, null, 2) + "\n", "utf8");
console.log(`Created tauri.worktree.conf.json with identifier: ${tauriWorktreeConfig.identifier}`);
fs.writeFileSync(
clientTauriConfigPath,
JSON.stringify(clientTauriWorktreeConfig, null, 2) + "\n",
"utf8",
);
console.log(
`Created client tauri.worktree.conf.json with identifier: ${clientTauriWorktreeConfig.identifier}`,
);
const proxyTauriWorktreeConfig = {
identifier: `app.yaak.proxy.dev.${worktreeName}`,
productName: `Yaak Proxy (${worktreeName})`,
};
const proxyTauriConfigPath = path.join(
process.cwd(),
"crates-tauri",
"yaak-app-proxy",
"tauri.worktree.conf.json",
);
fs.writeFileSync(
proxyTauriConfigPath,
JSON.stringify(proxyTauriWorktreeConfig, null, 2) + "\n",
"utf8",
);
console.log(
`Created proxy tauri.worktree.conf.json with identifier: ${proxyTauriWorktreeConfig.identifier}`,
);
// Copy gitignored editor config folders from main worktree (.zed, .vscode, .claude, etc.)
// This ensures your editor settings, tasks, and configurations are available in the new worktree
// without needing to manually copy them or commit them to git.
try {
const worktreeList = execSync("git worktree list --porcelain", { encoding: "utf8" });
const worktreeList = execSync("git worktree list --porcelain", {
encoding: "utf8",
});
const mainWorktreePath = worktreeList
.split("\n")
.find((line) => line.startsWith("worktree "))

View File

@@ -6,7 +6,7 @@ if (!version) {
throw new Error("YAAK_VERSION environment variable not set");
}
const tauriConfigPath = path.join(__dirname, "../crates-tauri/yaak-app/tauri.conf.json");
const tauriConfigPath = path.join(__dirname, "../crates-tauri/yaak-app-client/tauri.conf.json");
const tauriConfig = JSON.parse(fs.readFileSync(tauriConfigPath, "utf8"));
tauriConfig.version = version;

62
scripts/run-build.mjs Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env node
/**
* Runs a Tauri app build from the app directory so relative config paths and
* beforeBuildCommand entries resolve consistently.
*/
import { spawnSync } from "child_process";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const rootDir = path.join(__dirname, "..");
const [appName = "client", ...additionalArgs] = process.argv.slice(2);
const appConfigs = {
client: {
appDir: "crates-tauri/yaak-app-client",
tauriConfig: "tauri.conf.json",
},
proxy: {
appDir: "crates-tauri/yaak-app-proxy",
tauriConfig: "tauri.conf.json",
},
};
const appConfig = appConfigs[appName];
if (appConfig == null) {
console.error(`Unknown Tauri app "${appName}"`);
process.exit(1);
}
// Normalize extra `--config` path args to absolute paths from repo root so
// callers can keep passing root-relative config files.
const normalizedAdditionalArgs = [];
for (let i = 0; i < additionalArgs.length; i++) {
const arg = additionalArgs[i];
if (arg === "--config" && i + 1 < additionalArgs.length) {
const value = additionalArgs[i + 1];
const isInlineJson = value.trimStart().startsWith("{");
normalizedAdditionalArgs.push("--config");
normalizedAdditionalArgs.push(
!isInlineJson && !path.isAbsolute(value) ? path.join(rootDir, value) : value,
);
i++;
continue;
}
normalizedAdditionalArgs.push(arg);
}
const tauriJs = path.join(rootDir, "node_modules", "@tauri-apps", "cli", "tauri.js");
const result = spawnSync(
process.execPath,
[tauriJs, "build", "--config", appConfig.tauriConfig, ...normalizedAdditionalArgs],
{
cwd: path.join(rootDir, appConfig.appDir),
stdio: "inherit",
env: process.env,
},
);
process.exit(result.status || 0);

View File

@@ -1,8 +1,7 @@
#!/usr/bin/env node
/**
* Script to run Tauri dev server with dynamic port configuration.
* Loads port from .env.local if present, otherwise uses default port 1420.
* Script to run a Tauri app dev server with dynamic port configuration.
*/
import { spawnSync } from "child_process";
@@ -31,26 +30,75 @@ if (fs.existsSync(envLocalPath)) {
Object.assign(process.env, envVars);
}
const port = process.env.YAAK_DEV_PORT || "1420";
const config = JSON.stringify({ build: { devUrl: `http://localhost:${port}` } });
const [appName = "client", ...additionalArgs] = process.argv.slice(2);
const appConfigs = {
client: {
appDir: "crates-tauri/yaak-app-client",
devPortEnv: "YAAK_CLIENT_DEV_PORT",
fallbackDevPortEnv: "YAAK_DEV_PORT",
defaultPort: "1420",
tauriConfig: "tauri.conf.json",
tauriDevConfig: "tauri.development.conf.json",
},
proxy: {
appDir: "crates-tauri/yaak-app-proxy",
devPortEnv: "YAAK_PROXY_DEV_PORT",
fallbackDevPortEnv: null,
defaultPort: "2420",
tauriConfig: "tauri.conf.json",
tauriDevConfig: "tauri.development.conf.json",
},
};
// Get additional arguments passed after npm run app-dev --
const additionalArgs = process.argv.slice(2);
const appConfig = appConfigs[appName];
if (appConfig == null) {
console.error(`Unknown Tauri app "${appName}"`);
process.exit(1);
}
const port =
process.env[appConfig.devPortEnv] ||
(appConfig.fallbackDevPortEnv ? process.env[appConfig.fallbackDevPortEnv] : undefined) ||
appConfig.defaultPort;
const config = JSON.stringify({
build: { devUrl: `http://localhost:${port}` },
});
// Normalize extra `--config` path args to absolute paths from repo root so
// callers can keep passing root-relative config files.
const normalizedAdditionalArgs = [];
for (let i = 0; i < additionalArgs.length; i++) {
const arg = additionalArgs[i];
if (arg === "--config" && i + 1 < additionalArgs.length) {
const value = additionalArgs[i + 1];
const isInlineJson = value.trimStart().startsWith("{");
normalizedAdditionalArgs.push("--config");
normalizedAdditionalArgs.push(
!isInlineJson && !path.isAbsolute(value) ? path.join(rootDir, value) : value,
);
i++;
continue;
}
normalizedAdditionalArgs.push(arg);
}
const args = [
"dev",
"--no-watch",
"--config",
"crates-tauri/yaak-app/tauri.development.conf.json",
appConfig.tauriConfig,
"--config",
appConfig.tauriDevConfig,
"--config",
config,
...additionalArgs,
...normalizedAdditionalArgs,
];
// Invoke the tauri CLI JS entry point directly via node to avoid shell escaping issues on Windows
const tauriJs = path.join(rootDir, "node_modules", "@tauri-apps", "cli", "tauri.js");
const result = spawnSync(process.execPath, [tauriJs, ...args], {
cwd: path.join(rootDir, appConfig.appDir),
stdio: "inherit",
env: process.env,
});

View File

@@ -1,7 +1,8 @@
#!/usr/bin/env node
/**
* Runs `npm run dev` in parallel for all workspaces that have a dev script.
* Runs `npm run dev` in parallel for the provided workspaces, or all
* workspaces with a dev script when none are specified.
* Handles cleanup of child processes on exit.
*/
@@ -17,8 +18,11 @@ const rootDir = path.join(__dirname, "..");
const rootPkg = JSON.parse(fs.readFileSync(path.join(rootDir, "package.json"), "utf8"));
const workspaces = rootPkg.workspaces || [];
// Find all workspaces with a dev script
const workspacesWithDev = workspaces.filter((ws) => {
const requestedWorkspaces = process.argv.slice(2);
const workspaceCandidates = requestedWorkspaces.length > 0 ? requestedWorkspaces : workspaces;
// Find all candidate workspaces with a dev script
const workspacesWithDev = workspaceCandidates.filter((ws) => {
const pkgPath = path.join(rootDir, ws, "package.json");
if (!fs.existsSync(pkgPath)) return false;
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
@@ -52,7 +56,7 @@ for (const ws of workspacesWithDev) {
// Cleanup function to kill all children
function cleanup() {
for (const { child } of children) {
for (const { ws: _ws, child } of children) {
if (child.exitCode === null) {
// Process still running
if (process.platform === "win32") {

View File

@@ -54,7 +54,7 @@ const SHA256_MAP = {
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
const destDir = path.join(__dirname, `..`, "crates-tauri", "yaak-app", "vendored", "node");
const destDir = path.join(__dirname, `..`, "crates-tauri", "yaak-app-client", "vendored", "node");
const binDest = path.join(destDir, DST_BIN_MAP[key]);
console.log(`Vendoring NodeJS ${NODE_VERSION} for ${key}`);

View File

@@ -23,9 +23,19 @@ for (const name of readdirSync(pluginsDir)) {
console.log(`Skipping ${name} (external plugin)`);
continue;
}
const destDir = path.join(__dirname, "../crates-tauri/yaak-app/vendored/plugins/", name);
const destDir = path.join(
__dirname,
"..",
"crates-tauri",
"yaak-app-client",
"vendored",
"plugins",
name,
);
mkdirSync(destDir, { recursive: true });
console.log(`Copying ${name} to ${destDir}`);
cpSync(path.join(dir, "package.json"), path.join(destDir, "package.json"));
cpSync(path.join(dir, "build"), path.join(destDir, "build"), { recursive: true });
cpSync(path.join(dir, "build"), path.join(destDir, "build"), {
recursive: true,
});
}

View File

@@ -52,7 +52,7 @@ const SHA256_MAP = {
[WIN_ARM]: "d7a207fb6eec0e4b1b6613be3b7d11905375b6fd1147a071116eb8e9f24ac53b",
};
const dstDir = path.join(__dirname, `..`, "crates-tauri", "yaak-app", "vendored", "protoc");
const dstDir = path.join(__dirname, `..`, "crates-tauri", "yaak-app-client", "vendored", "protoc");
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
console.log(`Vendoring protoc ${VERSION} for ${key}`);