Move src/ → apps/server/ and packages/web/ → apps/web/ to adopt standard monorepo conventions (apps/ for runnable apps, packages/ for reusable libraries). Update all config files, shared package imports, test fixtures, and documentation to reflect new paths. Key fixes: - Update workspace config to ["apps/*", "packages/*"] - Update tsconfig.json rootDir/include for apps/server/ - Add apps/web/** to vitest exclude list - Update drizzle.config.ts schema path - Fix ensure-schema.ts migration path detection (3 levels up in dev, 2 levels up in dist) - Fix tests/integration/cli-server.test.ts import paths - Update packages/shared imports to apps/server/ paths - Update all docs/ files with new paths
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
/**
|
|
* Project Clone Management
|
|
*
|
|
* Ensures project repositories are cloned into the repos/ directory.
|
|
* These base clones are used as the source for git worktrees.
|
|
*/
|
|
|
|
import { join } from 'node:path';
|
|
import { access } from 'node:fs/promises';
|
|
import { cloneProject } from './clone.js';
|
|
import { createModuleLogger } from '../logger/index.js';
|
|
|
|
const log = createModuleLogger('git');
|
|
|
|
/**
|
|
* Derive the canonical clone directory for a project (relative to workspace root).
|
|
* Convention: repos/<sanitizedName>-<id>/
|
|
*/
|
|
export function getProjectCloneDir(projectName: string, projectId: string): string {
|
|
const sanitized = projectName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
return join('repos', `${sanitized}-${projectId}`);
|
|
}
|
|
|
|
/**
|
|
* Ensure a project's git repository is cloned to the workspace.
|
|
* Uses the canonical path: <workspaceRoot>/repos/<sanitizedName>-<id>/
|
|
*
|
|
* @param project - Project with id, name, and url
|
|
* @param workspaceRoot - Absolute path to the workspace root
|
|
* @returns Absolute path to the clone directory
|
|
*/
|
|
export async function ensureProjectClone(
|
|
project: { id: string; name: string; url: string },
|
|
workspaceRoot: string,
|
|
): Promise<string> {
|
|
const relPath = getProjectCloneDir(project.name, project.id);
|
|
const clonePath = join(workspaceRoot, relPath);
|
|
|
|
try {
|
|
await access(clonePath);
|
|
log.debug({ project: project.name, clonePath }, 'project clone already exists');
|
|
return clonePath;
|
|
} catch {
|
|
log.info({ project: project.name, url: project.url, clonePath }, 'cloning project for first time');
|
|
await cloneProject(project.url, clonePath);
|
|
return clonePath;
|
|
}
|
|
}
|