Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions commands/initReactNative.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import path from 'path';
import fs from 'fs';
import { execSync } from 'child_process';
import chalk from 'chalk';
import { checkNodeVersion } from '../utils/checkNodeVersion.js';
import { taskHandler } from '../utils/taskHandler.js';
import {
tailwindConfig,
globalCss,
babelConfig,
metroConfig,
layoutFile,
indexFile,
appJson,
} from '../utils/config.js';

function createExpoReactNative(projectName) {
checkNodeVersion();

let rootDir = '';
if (projectName === '.') rootDir = process.cwd();
else rootDir = path.join(process.cwd(), projectName);

// Initializing Expo Project
taskHandler(
() => {
execSync(`npx create-expo-app@latest ${projectName}`, {
stdio: 'inherit',
});
},
'🔧 Initiating Expo project...',
'✅ Initialized Expo project successfully!',
'❌ Error while initializing an Expo project'
);

// Run Expo Reset Script
taskHandler(
() => {
execSync(`npm run reset-project`, {
stdio: ['pipe', 'inherit', 'inherit'],
input: 'Y\n',
cwd: rootDir,
});
},
'🔧 Resetting Expo project...',
'✅ Reset Expo project successfully!',
'❌ Error while resetting an Expo project'
);

// Installing NativeWind dependencies
taskHandler(
() =>
execSync(
'npm install nativewind react-native-reanimated@~3.17.4 [email protected]',
{ stdio: 'inherit', cwd: rootDir }
),
'🔧 Installing NativeWind dependencies...',
'✅ NativeWind dependencies installed successfully!',
'❌ Error while installing NativeWind dependencies'
);

// Installing dev dependencies
taskHandler(
() =>
execSync(
'npm install --dev tailwindcss@^3.4.17 prettier-plugin-tailwindcss@^0.5.11',
{ stdio: 'inherit', cwd: rootDir }
),
'🔧 Installing dev dependencies...',
'✅ dev dependencies installed successfully!',
'❌ Error while installing dev dependencies'
);

// Initializing tailwind config file
taskHandler(
() => execSync('npx tailwindcss init', { stdio: 'inherit', cwd: rootDir }),
'🔧 Installing dev dependencies...',
'✅ dev dependencies installed successfully!',
'❌ Error while installing dev dependencies'
);

taskHandler(() => {
fs.writeFileSync(path.join(rootDir, 'tailwind.config.js'), tailwindConfig),
fs.writeFileSync(path.join(rootDir, './app/global.css'), globalCss),
fs.writeFileSync(path.join(rootDir, 'babel.config.js'), babelConfig),
fs.writeFileSync(path.join(rootDir, 'metro.config.js'), metroConfig),
fs.writeFileSync(path.join(rootDir, './app/_layout.tsx'), layoutFile),
fs.writeFileSync(path.join(rootDir, './app/index.tsx'), indexFile),
fs.writeFileSync(path.join(rootDir, 'app.json'), appJson),
'✍️ Adding files to setup NativeWind...',
'✅ All files written successfully!',
'❌ Failed to write some or all files';
});

taskHandler(
() => execSync('git init', { cwd: rootDir }),
'🔧 Initiating Git repo...',
'✅ Initialized Git repo successfully!',
'❌ Error while initializing a Git repo'
);

console.log(
'-------------------------------------------------------------------------'
);
console.log(
chalk.blue(
'🚀React Native + NativeWind project initialized with all basic configurations successfully!'
)
);
console.log(
'-------------------------------------------------------------------------'
);
}

export default function initReactNative(program) {
program
.command('create-react-native <projectName>')
.description('Create a new Expo React Native project')
.action((projectName) => {
createExpoReactNative(projectName);
});
}
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import initializeDockerCommand from './commands/initializeDocker.js';
import addESLintCommand from './commands/addESLint.js';
import addJWTAuthCommand from './commands/addJWTAuth.js';
import addDeployCommand from './commands/deployCommand.js';
import initReactNative from './commands/initReactNative.js';

// Step 1: Get the directory of the current file
const __filename = fileURLToPath(import.meta.url);
Expand Down Expand Up @@ -45,6 +46,7 @@ initializeDockerCommand(program);
addESLintCommand(program);
addJWTAuthCommand(program);
addDeployCommand(program);
initReactNative(program);

// Step 5: Parse the provided arguments and start the CLI
program.parse(process.argv);
104 changes: 104 additions & 0 deletions utils/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
export const tailwindConfig = `/** @type {import('tailwindcss').Config} */
module.exports = {
// NOTE: Update this to include the paths to all files that contain Nativewind classes.
content: ["./App.tsx", "./components/**/*.{js,jsx,ts,tsx}", "./app/**/*.{js,jsx,ts,tsx}"],
presets: [require("nativewind/preset")],
theme: {
extend: {},
},
plugins: [],
}`;

export const globalCss = `@tailwind base;
@tailwind components;
@tailwind utilities;`;

export const babelConfig = `module.exports = function (api) {
api.cache(true);
return {
presets: [
["babel-preset-expo", { jsxImportSource: "nativewind" }],
"nativewind/babel",
],
};
};`;

export const metroConfig = `const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require('nativewind/metro');

const config = getDefaultConfig(__dirname)

module.exports = withNativeWind(config, { input: './app/global.css' })`;

export const layoutFile = `import { Stack } from "expo-router";
import "./global.css"

export default function RootLayout() {
return <Stack />;
}`;

export const indexFile = `import { Text, View } from "react-native";

export default function Index() {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<Text>Decli successfully initialized your app!.</Text>
</View>
);
}`;

export const appJson = `{
"expo": {
"name": "TESTING",
"slug": "TESTING",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "testing",
"userInterfaceStyle": "automatic",
"newArchEnabled": true,
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"backgroundColor": "#E6F4FE",
"foregroundImage": "./assets/images/android-icon-foreground.png",
"backgroundImage": "./assets/images/android-icon-background.png",
"monochromeImage": "./assets/images/android-icon-monochrome.png"
},
"edgeToEdgeEnabled": true,
"predictiveBackGestureEnabled": false
},
"web": {
"bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
"image": "./assets/images/splash-icon.png",
"imageWidth": 200,
"resizeMode": "contain",
"backgroundColor": "#ffffff",
"dark": {
"backgroundColor": "#000000"
}
}
]
],
"experiments": {
"typedRoutes": true,
"reactCompiler": true
}
}
}`;