create-mobile-arch 1.0.0
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 +180 -0
- package/bin/index.js +144 -0
- package/package.json +43 -0
- package/src/generator.js +229 -0
- package/src/prompts.js +140 -0
- package/src/utils.js +185 -0
- package/templates/flutter-clean/analysis_options.yaml +46 -0
- package/templates/flutter-clean/lib/core/constants/app_constants.dart +26 -0
- package/templates/flutter-clean/lib/core/theme/app_theme.dart +90 -0
- package/templates/flutter-clean/lib/core/utils/app_utils.dart +29 -0
- package/templates/flutter-clean/lib/data/datasources/.gitkeep +0 -0
- package/templates/flutter-clean/lib/data/models/user_model.dart +57 -0
- package/templates/flutter-clean/lib/data/repositories/.gitkeep +0 -0
- package/templates/flutter-clean/lib/domain/entities/user.dart +23 -0
- package/templates/flutter-clean/lib/domain/repositories/.gitkeep +0 -0
- package/templates/flutter-clean/lib/domain/usecases/.gitkeep +0 -0
- package/templates/flutter-clean/lib/main.dart +33 -0
- package/templates/flutter-clean/lib/presentation/providers/.gitkeep +0 -0
- package/templates/flutter-clean/lib/presentation/screens/home_screen.dart +106 -0
- package/templates/flutter-clean/lib/presentation/widgets/.gitkeep +0 -0
- package/templates/flutter-clean/pubspec.yaml +69 -0
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# create-mobile-arch
|
|
2
|
+
|
|
3
|
+
A production-ready CLI tool to generate Flutter project architectures with best practices baked in.
|
|
4
|
+
|
|
5
|
+
## ๐ Quick Start
|
|
6
|
+
|
|
7
|
+
Create a new Flutter project with a single command:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx create-mobile-arch my_app
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## โจ Features
|
|
14
|
+
|
|
15
|
+
- ๐๏ธ **Multiple Architecture Patterns**: Clean Architecture & Feature-First
|
|
16
|
+
- ๐ฆ **State Management**: Riverpod or Bloc
|
|
17
|
+
- ๐ **Backend Integration**: Firebase or REST API
|
|
18
|
+
- ๐ **Well-Structured**: Production-ready folder organization
|
|
19
|
+
- ๐จ **Theme Support**: Light & dark mode out of the box
|
|
20
|
+
- ๐งช **Testing Ready**: Example tests included
|
|
21
|
+
- ๐ **Documentation**: README with architecture details
|
|
22
|
+
|
|
23
|
+
## ๐ Usage
|
|
24
|
+
|
|
25
|
+
### Basic Usage
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx create-mobile-arch <project-name>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### With Default Configuration
|
|
32
|
+
|
|
33
|
+
Skip prompts and use default settings:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx create-mobile-arch my_app -y
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## ๐ฏ Interactive Configuration
|
|
40
|
+
|
|
41
|
+
When you run the CLI, you'll be asked to choose:
|
|
42
|
+
|
|
43
|
+
1. **Architecture Pattern**
|
|
44
|
+
- Clean Architecture (Domain-driven with layers)
|
|
45
|
+
- Feature First (Organized by features)
|
|
46
|
+
|
|
47
|
+
2. **State Management**
|
|
48
|
+
- Riverpod (Recommended - compile-safe, testable)
|
|
49
|
+
- Bloc (Event-driven state management)
|
|
50
|
+
|
|
51
|
+
3. **Backend Integration**
|
|
52
|
+
- Firebase (Auth, Firestore, Storage)
|
|
53
|
+
- REST API (Custom backend with HTTP)
|
|
54
|
+
|
|
55
|
+
4. **Include Examples**
|
|
56
|
+
- Sample code and features
|
|
57
|
+
|
|
58
|
+
## ๐ Generated Project Structure
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
your_app/
|
|
62
|
+
โโโ lib/
|
|
63
|
+
โ โโโ core/ # Core functionality
|
|
64
|
+
โ โ โโโ constants/ # App constants
|
|
65
|
+
โ โ โโโ theme/ # Theme configuration
|
|
66
|
+
โ โ โโโ utils/ # Utility functions
|
|
67
|
+
โ โโโ data/ # Data layer
|
|
68
|
+
โ โ โโโ datasources/ # API, local storage
|
|
69
|
+
โ โ โโโ models/ # Data models
|
|
70
|
+
โ โ โโโ repositories/ # Repository implementations
|
|
71
|
+
โ โโโ domain/ # Business logic
|
|
72
|
+
โ โ โโโ entities/ # Business entities
|
|
73
|
+
โ โ โโโ repositories/ # Repository interfaces
|
|
74
|
+
โ โ โโโ usecases/ # Business use cases
|
|
75
|
+
โ โโโ presentation/ # UI layer
|
|
76
|
+
โ โ โโโ screens/ # App screens
|
|
77
|
+
โ โ โโโ widgets/ # Reusable widgets
|
|
78
|
+
โ โ โโโ providers/ # State management
|
|
79
|
+
โ โโโ main.dart # App entry point
|
|
80
|
+
โโโ test/ # Unit & widget tests
|
|
81
|
+
โโโ pubspec.yaml # Dependencies
|
|
82
|
+
โโโ README.md # Project documentation
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## ๐ ๏ธ Requirements
|
|
86
|
+
|
|
87
|
+
- **Node.js**: >= 14.0.0
|
|
88
|
+
- **Flutter**: >= 3.0.0 (for running the generated project)
|
|
89
|
+
|
|
90
|
+
## ๐ฆ What's Included
|
|
91
|
+
|
|
92
|
+
The generated Flutter project includes:
|
|
93
|
+
|
|
94
|
+
### Dependencies
|
|
95
|
+
- **flutter_riverpod**: State management
|
|
96
|
+
- **get_it**: Dependency injection
|
|
97
|
+
- **dio**: HTTP client
|
|
98
|
+
- **go_router**: Navigation
|
|
99
|
+
- **hive**: Local storage
|
|
100
|
+
- **equatable**: Value equality
|
|
101
|
+
- **freezed**: Code generation
|
|
102
|
+
|
|
103
|
+
### Dev Dependencies
|
|
104
|
+
- **build_runner**: Code generation
|
|
105
|
+
- **flutter_lints**: Linting rules
|
|
106
|
+
- **flutter_test**: Testing framework
|
|
107
|
+
|
|
108
|
+
## ๐ After Project Generation
|
|
109
|
+
|
|
110
|
+
Once your project is created:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
cd my_app
|
|
114
|
+
flutter run
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## ๐ Examples
|
|
118
|
+
|
|
119
|
+
### Create a clean architecture project
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npx create-mobile-arch awesome_app
|
|
123
|
+
# Then select: Clean Architecture, Riverpod, REST API
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Quick start with defaults
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npx create-mobile-arch quick_app -y
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## ๐ง Development
|
|
133
|
+
|
|
134
|
+
### Clone & Setup
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
git clone <repository-url>
|
|
138
|
+
cd create-mobile-arch
|
|
139
|
+
npm install
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Test Locally
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npm test
|
|
146
|
+
# or
|
|
147
|
+
node bin/index.js test_app
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Link for Local Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npm link
|
|
154
|
+
create-mobile-arch my_test_app
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## ๐ License
|
|
158
|
+
|
|
159
|
+
MIT
|
|
160
|
+
|
|
161
|
+
## ๐ค Contributing
|
|
162
|
+
|
|
163
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
164
|
+
|
|
165
|
+
## ๐ Support
|
|
166
|
+
|
|
167
|
+
If you encounter any issues or have questions:
|
|
168
|
+
- Open an issue on GitHub
|
|
169
|
+
- Check the documentation
|
|
170
|
+
|
|
171
|
+
## ๐ Acknowledgments
|
|
172
|
+
|
|
173
|
+
Inspired by popular project generators like:
|
|
174
|
+
- create-next-app
|
|
175
|
+
- create-vite
|
|
176
|
+
- create-react-app
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
**Built with โค๏ธ for the Flutter community**
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* create-mobile-arch CLI
|
|
5
|
+
* A production-ready CLI tool to generate Flutter project architectures
|
|
6
|
+
*
|
|
7
|
+
* Usage: npx create-mobile-arch <project-name>
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { program } = require('commander');
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const { promptUserChoices, confirmOverwrite, displayConfigSummary } = require('../src/prompts');
|
|
15
|
+
const { generateProject } = require('../src/generator');
|
|
16
|
+
const { validateProjectName, directoryExists, printError } = require('../src/utils');
|
|
17
|
+
|
|
18
|
+
// Package information
|
|
19
|
+
const packageJson = require('../package.json');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Main CLI function
|
|
23
|
+
*/
|
|
24
|
+
async function main() {
|
|
25
|
+
// Display banner
|
|
26
|
+
console.log('\n');
|
|
27
|
+
console.log(chalk.cyan.bold('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ'));
|
|
28
|
+
console.log(chalk.cyan.bold('โ ') + chalk.white.bold('Create Mobile Architecture') + chalk.cyan.bold(' โ'));
|
|
29
|
+
console.log(chalk.cyan.bold('โ ') + chalk.gray('Flutter Project Generator') + chalk.cyan.bold(' โ'));
|
|
30
|
+
console.log(chalk.cyan.bold('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ'));
|
|
31
|
+
console.log('\n');
|
|
32
|
+
|
|
33
|
+
// Configure CLI
|
|
34
|
+
program
|
|
35
|
+
.name('create-mobile-arch')
|
|
36
|
+
.description('Generate a production-ready Flutter project with Clean Architecture or Feature-First pattern')
|
|
37
|
+
.version(packageJson.version, '-v, --version', 'Output the current version')
|
|
38
|
+
.argument('[project-name]', 'Name of your Flutter project')
|
|
39
|
+
.option('-y, --yes', 'Skip prompts and use default configuration')
|
|
40
|
+
.helpOption('-h, --help', 'Display help for command')
|
|
41
|
+
.addHelpText('after', `
|
|
42
|
+
Example:
|
|
43
|
+
$ npx create-mobile-arch my_app
|
|
44
|
+
$ npx create-mobile-arch my_awesome_app -y
|
|
45
|
+
|
|
46
|
+
For more information, visit: https://github.com/yourusername/create-mobile-arch
|
|
47
|
+
`)
|
|
48
|
+
.parse(process.argv);
|
|
49
|
+
|
|
50
|
+
const args = program.args;
|
|
51
|
+
const options = program.opts();
|
|
52
|
+
|
|
53
|
+
// Get project name from arguments
|
|
54
|
+
let projectName = args[0];
|
|
55
|
+
|
|
56
|
+
// If no project name provided, show error
|
|
57
|
+
if (!projectName) {
|
|
58
|
+
printError('Project name is required');
|
|
59
|
+
console.log(chalk.white('Usage:'), chalk.cyan('npx create-mobile-arch <project-name>'));
|
|
60
|
+
console.log('\n');
|
|
61
|
+
console.log(chalk.gray('Example:'), chalk.white('npx create-mobile-arch my_app'));
|
|
62
|
+
console.log('\n');
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Validate project name
|
|
67
|
+
const validation = validateProjectName(projectName);
|
|
68
|
+
if (!validation.valid) {
|
|
69
|
+
printError(validation.error);
|
|
70
|
+
console.log(chalk.gray('Examples of valid names:'), chalk.white('my_app, flutter_project, awesome_app_2024'));
|
|
71
|
+
console.log('\n');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
// Check if directory already exists
|
|
77
|
+
const projectPath = path.join(process.cwd(), projectName);
|
|
78
|
+
const exists = await directoryExists(projectPath);
|
|
79
|
+
|
|
80
|
+
if (exists) {
|
|
81
|
+
// Ask for confirmation to overwrite
|
|
82
|
+
const shouldOverwrite = await confirmOverwrite(projectName);
|
|
83
|
+
|
|
84
|
+
if (!shouldOverwrite) {
|
|
85
|
+
console.log('\n');
|
|
86
|
+
console.log(chalk.yellow('Operation cancelled'));
|
|
87
|
+
console.log('\n');
|
|
88
|
+
process.exit(0);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Remove existing directory
|
|
92
|
+
const fs = require('fs-extra');
|
|
93
|
+
await fs.remove(projectPath);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Get user choices (or use defaults if -y flag)
|
|
97
|
+
let userChoices;
|
|
98
|
+
|
|
99
|
+
if (options.yes) {
|
|
100
|
+
// Use default configuration
|
|
101
|
+
userChoices = {
|
|
102
|
+
architecture: 'clean',
|
|
103
|
+
stateManagement: 'riverpod',
|
|
104
|
+
backend: 'rest',
|
|
105
|
+
includeExamples: true
|
|
106
|
+
};
|
|
107
|
+
console.log(chalk.gray('Using default configuration...'));
|
|
108
|
+
} else {
|
|
109
|
+
// Prompt user for configuration
|
|
110
|
+
userChoices = await promptUserChoices();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Display configuration summary
|
|
114
|
+
displayConfigSummary(projectName, userChoices);
|
|
115
|
+
|
|
116
|
+
// Generate the project
|
|
117
|
+
console.log(chalk.cyan.bold('๐ Generating your Flutter project...'));
|
|
118
|
+
console.log('\n');
|
|
119
|
+
|
|
120
|
+
await generateProject(projectName, userChoices);
|
|
121
|
+
|
|
122
|
+
} catch (error) {
|
|
123
|
+
// Handle errors gracefully
|
|
124
|
+
printError(error.message);
|
|
125
|
+
|
|
126
|
+
if (error.stack && process.env.DEBUG) {
|
|
127
|
+
console.log(chalk.gray('Stack trace:'));
|
|
128
|
+
console.log(chalk.gray(error.stack));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
console.log(chalk.gray('If this issue persists, please report it at:'));
|
|
132
|
+
console.log(chalk.cyan('https://github.com/yourusername/create-mobile-arch/issues'));
|
|
133
|
+
console.log('\n');
|
|
134
|
+
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Run the CLI
|
|
140
|
+
main().catch(error => {
|
|
141
|
+
printError('Unexpected error occurred');
|
|
142
|
+
console.error(error);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-mobile-arch",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A production-ready CLI tool to generate Flutter project architectures with Clean Architecture or Feature-First patterns",
|
|
5
|
+
"main": "bin/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-mobile-arch": "./bin/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node bin/index.js test-app",
|
|
11
|
+
"prepublishOnly": "echo 'Ready to publish'"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"flutter",
|
|
15
|
+
"cli",
|
|
16
|
+
"architecture",
|
|
17
|
+
"clean-architecture",
|
|
18
|
+
"feature-first",
|
|
19
|
+
"riverpod",
|
|
20
|
+
"bloc",
|
|
21
|
+
"scaffold",
|
|
22
|
+
"generator"
|
|
23
|
+
],
|
|
24
|
+
"author": "",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=14.0.0"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"chalk": "^4.1.2",
|
|
31
|
+
"commander": "^11.1.0",
|
|
32
|
+
"fs-extra": "^11.2.0",
|
|
33
|
+
"inquirer": "^8.2.5",
|
|
34
|
+
"ora": "^5.4.1"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/yourusername/create-mobile-arch.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/yourusername/create-mobile-arch/issues"
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/generator.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const ora = require('ora');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const { exec } = require('child_process');
|
|
6
|
+
const util = require('util');
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
copyAndReplace,
|
|
10
|
+
toPascalCase,
|
|
11
|
+
toSnakeCase,
|
|
12
|
+
isFlutterInstalled,
|
|
13
|
+
printSuccessMessage,
|
|
14
|
+
printError
|
|
15
|
+
} = require('./utils');
|
|
16
|
+
|
|
17
|
+
const execPromise = util.promisify(exec);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Main function to generate a Flutter project
|
|
21
|
+
* This is where the template copying happens:
|
|
22
|
+
* - Templates are stored in /templates/flutter-clean directory
|
|
23
|
+
* - The copyAndReplace utility function recursively copies all files
|
|
24
|
+
* - During copy, it replaces placeholders like __APP_NAME__ with actual values
|
|
25
|
+
*
|
|
26
|
+
* @param {string} projectName - Name of the project
|
|
27
|
+
* @param {Object} options - Project configuration options
|
|
28
|
+
* @returns {Promise<void>}
|
|
29
|
+
*/
|
|
30
|
+
async function generateProject(projectName, options) {
|
|
31
|
+
const projectPath = path.join(process.cwd(), projectName);
|
|
32
|
+
let spinner;
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Step 1: Create project directory
|
|
36
|
+
spinner = ora({
|
|
37
|
+
text: 'Creating project directory...',
|
|
38
|
+
color: 'cyan'
|
|
39
|
+
}).start();
|
|
40
|
+
|
|
41
|
+
await fs.ensureDir(projectPath);
|
|
42
|
+
spinner.succeed(chalk.green('Project directory created'));
|
|
43
|
+
|
|
44
|
+
// Step 2: Determine template path based on architecture choice
|
|
45
|
+
const templateName = options.architecture === 'clean' ? 'flutter-clean' : 'flutter-clean';
|
|
46
|
+
const templatePath = path.join(__dirname, '..', 'templates', templateName);
|
|
47
|
+
|
|
48
|
+
// Check if template exists
|
|
49
|
+
const templateExists = await fs.pathExists(templatePath);
|
|
50
|
+
if (!templateExists) {
|
|
51
|
+
throw new Error(`Template not found at ${templatePath}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Step 3: Copy template files and replace placeholders
|
|
55
|
+
// THIS IS WHERE TEMPLATE COPYING HAPPENS
|
|
56
|
+
spinner = ora({
|
|
57
|
+
text: 'Copying template files...',
|
|
58
|
+
color: 'cyan'
|
|
59
|
+
}).start();
|
|
60
|
+
|
|
61
|
+
const replacements = {
|
|
62
|
+
'__APP_NAME__': projectName,
|
|
63
|
+
'__APP_NAME_PASCAL__': toPascalCase(projectName),
|
|
64
|
+
'__APP_NAME_SNAKE__': toSnakeCase(projectName),
|
|
65
|
+
'__STATE_MANAGEMENT__': options.stateManagement,
|
|
66
|
+
'__BACKEND_TYPE__': options.backend
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Copy all files from template directory and replace placeholders
|
|
70
|
+
await copyAndReplace(templatePath, projectPath, replacements);
|
|
71
|
+
spinner.succeed(chalk.green('Template files copied'));
|
|
72
|
+
|
|
73
|
+
// Step 4: Generate README with configuration details
|
|
74
|
+
spinner = ora({
|
|
75
|
+
text: 'Generating project documentation...',
|
|
76
|
+
color: 'cyan'
|
|
77
|
+
}).start();
|
|
78
|
+
|
|
79
|
+
await generateReadme(projectPath, projectName, options);
|
|
80
|
+
spinner.succeed(chalk.green('Documentation generated'));
|
|
81
|
+
|
|
82
|
+
// Step 5: Check if Flutter is installed
|
|
83
|
+
const flutterInstalled = await isFlutterInstalled();
|
|
84
|
+
|
|
85
|
+
if (!flutterInstalled) {
|
|
86
|
+
spinner = ora().warn(chalk.yellow('Flutter not found. Skipping flutter pub get'));
|
|
87
|
+
console.log(chalk.yellow(' Please install Flutter and run "flutter pub get" manually'));
|
|
88
|
+
} else {
|
|
89
|
+
// Step 6: Run flutter pub get
|
|
90
|
+
spinner = ora({
|
|
91
|
+
text: 'Running flutter pub get...',
|
|
92
|
+
color: 'cyan'
|
|
93
|
+
}).start();
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
await execPromise('flutter pub get', {
|
|
97
|
+
cwd: projectPath,
|
|
98
|
+
// Set timeout to 2 minutes
|
|
99
|
+
timeout: 120000
|
|
100
|
+
});
|
|
101
|
+
spinner.succeed(chalk.green('Dependencies installed'));
|
|
102
|
+
} catch (error) {
|
|
103
|
+
spinner.warn(chalk.yellow('Failed to install dependencies'));
|
|
104
|
+
console.log(chalk.gray(` You can run "flutter pub get" manually in the project directory`));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Step 7: Display success message
|
|
109
|
+
printSuccessMessage(projectName, projectPath);
|
|
110
|
+
|
|
111
|
+
} catch (error) {
|
|
112
|
+
if (spinner) {
|
|
113
|
+
spinner.fail(chalk.red('Project generation failed'));
|
|
114
|
+
}
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Generates a comprehensive README.md file for the project
|
|
121
|
+
* @param {string} projectPath - Path to the project directory
|
|
122
|
+
* @param {string} projectName - Name of the project
|
|
123
|
+
* @param {Object} options - Project configuration options
|
|
124
|
+
*/
|
|
125
|
+
async function generateReadme(projectPath, projectName, options) {
|
|
126
|
+
const archName = options.architecture === 'clean' ? 'Clean Architecture' : 'Feature-First Architecture';
|
|
127
|
+
const stateMgmt = options.stateManagement === 'riverpod' ? 'Riverpod' : 'Bloc';
|
|
128
|
+
const backend = options.backend === 'firebase' ? 'Firebase' : 'REST API';
|
|
129
|
+
|
|
130
|
+
const readmeContent = `# ${toPascalCase(projectName)}
|
|
131
|
+
|
|
132
|
+
A Flutter project built with **${archName}** pattern.
|
|
133
|
+
|
|
134
|
+
## ๐ฑ Project Overview
|
|
135
|
+
|
|
136
|
+
This project was generated using \`create-mobile-arch\` CLI tool.
|
|
137
|
+
|
|
138
|
+
### Architecture & Tech Stack
|
|
139
|
+
|
|
140
|
+
- **Architecture Pattern:** ${archName}
|
|
141
|
+
- **State Management:** ${stateMgmt}
|
|
142
|
+
- **Backend Integration:** ${backend}
|
|
143
|
+
|
|
144
|
+
## ๐๏ธ Project Structure
|
|
145
|
+
|
|
146
|
+
\`\`\`
|
|
147
|
+
lib/
|
|
148
|
+
โโโ core/ # Core functionality (constants, themes, utils)
|
|
149
|
+
โโโ data/ # Data layer (repositories, data sources, models)
|
|
150
|
+
โโโ domain/ # Business logic (entities, use cases, interfaces)
|
|
151
|
+
โโโ presentation/ # UI layer (screens, widgets, ${options.stateManagement})
|
|
152
|
+
โโโ main.dart # Application entry point
|
|
153
|
+
\`\`\`
|
|
154
|
+
|
|
155
|
+
## ๐ Getting Started
|
|
156
|
+
|
|
157
|
+
### Prerequisites
|
|
158
|
+
|
|
159
|
+
- Flutter SDK (>=3.0.0)
|
|
160
|
+
- Dart SDK (>=3.0.0)
|
|
161
|
+
${options.backend === 'firebase' ? '- Firebase project setup\n' : ''}
|
|
162
|
+
### Installation
|
|
163
|
+
|
|
164
|
+
1. Get dependencies:
|
|
165
|
+
\`\`\`bash
|
|
166
|
+
flutter pub get
|
|
167
|
+
\`\`\`
|
|
168
|
+
|
|
169
|
+
2. Run the app:
|
|
170
|
+
\`\`\`bash
|
|
171
|
+
flutter run
|
|
172
|
+
\`\`\`
|
|
173
|
+
|
|
174
|
+
## ๐ฆ Dependencies
|
|
175
|
+
|
|
176
|
+
Check \`pubspec.yaml\` for the complete list of dependencies.
|
|
177
|
+
|
|
178
|
+
### Key Packages
|
|
179
|
+
|
|
180
|
+
- **${stateMgmt}:** State management
|
|
181
|
+
${options.backend === 'firebase'
|
|
182
|
+
? '- **Firebase Core, Auth, Firestore:** Backend services\n'
|
|
183
|
+
: '- **HTTP/Dio:** API communication\n'}
|
|
184
|
+
- **Get It:** Dependency injection
|
|
185
|
+
|
|
186
|
+
## ๐งช Testing
|
|
187
|
+
|
|
188
|
+
Run tests:
|
|
189
|
+
\`\`\`bash
|
|
190
|
+
flutter test
|
|
191
|
+
\`\`\`
|
|
192
|
+
|
|
193
|
+
## ๐๏ธ Architecture Details
|
|
194
|
+
|
|
195
|
+
### ${archName}
|
|
196
|
+
|
|
197
|
+
${options.architecture === 'clean'
|
|
198
|
+
? `This project follows Clean Architecture principles with three main layers:
|
|
199
|
+
|
|
200
|
+
1. **Presentation Layer:** UI components, state management
|
|
201
|
+
2. **Domain Layer:** Business logic, use cases, entities
|
|
202
|
+
3. **Data Layer:** API calls, local storage, repositories
|
|
203
|
+
|
|
204
|
+
**Data Flow:** UI โ State Management โ Use Cases โ Repository โ Data Source`
|
|
205
|
+
: `This project follows Feature-First architecture:
|
|
206
|
+
|
|
207
|
+
- Each feature is self-contained in its own directory
|
|
208
|
+
- Features contain their own models, widgets, and logic
|
|
209
|
+
- Shared code is placed in common/core directories`}
|
|
210
|
+
|
|
211
|
+
## ๐ License
|
|
212
|
+
|
|
213
|
+
This project is licensed under the MIT License.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
Generated with โค๏ธ by create-mobile-arch
|
|
218
|
+
`;
|
|
219
|
+
|
|
220
|
+
await fs.writeFile(
|
|
221
|
+
path.join(projectPath, 'README.md'),
|
|
222
|
+
readmeContent,
|
|
223
|
+
'utf8'
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module.exports = {
|
|
228
|
+
generateProject
|
|
229
|
+
};
|