rnsup 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -198
- package/dist/commands/generateComponent.js +38 -24
- package/dist/commands/generateFolder.js +103 -0
- package/dist/commands/generateScreen.js +35 -10
- package/dist/commands/setup.js +1 -1
- package/dist/commands/viewStructure.js +91 -0
- package/dist/index.js +17 -0
- package/dist/templates/componentTemplates.js +99 -0
- package/dist/templates/screenTemplates.js +342 -0
- package/dist/utils/selectPrompt.js +13 -24
- package/dist/utils/treeGenerator.js +170 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,300 +1,246 @@
|
|
|
1
|
-
<img width="1536" height="1024" alt="
|
|
2
|
-
|
|
1
|
+
<img width="1536" height="1024" alt="RNSUP React Native Setup" src="https://github.com/user-attachments/assets/3a35bc32-3413-40e5-8355-5db4806923a4" />
|
|
3
2
|
|
|
4
3
|
# RNSUP — React Native Support CLI
|
|
5
4
|
|
|
6
|
-

|
|
7
|
-
|
|
8
|
-
**RNSUP** is a developer productivity CLI that converts a fresh React Native CLI project into a production-ready architecture.
|
|
9
|
-
|
|
10
|
-
Instead of spending 3–6 hours configuring navigation, alias paths, reanimated, gesture handler, axios setup and folder structure, you can do everything with **one command**.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Why RNSUP?
|
|
15
|
-
|
|
16
|
-
Starting a React Native CLI project usually requires:
|
|
17
|
-
|
|
18
|
-
* Installing React Navigation dependencies
|
|
19
|
-
* Configuring Reanimated
|
|
20
|
-
* Adding Gesture Handler import
|
|
21
|
-
* Setting up TypeScript aliases
|
|
22
|
-
* Creating folder structure
|
|
23
|
-
* Writing axios interceptors
|
|
24
|
-
* Adding responsive utilities
|
|
25
|
-
* Supporting image imports in TypeScript
|
|
26
|
-
|
|
27
|
-
Most developers repeat this setup for every project.
|
|
28
|
-
|
|
29
|
-
**RNSUP automates all of it.**
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## What RNSUP Does
|
|
34
|
-
|
|
35
|
-
After running setup, your project automatically gets:
|
|
36
|
-
|
|
37
|
-
### Configuration
|
|
38
|
-
|
|
39
|
-
* React Navigation dependencies installed
|
|
40
|
-
* Reanimated + Worklets configured
|
|
41
|
-
* Gesture Handler patched
|
|
42
|
-
* Babel alias configuration
|
|
43
|
-
* TypeScript path aliases
|
|
44
|
-
* Lockfile conflict handled (npm/yarn)
|
|
45
|
-
|
|
46
|
-
### Architecture
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
src/
|
|
50
|
-
components/
|
|
51
|
-
screens/
|
|
52
|
-
services/
|
|
53
|
-
utils/
|
|
54
|
-
hooks/
|
|
55
|
-
store/
|
|
56
|
-
theme/
|
|
57
|
-
assets/
|
|
58
|
-
types/
|
|
59
|
-
```
|
|
5
|
+
  
|
|
60
6
|
|
|
61
|
-
|
|
7
|
+
**RNSUP** helps you set up a production-ready React Native project in minutes instead of hours.
|
|
62
8
|
|
|
63
|
-
|
|
64
|
-
* Responsive screen helpers
|
|
65
|
-
* Image import TypeScript support
|
|
66
|
-
* Clean folder structure
|
|
9
|
+
What normally takes 3–6 hours of manual configuration — installation, setup, folder structure, aliases, API client setup — gets done automatically with a single command.
|
|
67
10
|
|
|
68
11
|
---
|
|
69
12
|
|
|
70
|
-
##
|
|
71
|
-
|
|
72
|
-
RNSUP installs a curated set of libraries into your project. These are added automatically when you run `npx rnsup setup` (some are optional via prompt):
|
|
73
|
-
|
|
74
|
-
- `@react-navigation/native`
|
|
75
|
-
- `react-native-screens`
|
|
76
|
-
- `react-native-gesture-handler`
|
|
77
|
-
- `react-native-reanimated`
|
|
78
|
-
- `react-native-worklets` (Babel plugin integration)
|
|
79
|
-
- `react-native-vector-icons`
|
|
80
|
-
- `zustand`
|
|
81
|
-
- `axios`
|
|
82
|
-
- `@tanstack/react-query`
|
|
83
|
-
- `react-native-mmkv`
|
|
84
|
-
- navigation extras (conditional): `@react-navigation/native-stack`, `@react-navigation/bottom-tabs`, `@react-navigation/drawer`
|
|
85
|
-
- optional (prompted): `react-native-svg`, `lucide-react-native`
|
|
86
|
-
|
|
87
|
-
<div style="background:#fff3cd;border-left:6px solid #ffeeba;padding:12px;border-radius:6px">
|
|
88
|
-
<strong>⚠️ Warning</strong>
|
|
89
|
-
<p style="margin:6px 0 0">Many of the packages above include native code. After installation you <strong>must</strong> verify and complete any required native configuration (for iOS and Android). Common steps include:</p>
|
|
90
|
-
<ul style="margin:6px 0 0;padding-left:20px">
|
|
91
|
-
<li>Run <code>cd ios && pod install</code> on macOS</li>
|
|
92
|
-
<li>Follow the official docs for Reanimated, MMKV, react-native-svg and React Navigation</li>
|
|
93
|
-
<li>Check Android Gradle / manifest changes for native modules</li>
|
|
94
|
-
</ul>
|
|
95
|
-
<p style="margin:6px 0 0">If something looks off (build errors, missing icons, or runtime crashes), consult the package docs first — RNSUP does not (and cannot) run platform-specific installs for you.</p>
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
### Developer Experience
|
|
13
|
+
## Features at a Glance
|
|
100
14
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
15
|
+
| Feature | What You Get |
|
|
16
|
+
|---------|-------------|
|
|
17
|
+
| **Navigation** | React Navigation with preset stacks configured |
|
|
18
|
+
| **Performance** | Reanimated + Worklets for smooth animations |
|
|
19
|
+
| **Gestures** | Gesture Handler pre-integrated |
|
|
20
|
+
| **Routing** | TypeScript paths and Babel aliases |
|
|
21
|
+
| **APIs** | Axios with interceptors ready to use |
|
|
22
|
+
| **Utilities** | Responsive helpers, image imports, TypeScript support |
|
|
23
|
+
| **State** | Zustand store setup with TypeScript |
|
|
24
|
+
| **Generators** | CLI commands for screens, components, and folders |
|
|
25
|
+
| **Structure** | Pre-built folder organization |
|
|
104
26
|
|
|
105
27
|
---
|
|
106
28
|
|
|
107
|
-
##
|
|
29
|
+
## Install & Setup
|
|
108
30
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
Use directly via npx:
|
|
31
|
+
No global installation needed. Just run:
|
|
112
32
|
|
|
113
33
|
```bash
|
|
34
|
+
npx create-rn MyApp
|
|
35
|
+
cd MyApp
|
|
114
36
|
npx rnsup setup
|
|
115
37
|
```
|
|
116
38
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
## Quick Start
|
|
120
|
-
|
|
121
|
-
### 1) Create React Native Project
|
|
122
|
-
for creating latest cli project !
|
|
39
|
+
Follow the prompts to select your package manager. That's it—your project is ready.
|
|
123
40
|
|
|
124
41
|
```bash
|
|
125
|
-
npx
|
|
126
|
-
|
|
42
|
+
npx react-native start --reset-cache
|
|
43
|
+
npx react-native run-android
|
|
127
44
|
```
|
|
128
45
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
npx rnsup setup
|
|
133
|
-
```
|
|
46
|
+
---
|
|
134
47
|
|
|
135
|
-
|
|
48
|
+
## What Gets Installed
|
|
136
49
|
|
|
137
|
-
|
|
50
|
+
RNSUP automatically installs and configures these packages:
|
|
138
51
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
52
|
+
| Package | Purpose | Type |
|
|
53
|
+
|---------|---------|------|
|
|
54
|
+
| `@react-navigation/native` | Screen navigation | Required |
|
|
55
|
+
| `react-native-gesture-handler` | Touch gesture support | Required |
|
|
56
|
+
| `react-native-reanimated` | Smooth animations | Required |
|
|
57
|
+
| `react-native-screens` | Performance optimization | Required |
|
|
58
|
+
| `axios` | HTTP client | Required |
|
|
59
|
+
| `zustand` | State management | Required |
|
|
60
|
+
| `@tanstack/react-query` | Data fetching | Required |
|
|
61
|
+
| `react-native-mmkv` | Fast storage | Required |
|
|
62
|
+
| `react-native-vector-icons` | Icon library | Required |
|
|
63
|
+
| `@react-navigation/native-stack` | Stack navigation | Optional |
|
|
64
|
+
| `@react-navigation/bottom-tabs` | Tab navigation | Optional |
|
|
65
|
+
| `react-native-svg` | SVG support | Optional |
|
|
66
|
+
| `lucide-react-native` | Icon set | Optional |
|
|
143
67
|
|
|
144
|
-
|
|
68
|
+
⚠️ **Note:** Many packages include native code. After setup, you'll need to complete native configuration for iOS and Android (pod install, gradle sync, manifest updates). Check the official docs for each package.
|
|
145
69
|
|
|
146
70
|
---
|
|
147
71
|
|
|
148
|
-
##
|
|
72
|
+
## Project Structure
|
|
149
73
|
|
|
150
|
-
|
|
74
|
+
After setup, your project will have:
|
|
151
75
|
|
|
152
76
|
```
|
|
153
|
-
|
|
77
|
+
src/
|
|
78
|
+
├── components/ # Reusable UI components
|
|
79
|
+
├── screens/ # App screens/pages
|
|
80
|
+
├── services/ # API calls & external services
|
|
81
|
+
├── utils/ # Helper functions
|
|
82
|
+
├── hooks/ # Custom React hooks
|
|
83
|
+
├── store/ # State management
|
|
84
|
+
├── theme/ # Colors, typography, styling
|
|
85
|
+
├── assets/ # Images, fonts, static files
|
|
86
|
+
└── types/ # TypeScript types & interfaces
|
|
154
87
|
```
|
|
155
88
|
|
|
156
89
|
---
|
|
157
90
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
> Here `s` mean `screen`, and `g` mean `generate`
|
|
91
|
+
## Commands
|
|
161
92
|
|
|
93
|
+
### Generate a Screen
|
|
162
94
|
|
|
163
|
-
```
|
|
164
|
-
rnsup g s
|
|
165
|
-
rnsup g s auth/
|
|
166
|
-
rnsup g s features/auth/
|
|
95
|
+
```bash
|
|
96
|
+
rnsup g s LoginScreen
|
|
97
|
+
rnsup g s auth/LoginScreen
|
|
98
|
+
rnsup g s features/auth/LoginScreen
|
|
167
99
|
```
|
|
168
100
|
|
|
169
|
-
|
|
101
|
+
Choose from: **Basic**, **List**, **Form**, or **Detail** templates.
|
|
170
102
|
|
|
171
|
-
|
|
172
|
-
src/screens/LoginScreen.tsx
|
|
173
|
-
src/auth/LoginScreen.tsx
|
|
174
|
-
src/features/auth/LoginScreen.tsx
|
|
175
|
-
```
|
|
103
|
+
### Generate a Component
|
|
176
104
|
|
|
177
|
-
|
|
105
|
+
```bash
|
|
106
|
+
rnsup g c Button
|
|
107
|
+
rnsup g c ui/Card
|
|
108
|
+
rnsup g c forms/TextInput
|
|
109
|
+
```
|
|
178
110
|
|
|
179
|
-
|
|
111
|
+
Creates `.tsx` by default (press Enter) or choose `.jsx`.
|
|
180
112
|
|
|
181
|
-
|
|
113
|
+
### Generate a Folder
|
|
182
114
|
|
|
183
|
-
```
|
|
184
|
-
rnsup g
|
|
185
|
-
rnsup g
|
|
115
|
+
```bash
|
|
116
|
+
rnsup g d themes
|
|
117
|
+
rnsup g d src/api
|
|
118
|
+
rnsup g d src/utils/helpers
|
|
186
119
|
```
|
|
187
120
|
|
|
188
|
-
|
|
121
|
+
Auto-registers TypeScript aliases for `src/` folders.
|
|
189
122
|
|
|
123
|
+
### View Project Structure
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
rnsup view # Show raw structure
|
|
127
|
+
rnsup view -p # Show with icons and colors
|
|
128
|
+
rnsup view --time # Show with timestamps
|
|
129
|
+
rnsup view -p --time # Pretty + timestamps
|
|
190
130
|
```
|
|
191
|
-
|
|
192
|
-
src/
|
|
193
|
-
```
|
|
131
|
+
|
|
132
|
+
Choose between Root level or src/ folder when prompted.
|
|
194
133
|
|
|
195
134
|
---
|
|
196
135
|
|
|
197
|
-
##
|
|
136
|
+
## Usage Examples
|
|
198
137
|
|
|
199
|
-
|
|
138
|
+
### Import Components (No Relative Paths)
|
|
200
139
|
|
|
201
140
|
Instead of:
|
|
202
|
-
|
|
203
|
-
```ts
|
|
141
|
+
```typescript
|
|
204
142
|
import Button from '../../../components/Button';
|
|
205
143
|
```
|
|
206
144
|
|
|
207
145
|
Use:
|
|
208
|
-
|
|
209
|
-
```ts
|
|
146
|
+
```typescript
|
|
210
147
|
import Button from '@components/Button';
|
|
211
148
|
```
|
|
212
149
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
@assets
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
New folders inside `src` automatically get alias support.
|
|
226
|
-
|
|
227
|
-
---
|
|
150
|
+
Automatically configured aliases:
|
|
151
|
+
- `@components` → `src/components/`
|
|
152
|
+
- `@screens` → `src/screens/`
|
|
153
|
+
- `@services` → `src/services/`
|
|
154
|
+
- `@utils` → `src/utils/`
|
|
155
|
+
- `@hooks` → `src/hooks/`
|
|
156
|
+
- `@store` → `src/store/`
|
|
157
|
+
- `@theme` → `src/theme/`
|
|
158
|
+
- `@assets` → `src/assets/`
|
|
228
159
|
|
|
229
|
-
|
|
160
|
+
### Use the API Client
|
|
230
161
|
|
|
231
|
-
```
|
|
162
|
+
```typescript
|
|
232
163
|
import api from '@services/api/client';
|
|
233
164
|
|
|
165
|
+
// GET request
|
|
234
166
|
const users = await api.get('/users');
|
|
167
|
+
|
|
168
|
+
// POST request
|
|
169
|
+
const response = await api.post('/login', { email, password });
|
|
235
170
|
```
|
|
236
171
|
|
|
237
|
-
Interceptors
|
|
172
|
+
Interceptors are pre-configured for error handling and auth tokens.
|
|
238
173
|
|
|
239
|
-
|
|
174
|
+
### Responsive Layouts
|
|
240
175
|
|
|
241
|
-
|
|
176
|
+
```typescript
|
|
177
|
+
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from '@utils/responsive-screen';
|
|
242
178
|
|
|
243
|
-
|
|
244
|
-
import { widthPercentageToDP as wp } from '@utils/responsive-screen';
|
|
245
|
-
|
|
246
|
-
<View style={{ width: wp(80) }} />
|
|
179
|
+
<View style={{ width: wp(80), height: hp(50) }} />
|
|
247
180
|
```
|
|
248
181
|
|
|
249
|
-
|
|
182
|
+
Works on all device sizes without manual breakpoints.
|
|
250
183
|
|
|
251
|
-
|
|
184
|
+
### Import Images in TypeScript
|
|
252
185
|
|
|
253
|
-
```
|
|
186
|
+
```typescript
|
|
254
187
|
import logo from '@assets/logo.png';
|
|
255
188
|
|
|
256
|
-
<Image source={logo} />
|
|
189
|
+
<Image source={logo} style={{ width: 100, height: 100 }} />
|
|
257
190
|
```
|
|
258
191
|
|
|
259
|
-
No TypeScript
|
|
192
|
+
No TypeScript errors—types are automatically set up.
|
|
260
193
|
|
|
261
194
|
---
|
|
262
195
|
|
|
263
|
-
##
|
|
196
|
+
## Auto Aliases
|
|
264
197
|
|
|
265
|
-
|
|
198
|
+
New folders inside `src/` automatically get alias support:
|
|
266
199
|
|
|
267
|
-
|
|
200
|
+
```bash
|
|
201
|
+
rnsup g d src/modals
|
|
202
|
+
# Now use: import Modal from '@modals/MyModal';
|
|
203
|
+
```
|
|
268
204
|
|
|
269
|
-
|
|
270
|
-
* Prevents configuration mistakes
|
|
271
|
-
* Standardizes project structure
|
|
272
|
-
* Faster onboarding for new developers
|
|
273
|
-
* Clean import paths
|
|
274
|
-
* Production-ready base
|
|
205
|
+
Aliases update in both TypeScript `tsconfig.json` and Babel `.babelrc`.
|
|
275
206
|
|
|
276
207
|
---
|
|
277
208
|
|
|
278
209
|
## Best Practices
|
|
279
210
|
|
|
280
|
-
|
|
211
|
+
1. **Always use generators** — Keeps aliases and structure consistent
|
|
212
|
+
2. **Avoid manual folders** — Use `rnsup g d` instead
|
|
213
|
+
3. **Keep folder names consistent** — Use kebab-case or camelCase, not spaces
|
|
214
|
+
4. **Update native config** — Don't skip iOS/Android setup
|
|
215
|
+
5. **Commit early** — Make a git commit right after `rnsup setup`
|
|
281
216
|
|
|
282
|
-
|
|
283
|
-
2. Run `rnsup setup`
|
|
284
|
-
3. Only create screens/components using `rnsup g`
|
|
285
|
-
4. Avoid manual folder creation inside `src`
|
|
217
|
+
---
|
|
286
218
|
|
|
287
|
-
|
|
219
|
+
## Troubleshooting
|
|
288
220
|
|
|
221
|
+
**Error: "Not a React Native CLI project"**
|
|
222
|
+
- Run `rnsup setup` from your React Native project root (where `package.json` exists)
|
|
289
223
|
|
|
290
|
-
|
|
224
|
+
**Error: "Selected package manager is not installed"**
|
|
225
|
+
- Install npm, yarn, or pnpm first
|
|
226
|
+
|
|
227
|
+
**Native build fails after setup**
|
|
228
|
+
- Run `cd ios && pod install` (macOS only)
|
|
229
|
+
- Check your Android SDK and NDK are up to date
|
|
230
|
+
- Read the official docs for each native package
|
|
231
|
+
|
|
232
|
+
**Aliases not working**
|
|
233
|
+
- Run `npx react-native start --reset-cache`
|
|
234
|
+
- If still broken, check `tsconfig.json` has correct paths
|
|
235
|
+
|
|
236
|
+
---
|
|
291
237
|
|
|
292
|
-
|
|
238
|
+
## Contributing
|
|
293
239
|
|
|
294
|
-
|
|
240
|
+
Found a bug or want a feature? Open an issue or submit a PR at dev branch.
|
|
295
241
|
|
|
296
242
|
---
|
|
297
243
|
|
|
298
244
|
## License
|
|
299
245
|
|
|
300
|
-
MIT
|
|
246
|
+
MIT © 2026
|
|
@@ -8,17 +8,36 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
10
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
-
const
|
|
11
|
+
const componentTemplates_1 = require("../templates/componentTemplates");
|
|
12
12
|
const parseComponentName_1 = require("../utils/parseComponentName");
|
|
13
13
|
const aliasManager_1 = require("../utils/aliasManager");
|
|
14
14
|
const history_1 = require("../utils/history");
|
|
15
|
+
const handleCancel_1 = require("../utils/handleCancel");
|
|
15
16
|
async function generateComponent(input) {
|
|
16
17
|
try {
|
|
17
18
|
const { componentName, fullDir, relativeDir } = (0, parseComponentName_1.parseComponentName)(input);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
// Ask for file extension
|
|
20
|
+
const { fileExtension } = await inquirer_1.default.prompt([
|
|
21
|
+
{
|
|
22
|
+
type: 'list',
|
|
23
|
+
name: 'fileExtension',
|
|
24
|
+
message: 'Enter file extension:',
|
|
25
|
+
choices: [
|
|
26
|
+
{ name: 'TypeScript (tsx) - Default, Recommended', value: 'tsx' },
|
|
27
|
+
{ name: 'JavaScript (jsx)', value: 'jsx' }
|
|
28
|
+
],
|
|
29
|
+
default: 'tsx'
|
|
30
|
+
}
|
|
31
|
+
]);
|
|
32
|
+
const filePath = path_1.default.join(fullDir, `${componentName}.${fileExtension}`);
|
|
33
|
+
// Show colored details
|
|
34
|
+
console.log('\n' + chalk_1.default.cyan.bold('🏗️ Component Creation Details'));
|
|
35
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
36
|
+
console.log(chalk_1.default.yellow('Name: '), chalk_1.default.cyan(componentName));
|
|
37
|
+
console.log(chalk_1.default.yellow('Extension: '), chalk_1.default.magenta(fileExtension.toUpperCase()));
|
|
38
|
+
console.log(chalk_1.default.yellow('Location: '), chalk_1.default.white(relativeDir));
|
|
39
|
+
console.log(chalk_1.default.yellow('File: '), chalk_1.default.dim(`${componentName}.${fileExtension}`));
|
|
40
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
22
41
|
// overwrite check
|
|
23
42
|
if (await fs_extra_1.default.pathExists(filePath)) {
|
|
24
43
|
const { overwrite } = await inquirer_1.default.prompt([
|
|
@@ -30,7 +49,7 @@ async function generateComponent(input) {
|
|
|
30
49
|
}
|
|
31
50
|
]);
|
|
32
51
|
if (!overwrite) {
|
|
33
|
-
console.log(chalk_1.default.yellow('
|
|
52
|
+
console.log(chalk_1.default.yellow('Operation cancelled.'));
|
|
34
53
|
return;
|
|
35
54
|
}
|
|
36
55
|
}
|
|
@@ -38,33 +57,28 @@ async function generateComponent(input) {
|
|
|
38
57
|
{
|
|
39
58
|
type: 'confirm',
|
|
40
59
|
name: 'confirm',
|
|
41
|
-
message: `Create ${componentName}
|
|
60
|
+
message: chalk_1.default.green(`Create ${componentName} (${fileExtension.toUpperCase()})?`),
|
|
42
61
|
default: true
|
|
43
62
|
}
|
|
44
63
|
]);
|
|
45
|
-
if (!confirm)
|
|
64
|
+
if (!confirm) {
|
|
65
|
+
console.log(chalk_1.default.yellow('Cancelled.'));
|
|
46
66
|
return;
|
|
67
|
+
}
|
|
47
68
|
// create directory
|
|
48
69
|
await fs_extra_1.default.ensureDir(fullDir);
|
|
49
70
|
// ensure alias (for nested components like ui/forms)
|
|
50
71
|
await (0, aliasManager_1.registerAlias)(relativeDir);
|
|
51
|
-
// write component
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
await fs_extra_1.default.appendFile(indexFile, exportLine);
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
await fs_extra_1.default.writeFile(indexFile, exportLine);
|
|
63
|
-
}
|
|
64
|
-
await (0, history_1.addHistory)(`Generated component ${componentName}`);
|
|
65
|
-
console.log(chalk_1.default.green(`\n${componentName} created successfully.`));
|
|
72
|
+
// write component with simple template
|
|
73
|
+
const template = (0, componentTemplates_1.getComponentTemplate)(componentName, 'presentational');
|
|
74
|
+
await fs_extra_1.default.writeFile(filePath, template);
|
|
75
|
+
await (0, history_1.addHistory)(`Generated component ${componentName} (${fileExtension})`);
|
|
76
|
+
console.log(chalk_1.default.green(`\n✨ Component ${chalk_1.default.bold(componentName)} created successfully!`));
|
|
77
|
+
console.log(chalk_1.default.gray(`Location: ${relativeDir}`));
|
|
78
|
+
console.log(chalk_1.default.gray(`Extension: ${fileExtension}`));
|
|
79
|
+
console.log();
|
|
66
80
|
}
|
|
67
81
|
catch (err) {
|
|
68
|
-
|
|
82
|
+
(0, handleCancel_1.handleCancel)(err);
|
|
69
83
|
}
|
|
70
84
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateFolder = generateFolder;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const history_1 = require("../utils/history");
|
|
12
|
+
const aliasManager_1 = require("../utils/aliasManager");
|
|
13
|
+
const handleCancel_1 = require("../utils/handleCancel");
|
|
14
|
+
async function generateFolder(input) {
|
|
15
|
+
try {
|
|
16
|
+
// normalize slashes and clean input
|
|
17
|
+
let cleaned = input.replace(/\\/g, '/').trim();
|
|
18
|
+
// resolve folder path
|
|
19
|
+
let fullDir;
|
|
20
|
+
let relativeDir;
|
|
21
|
+
// if path starts with src/, use as-is
|
|
22
|
+
if (cleaned.startsWith('src/')) {
|
|
23
|
+
relativeDir = cleaned;
|
|
24
|
+
fullDir = path_1.default.join(process.cwd(), cleaned);
|
|
25
|
+
}
|
|
26
|
+
// if path contains /, but doesn't start with src/
|
|
27
|
+
else if (cleaned.includes('/')) {
|
|
28
|
+
fullDir = path_1.default.join(process.cwd(), cleaned);
|
|
29
|
+
relativeDir = cleaned;
|
|
30
|
+
}
|
|
31
|
+
// just a folder name, create at root
|
|
32
|
+
else {
|
|
33
|
+
fullDir = path_1.default.join(process.cwd(), cleaned);
|
|
34
|
+
relativeDir = cleaned;
|
|
35
|
+
}
|
|
36
|
+
const folderName = path_1.default.basename(fullDir);
|
|
37
|
+
// show colored info
|
|
38
|
+
console.log('\n' + chalk_1.default.cyan.bold('📁 Folder Creation Details'));
|
|
39
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
40
|
+
console.log(chalk_1.default.yellow('Folder Name:'), chalk_1.default.white(folderName));
|
|
41
|
+
console.log(chalk_1.default.yellow('Location: '), chalk_1.default.white(relativeDir));
|
|
42
|
+
console.log(chalk_1.default.yellow('Full Path: '), chalk_1.default.dim(fullDir));
|
|
43
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
44
|
+
// check if folder already exists
|
|
45
|
+
if (await fs_extra_1.default.pathExists(fullDir)) {
|
|
46
|
+
console.log(chalk_1.default.yellow(`\n⚠️ Folder ${relativeDir} already exists.`));
|
|
47
|
+
const { proceed } = await inquirer_1.default.prompt([
|
|
48
|
+
{
|
|
49
|
+
type: 'confirm',
|
|
50
|
+
name: 'proceed',
|
|
51
|
+
message: 'Do you want to continue anyway?',
|
|
52
|
+
default: false
|
|
53
|
+
}
|
|
54
|
+
]);
|
|
55
|
+
if (!proceed) {
|
|
56
|
+
console.log(chalk_1.default.yellow('Cancelled.'));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ask to create index.ts
|
|
61
|
+
const { createIndex } = await inquirer_1.default.prompt([
|
|
62
|
+
{
|
|
63
|
+
type: 'confirm',
|
|
64
|
+
name: 'createIndex',
|
|
65
|
+
message: 'Create index.ts file?',
|
|
66
|
+
default: true
|
|
67
|
+
}
|
|
68
|
+
]);
|
|
69
|
+
// final confirmation
|
|
70
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
71
|
+
{
|
|
72
|
+
type: 'confirm',
|
|
73
|
+
name: 'confirm',
|
|
74
|
+
message: chalk_1.default.green(`Create folder ${chalk_1.default.bold(folderName)}?`),
|
|
75
|
+
default: true
|
|
76
|
+
}
|
|
77
|
+
]);
|
|
78
|
+
if (!confirm) {
|
|
79
|
+
console.log(chalk_1.default.yellow('Cancelled.'));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// create folder
|
|
83
|
+
await fs_extra_1.default.ensureDir(fullDir);
|
|
84
|
+
// register alias if it's under src/
|
|
85
|
+
if (relativeDir.startsWith('src/')) {
|
|
86
|
+
await (0, aliasManager_1.registerAlias)(relativeDir);
|
|
87
|
+
}
|
|
88
|
+
// create index.ts if requested
|
|
89
|
+
if (createIndex) {
|
|
90
|
+
const indexFile = path_1.default.join(fullDir, 'index.ts');
|
|
91
|
+
if (!(await fs_extra_1.default.pathExists(indexFile))) {
|
|
92
|
+
await fs_extra_1.default.writeFile(indexFile, '// Add your exports here\n');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
await (0, history_1.addHistory)(`Created folder ${relativeDir}`);
|
|
96
|
+
console.log(chalk_1.default.green(`\n✨ Folder ${chalk_1.default.bold(folderName)} created successfully!`));
|
|
97
|
+
console.log(chalk_1.default.gray(`Location: ${relativeDir}`));
|
|
98
|
+
console.log();
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
(0, handleCancel_1.handleCancel)(err);
|
|
102
|
+
}
|
|
103
|
+
}
|