UNPKG

create-vhs

Version:

Create a VHS monorepo with one command.

187 lines (178 loc) 5.66 kB
import path from "node:path"; import fs from "fs-extra"; import { glob } from "glob"; export function validateProjectName(name) { // Valid npm package name regex const validNameRegex = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/; return (validNameRegex.test(name) && name.length <= 214 && !name.startsWith(".") && !name.startsWith("_") && name === name.toLowerCase() && !name.includes(" ")); } export async function replaceTemplateVariables(projectPath, pattern, variables) { try { const files = await glob(pattern, { cwd: projectPath, ignore: ["node_modules/**", ".git/**"], }); for (const file of files) { const filePath = path.join(projectPath, file); if (await fs.pathExists(filePath)) { const stat = await fs.stat(filePath); if (stat.isFile()) { let content = await fs.readFile(filePath, "utf8"); // Replace template variables for (const [key, value] of Object.entries(variables)) { const regex = new RegExp(`{{\\s*${key}\\s*}}`, "g"); content = content.replace(regex, String(value)); } await fs.writeFile(filePath, content); } } } } catch (error) { // Ignore glob errors for non-existent patterns console.warn(`Warning: Pattern ${pattern} did not match any files`); } } export async function updatePackageJson(projectPath, projectName, options) { const packageJsonPath = path.join(projectPath, "package.json"); if (await fs.pathExists(packageJsonPath)) { const packageJson = await fs.readJson(packageJsonPath); // Update basic info packageJson.name = projectName; packageJson.version = "0.1.0"; packageJson.description = packageJson.description || `${projectName} - Generated by create-my-bun-app`; // Remove template-specific fields packageJson.repository = undefined; packageJson.bugs = undefined; packageJson.homepage = undefined; // Update scripts based on package manager if (packageJson.scripts) { const scripts = packageJson.scripts; // Update package manager commands if (options.packageManager !== "bun") { // biome-ignore lint/complexity/noForEach: <explanation> Object.keys(scripts).forEach((script) => { if (scripts[script]?.includes("bun ")) { scripts[script] = scripts[script]?.replace(/bun /g, `${options.packageManager} `); } }); } // Feature-specific scripts // if (options.features.includes("biome")) { // scripts.lint = "biome check ."; // scripts["lint:fix"] = "biome check . --apply"; // scripts.format = "biome format . --write"; // } } // Workspace configuration for monorepos if (["basic", "mini-app"].includes(options.template)) { packageJson.workspaces = ["apps/*", "packages/*"]; } await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 }); } } export async function updateTsConfig(projectPath, options) { const tsConfigPath = path.join(projectPath, "tsconfig.json"); const tsConfig = { compilerOptions: { target: "ES2022", module: "ESNext", moduleResolution: "bundler", allowImportingTsExtensions: true, allowSyntheticDefaultImports: true, esModuleInterop: true, forceConsistentCasingInFileNames: true, strict: true, noUncheckedIndexedAccess: true, skipLibCheck: true, resolveJsonModule: true, allowJs: true, jsx: "react-jsx", composite: false, incremental: true, }, include: ["**/*.ts", "**/*.tsx"], exclude: ["node_modules", "dist", "build"], }; // Remove undefined values // biome-ignore lint/complexity/noForEach: <explanation> Object.keys(tsConfig.compilerOptions).forEach((key) => { if (tsConfig.compilerOptions[key] === undefined) { delete tsConfig.compilerOptions[key]; } }); await fs.writeJson(tsConfigPath, tsConfig, { spaces: 2 }); } export async function createGitIgnore(projectPath, options) { const gitIgnoreContent = ` # Dependencies node_modules/ .pnp .pnp.js # Testing coverage/ # Build outputs dist/ build/ .next/ # Environment variables .env .env.local .env.development.local .env.test.local .env.production.local # Logs npm-debug.log* yarn-debug.log* yarn-error.log* bun.lockb # Runtime data pids *.pid *.seed *.pid.lock # IDE .vscode/ .idea/ *.swp *.swo *~ # OS .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes ehthumbs.db Thumbs.db # Turborepo .turbo/ # Docker .dockerignore `.trim(); await fs.writeFile(path.join(projectPath, ".gitignore"), gitIgnoreContent); } export function getPackageManagerCommand(packageManager) { const commands = { bun: "bun", npm: "npm run", yarn: "yarn", pnpm: "pnpm", }; return commands[packageManager] || "bun"; } export function formatProjectName(name) { return name .toLowerCase() .replace(/[^a-z0-9-]/g, "-") .replace(/^-+|-+$/g, "") .replace(/-+/g, "-"); } //# sourceMappingURL=utils.js.map