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 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
+ }
@@ -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
+ };