import fsp from "node:fs/promises"; import fs from "node:fs"; import path from "node:path"; import process from "node:process"; import * as child_process from "node:child_process"; console.log("Setting up project"); const argv = process.argv.slice(2); const packageManager = argv[0] ?? "pnpm"; let currentlySettingUp = ""; let needsToInstallDependencies = false; const url = new URL(import.meta.url); let projectDir = url.pathname .split("/") .filter((v) => v && v.length > 0) .join(path.sep); // This is a cheap but probably check to see if we're *not* on Windows. if (path.sep !== "\\") { // You could inline `path.sep` as "\" but why not go that extra mile // We're already using it so projectDir = path.sep + projectDir; } projectDir = path.dirname(path.resolve(projectDir)); const legacyDir = path.resolve(projectDir, ".."); function message(str) { let prefix = ""; if (!!currentlySettingUp && currentlySettingUp.trim().length >= 0) { prefix = `[${currentlySettingUp}] `; } console.log(" " + prefix + str); } console.log(` Project directory: ${projectDir} Legacy directory: ${legacyDir} `); async function symlink(to, from) { if (!fs.existsSync(from)) { message(`Creating symlink from ${from} to ${to}`); await fsp.symlink(to, from, "dir"); } else { message(`File ${from} already exists - not symlinking to ${to}`); } } // Create temporary symlinks // This step may very well be removed in the future. { currentlySettingUp = "data"; let to, from; to = path.resolve(legacyDir, "locale"); from = path.resolve(projectDir, "locales"); await symlink(to, from); to = path.resolve(legacyDir, "public"); from = path.resolve(projectDir, "static"); await symlink(to, from); } { currentlySettingUp = "common"; const commonDir = path.resolve(projectDir, "common"); const commonDistDir = path.resolve(commonDir, "dist"); if (!fs.existsSync(commonDistDir)) { message("Building common package"); child_process.spawnSync(packageManager, ["run", "build"], { cwd: commonDir, stdio: "inherit", }); } } { currentlySettingUp = "backend"; const backendDir = path.resolve(projectDir, "backend"); const envFile = path.resolve(backendDir, ".env"), exampleEnvFile = path.resolve(backendDir, "example.env"); if (!fs.existsSync(envFile)) { message(`Missing .env file for backend, creating from example.env`); await fsp.cp(exampleEnvFile, envFile); } else { message(`Environment file already exists, continuing`); } const prismaDistDir = path.resolve(backendDir, "prisma", "dist"); if (!fs.existsSync(prismaDistDir)) { message("Generating Prisma client"); child_process.spawnSync(packageManager, ["run", "db:generate"], { cwd: backendDir, stdio: "inherit", }); } else { message("Prisma client has already been generated and is not broken"); } // This is a cheap fix for a bug that occurs when the .prisma/client // package has already been linked, but the target (prisma/dist) doesn't exist const prismaClientFile = path.resolve( backendDir, "node_modules", ".prisma", "client" ); let shouldFixPrismaClient = true; if (fs.existsSync(prismaClientFile)) { shouldFixPrismaClient &&= !( await fsp.stat(prismaClientFile) ).isDirectory(); } if (shouldFixPrismaClient) { message("Fixing .prisma/client package"); if (fs.existsSync(prismaClientFile)) { await fsp.rm(prismaClientFile); } needsToInstallDependencies = true; } } { currentlySettingUp = "finalise"; if (needsToInstallDependencies) { message("Installing dependencies"); child_process.spawnSync(packageManager, ["install"], { cwd: projectDir, stdio: "inherit", }); } } console.log(`\nDone!`);