create-nttb
Version:
An opinionated Next.js, TypeScript, and Tailwind boilerplate using Atomic Design Methodology for presentation components.
154 lines • 5.43 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateProjectName = validateProjectName;
exports.checkNodeVersion = checkNodeVersion;
exports.checkNpmVersion = checkNpmVersion;
exports.createProjectDirectory = createProjectDirectory;
exports.runCommand = runCommand;
exports.copyTemplate = copyTemplate;
exports.getCreateNttbVersion = getCreateNttbVersion;
exports.updatePackageJson = updatePackageJson;
exports.main = main;
const child_process_1 = require("child_process");
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
function writeLine(msg) {
const width = process.stdout.columns || 80;
const blank = " ".repeat(width);
process.stdout.write(`\r${blank}\r${msg}`);
}
function clearLine() {
const width = process.stdout.columns || 80;
const blank = " ".repeat(width);
process.stdout.write(`\r${blank}\r`);
}
function step(label) {
writeLine(label + "...");
}
function doneStep() {
clearLine();
}
function validateProjectName(name) {
if (!/^[a-z0-9]([a-z0-9-_]*[a-z0-9])?$/i.test(name)) {
throw new Error(`Invalid project name "${name}". Use only letters, numbers, hyphens, and underscores.`);
}
if (name.length > 214) {
throw new Error("Project name must be 214 characters or fewer.");
}
}
function checkNodeVersion(minMajor = 20) {
const [major] = process.version.replace("v", "").split(".");
if (Number(major) < minMajor) {
throw new Error(`Node.js v${minMajor}+ required`);
}
}
function checkNpmVersion(minMajor = 10) {
let version;
try {
version = (0, child_process_1.execSync)("npm --version", { encoding: "utf8" }).trim();
}
catch {
throw new Error("npm is not installed or not accessible.");
}
const [major] = version.split(".");
if (Number(major) < minMajor) {
throw new Error(`npm v${minMajor}+ required (found v${version})`);
}
}
function createProjectDirectory(projectPath) {
if (fs_1.default.existsSync(projectPath)) {
if (fs_1.default.readdirSync(projectPath).length === 0)
return;
throw new Error(`Directory "${path_1.default.basename(projectPath)}" exists and is not empty.`);
}
fs_1.default.mkdirSync(projectPath, { recursive: true });
}
function runCommand(command, args = [], options = {}) {
const result = (0, child_process_1.spawnSync)(command, args, { stdio: "inherit", ...options });
if (!result || typeof result !== "object") {
throw new Error(`${command} failed`);
}
if (result.error) {
throw new Error(result.error.message || `${command} failed`);
}
if (result.status !== 0) {
throw new Error(`${command} failed`);
}
}
function copyTemplate(templateDir, projectPath) {
fs_1.default.cpSync(templateDir, projectPath, { recursive: true });
}
function getCreateNttbVersion() {
const rootPackageJsonPath = path_1.default.join(__dirname, "..", "package.json");
const rootPkg = JSON.parse(fs_1.default.readFileSync(rootPackageJsonPath, "utf8"));
if (!rootPkg.version) {
throw new Error("Could not determine create-nttb version from root package.json.");
}
return rootPkg.version;
}
function updatePackageJson(projectPath, projectName) {
const file = path_1.default.join(projectPath, "package.json");
const pkg = JSON.parse(fs_1.default.readFileSync(file, "utf8"));
const createNttbVersion = getCreateNttbVersion();
const updated = {
...pkg,
name: projectName,
version: "1.0.0",
description: `${projectName} app`,
private: true,
createNttbVersion,
keywords: [
"create-nttb",
"nextjs",
"react",
"typescript",
"tailwindcss",
"boilerplate",
projectName,
],
};
fs_1.default.writeFileSync(file, JSON.stringify(updated, null, 2) + "\n");
}
async function main(name) {
if (!name) {
throw new Error("Please provide a project name.");
}
const projectPath = path_1.default.join(process.cwd(), name);
const templateDir = path_1.default.join(__dirname, "..", "template");
try {
step("Validating project name");
validateProjectName(name);
doneStep();
step("Checking Node version");
checkNodeVersion();
doneStep();
step("Checking npm version");
checkNpmVersion();
doneStep();
step("Creating project");
createProjectDirectory(projectPath);
doneStep();
step("Copying template");
copyTemplate(templateDir, projectPath);
doneStep();
step("Updating package.json");
updatePackageJson(projectPath, name);
doneStep();
step("Installing packages");
runCommand("npm", ["install"], { cwd: projectPath });
doneStep();
clearLine();
console.log(`\nInstallation complete\n\nNext steps:\n\ncd ${name}\nnpm run dev\n`);
}
catch (err) {
clearLine();
if (fs_1.default.existsSync(projectPath)) {
fs_1.default.rmSync(projectPath, { recursive: true, force: true });
}
throw err;
}
}
//# sourceMappingURL=install.js.map