react-native-app-starter
Version:
A React Native Template.
316 lines (312 loc) • 13.3 kB
JavaScript
;
/**
* Project setup and configuration service
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const os = __importStar(require("os"));
const shell = __importStar(require("shelljs"));
const fileSystem_1 = require("../utils/fileSystem");
class ProjectService {
/**
* Adds custom scripts to package.json
* @param directory - Project directory
* @param includeHusky - Whether to include husky scripts
*/
static addScripts(directory, includeHusky) {
console.log("Adding additional scripts...");
const packageJsonPath = `${directory}/package.json`;
const packageJSON = (0, fileSystem_1.readJsonFile)(packageJsonPath);
const customScripts = {
postinstall: "./postinstall",
lint: "eslint .",
"lint:fix": "eslint . --fix",
prepare: "husky init",
"bundle-android": "npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle",
"bundle-ios": "npx react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle",
"release-ios-changelog": "bun install && bun run generate-changelog && fastlane ios beta",
"release-android-changelog": "bun install && bun run generate-changelog && fastlane android beta",
"release-ios-changelog-bump": "bun install && bun run generate-changelog-bump && fastlane ios beta",
"release-android-changelog-bump": "bun install && bun run generate-changelog-bump && fastlane android beta",
"generate-changelog": 'fastlane changelog build_changelog bump_type:"patch"',
"generate-changelog-bump": "fastlane changelog build_changelog",
"release-ios": "bun install && fastlane ios beta",
"release-android": "bun install && fastlane android beta",
release: "bun run generate-changelog && bun run release-android && bun run release-ios",
"release-bump": "bun run generate-changelog-bump && bun run release-android && bun run release-ios",
"android-clean": "cd android && ./gradlew clean && ./gradlew --stop",
"android-aab": "bun android-clean && react-native build-android --mode=release",
};
packageJSON.scripts = {
...packageJSON.scripts,
...customScripts,
};
if (!includeHusky) {
delete packageJSON.scripts?.prepare;
}
(0, fileSystem_1.writeJsonFile)(packageJsonPath, packageJSON);
console.log("Added scripts to package.json");
}
/**
* Modifies Android build.gradle file
* @param directoryName - Project directory name
*/
static modifyAndroidBuildGradle(directoryName) {
console.log("Configuring Android build.gradle...");
const buildGradlePath = `${directoryName}/android/app/build.gradle`;
try {
if (!(0, fs_1.existsSync)(buildGradlePath)) {
console.warn(`build.gradle not found at ${buildGradlePath}`);
return;
}
const buildGradleContent = (0, fs_1.readFileSync)(buildGradlePath, "utf8");
const lines = buildGradleContent.split("\n");
let lastApplyPluginIndex = -1;
// Find the last occurrence of "apply plugin"
for (let i = 0; i < lines.length; i++) {
if (lines[i].trim().startsWith("apply plugin")) {
lastApplyPluginIndex = i;
}
}
if (lastApplyPluginIndex !== -1) {
// Insert the new line after the last "apply plugin" line
lines.splice(lastApplyPluginIndex + 1, 0, "apply from: project(':react-native-config').projectDir.getPath() + \"/dotenv.gradle\"");
// Write the modified content back to the file
(0, fs_1.writeFileSync)(buildGradlePath, lines.join("\n"));
console.log("Added react-native-config dotenv.gradle to android/app/build.gradle");
}
else {
console.warn("Could not find 'apply plugin' lines in android/app/build.gradle");
}
}
catch (error) {
console.error(`Error modifying android/app/build.gradle: ${error.message}`);
}
}
/**
* Ensures tsconfig.json has compilerOptions
* @param directoryName - Project directory name
*/
static ensureTsconfigCompilerOptions(directoryName) {
const tsconfigPath = `${directoryName}/tsconfig.json`;
try {
// Check if tsconfig.json exists
if (!(0, fs_1.existsSync)(tsconfigPath)) {
console.log("tsconfig.json not found, creating a new one...");
const defaultTsconfig = {
compilerOptions: {},
};
(0, fs_1.writeFileSync)(tsconfigPath, JSON.stringify(defaultTsconfig, null, 2));
console.log("Created tsconfig.json with compilerOptions");
return;
}
// Read existing tsconfig.json
const tsconfigContent = (0, fs_1.readFileSync)(tsconfigPath, "utf8");
let tsconfig;
try {
tsconfig = JSON.parse(tsconfigContent);
}
catch (parseError) {
console.warn("Invalid JSON in tsconfig.json, creating a new one...");
tsconfig = {};
}
// Ensure compilerOptions exists as an object
if (!tsconfig.compilerOptions ||
typeof tsconfig.compilerOptions !== "object") {
tsconfig.compilerOptions = {};
(0, fs_1.writeFileSync)(tsconfigPath, JSON.stringify(tsconfig, null, 2));
console.log("Added compilerOptions to tsconfig.json");
}
else {
console.log("compilerOptions already exists in tsconfig.json");
}
}
catch (error) {
console.error(`Error modifying tsconfig.json: ${error.message}`);
}
}
/**
* Copies project assets from template
* @param tmpDir - Template directory
* @param directoryName - Target directory
*/
static copyProjectAssets(tmpDir, directoryName) {
console.log("Copying project assets...");
try {
// Split directory name for nested projects
const projectDirectories = directoryName.split("/");
const finalProjectName = projectDirectories[projectDirectories.length - 1];
// Copy Android resources
shell
.ls(`${tmpDir}/android/app/src/main/res/drawable/`)
.forEach((file) => {
shell.cp("-rf", `${tmpDir}/android/app/src/main/res/drawable/${file}`, `${directoryName}/android/app/src/main/res/drawable/`);
});
// Copy iOS resources
shell
.ls(`${tmpDir}/ios/boilerPlateTypescript/Images.xcassets/`)
.forEach((file) => {
shell.cp("-rf", `${tmpDir}/ios/boilerPlateTypescript/Images.xcassets/${file}`, `${directoryName}/ios/${finalProjectName}/Images.xcassets/`);
});
// Common files to copy
const filesToCopy = [
"App",
".env",
"fastlane",
"babel.config.js",
"moduleResolver.js",
"modules.json",
"postinstall",
".prettierrc.js",
"env.config",
"react-native-config.d.ts",
];
filesToCopy.forEach((file) => {
if ((0, fs_1.existsSync)(`${tmpDir}/${file}`)) {
shell.mv(`${tmpDir}/${file}`, `${directoryName}`);
}
});
console.log("Project assets copied successfully");
}
catch (error) {
console.error(`Error copying project assets: ${error.message}`);
throw error;
}
}
/**
* Sets up Husky hooks
* @param directoryName - Project directory name
*/
static setupHusky(directoryName) {
console.log("Setting up Husky...");
const shellOptions = { cwd: `${process.cwd()}/${directoryName}` };
try {
console.log("Installing husky hooks");
shell.exec("bun run prepare", shellOptions);
console.log("Setting up pre-commit hook with lint:fix");
const preCommitHookPath = `${directoryName}/.husky/pre-commit`;
const preCommitContent = `#!/bin/sh
bun test
bun lint:fix`;
(0, fs_1.writeFileSync)(preCommitHookPath, preCommitContent);
// Make the hook executable on Unix systems
if (os.platform() !== "win32") {
shell.exec(`chmod +x ${preCommitHookPath}`);
}
console.log("Pre-commit hook configured with lint:fix");
}
catch (error) {
console.error(`Error setting up pre-commit hook: ${error.message}`);
}
}
/**
* Sets up .gitignore file
* @param directoryName - Project directory name
*/
static setupGitignore(directoryName) {
console.log("Setting up .gitignore");
shell.exec(`echo "\n.env\n\!**/fastlane/.env" >> ${directoryName}/.gitignore`);
}
/**
* Creates Windows batch file for postinstall tasks
* @param directoryName - Project directory name
*/
static createPostinstallScripts(directoryName) {
console.log("Creating Windows postinstall batch file...");
try {
// Windows batch file content
const batContent = `@echo off
REM Windows batch file for postinstall tasks
REM Check if bun is available and set the appropriate command
where bun >nul 2>nul
if %errorlevel% == 0 (
echo Using bun as package manager...
set "RUNNER=bun"
) else (
echo Using node as package manager...
set "RUNNER=node"
)
REM Run moduleResolver.js if it exists
if exist "moduleResolver.js" (
echo Running moduleResolver.js...
%RUNNER% ./moduleResolver.js
if %errorlevel% neq 0 (
echo Error: moduleResolver.js failed to execute
exit /b 1
)
) else (
echo Warning: moduleResolver.js not found, skipping...
)
REM Run env.config.js if it exists
if exist "env.config\\env.config.js" (
echo Running env.config/env.config.js...
%RUNNER% ./env.config/env.config.js
if %errorlevel% neq 0 (
echo Error: env.config/env.config.js failed to execute
exit /b 1
)
) else (
echo Warning: env.config/env.config.js not found, skipping...
)
echo Postinstall tasks completed successfully!`;
// Write only the Windows batch file (postinstall.sh is copied from template)
(0, fs_1.writeFileSync)(`${directoryName}/postinstall.bat`, batContent);
console.log("Windows postinstall batch file created successfully");
}
catch (error) {
console.error(`Error creating postinstall batch file: ${error.message}`);
throw error;
}
}
/**
* Runs post-installation scripts
* @param directoryName - Project directory name
*/
static runPostInstallScripts(directoryName) {
console.log("Running post-installation scripts...");
const shellOptions = { cwd: `${process.cwd()}/${directoryName}` };
if (os.platform() === "win32") {
// Windows: Use the batch file
shell.exec("postinstall.bat", shellOptions);
}
else {
// Unix-like systems: Use the shell script
shell.exec("sh postinstall", shellOptions);
}
}
}
exports.default = ProjectService;
//# sourceMappingURL=ProjectService.js.map