Skip to content

Latest commit

 

History

History
1054 lines (850 loc) · 24 KB

File metadata and controls

1054 lines (850 loc) · 24 KB

Ercode CLI - Comprehensive Documentation

Table of Contents

  1. Overview
  2. Installation
  3. Architecture
  4. Commands
  5. JSON Configuration
  6. Code Generation Process
  7. Generated File Structure
  8. Templates
  9. Helper Functions
  10. Advanced Usage
  11. Examples
  12. Troubleshooting

Overview

Ercode CLI is a powerful code generator tool for Flutter applications that automates the creation of boilerplate code for CRUD (Create, Read, Update, Delete) operations. It generates a complete module structure including models, repositories, controllers, and views based on a simple JSON configuration file.

Key Features

  • 🚀 Rapid Development: Generate complete CRUD modules in seconds
  • 📝 JSON-based Configuration: Simple, declarative module definitions
  • 🏗️ Structured Architecture: Follows clean architecture principles
  • 🎨 Customizable Templates: Pre-built templates for common UI patterns
  • 🔧 Helper Utilities: Built-in API client, state management, and widgets
  • 📦 Dependency Management: Auto-installs required packages

Generated Components

For each module, Ercode CLI generates:

  • Model: Data class with JSON serialization
  • Repository: API communication layer
  • List View: Display data in a list with pagination
  • Add View: Form for creating/editing records
  • Detail View: Display single record details
  • Controllers: State management for each view

Installation

Requirements

  • Dart SDK >= 2.18.6 < 3.0.0
  • Flutter SDK (latest stable version recommended)

Install Globally

# Using dart
dart pub global activate ercode_cli

# Or using flutter
flutter pub global activate ercode_cli

Verify Installation

ercode

You should see:

 ercode

   init                          to init ercode generator
   generate <folder/generator.json>      to generate code

Architecture

Ercode CLI follows a modular architecture with clear separation of concerns:

ercode_cli/
├── bin/
│   └── ercode_cli.dart          # CLI entry point
├── lib/
│   ├── ercode.dart              # Init project functionality
│   ├── generate_code.dart       # Code generation orchestrator
│   ├── models/                  # Data models
│   │   ├── module.dart          # Module configuration model
│   │   └── field.dart           # Field configuration model
│   ├── generator/               # Code generators
│   │   ├── model_generator.dart
│   │   ├── repo_generator.dart
│   │   ├── list/                # List view generators
│   │   ├── add/                 # Add view generators
│   │   └── detail/              # Detail view generators
│   ├── templates/               # Code templates
│   │   ├── model.dart
│   │   ├── repository.dart
│   │   ├── list/
│   │   ├── add/
│   │   └── detail/
│   └── helpers/                 # Utility functions
│       ├── extension.dart       # String extensions
│       ├── rb_helpers.dart      # Helper functions
│       └── cli/                 # CLI utilities
└── templates/
    └── init/                    # Initial project setup

Commands

1. Initialize Project

ercode init

What it does:

  1. Installs required dependencies:

    • dio: HTTP client for API calls
    • pretty_dio_logger: Request/response logging
    • validators: Input validation
    • cached_network_image: Image caching
    • image_picker: Select images from gallery/camera
    • image_crop: Crop images
    • flutter_easyloading: Loading indicators
    • path: File path manipulation
  2. Creates helper files in lib/helpers/:

    • state_util.dart: State management utilities
    • api.dart: API client wrapper
    • constants.dart: App constants (API URL, tokens)
    • validator.dart: Form validation helpers
    • rb_helpers.dart: General helper functions
  3. Creates reusable widgets in lib/widgets/:

    • crop_image.dart: Image cropping widget
    • dialog_confirm.dart: Confirmation dialog
    • dropdown_spinner.dart: Dropdown with loading state
    • edit_text.dart: Custom text input
    • error_layout.dart: Error state display
    • image_text.dart: Image with text widget
    • loading_layout.dart: Loading state display
    • pick_image.dart: Image picker widget
    • show_page.dart: Page navigation helper
    • submit_button.dart: Submit button with loading
    • text_info.dart: Info text display
  4. Creates models in lib/models/:

    • response_data.dart: Standardized API response model
  5. Modifies lib/main.dart:

    • Adds required imports
    • Configures EasyLoading
    • Sets up navigation key

Post-initialization: Edit lib/helpers/constants.dart to set your API configuration:

const baseUrl = 'https://your-api.com/api';
const apiToken = 'your-api-token'; // Optional

2. Generate Code

ercode generate <path-to-json-config>

Examples:

# Generate from generator folder
ercode generate generator/book.json

# Generate from any path
ercode generate config/user.json

# Force overwrite existing files
ercode generate generator/book.json force

What it does: Reads the JSON configuration and generates:

  • Model class
  • Repository class
  • List controller & view
  • Add/Edit controller & view
  • Detail controller & view

Force Mode: By default, existing files are not overwritten. Use the force argument to replace existing files.


JSON Configuration

Basic Structure

{
  "name": "module_name",
  "api": "api_endpoint",
  "modelName": "ModelName",
  "only": [],
  "fields": [
    {
      "name": "field_name",
      "type": "String",
      "input": "text",
      "hidden": false,
      "primary": false,
      "list": true
    }
  ]
}

Module Parameters

Parameter Type Required Default Description
name String ✅ Yes - Module name (used for folder/file names)
api String ❌ No Same as name API endpoint path
modelName String ❌ No Same as name Model class name
only Array ❌ No [] Limit generation to specific components
fields Array ✅ Yes - List of field configurations

only values:

  • "model": Generate only the model class
  • "repository": Generate only the repository
  • "list": Generate list controller & view
  • "add": Generate add/edit controller & view
  • "detail": Generate detail controller & view

Example - Generate only model and repository:

{
  "name": "product",
  "only": ["model", "repository"],
  "fields": [...]
}

Field Parameters

Parameter Type Required Default Description
name String ✅ Yes - Field name (snake_case recommended)
type String ❌ No "String" Dart data type
input String ❌ No "text" Input type for forms
hidden Boolean ❌ No false Hide from create/edit forms
primary Boolean ❌ No false Mark as primary key (usually id)
list Boolean ❌ No false Show in list view

Supported Data Types:

  • String: Text data
  • int: Integer numbers
  • bool: Boolean values
  • double: Floating-point numbers (experimental)

Supported Input Types:

  • text: Text input field (default)
  • image: Image picker with upload

Field Naming Convention:

  • Use snake_case in JSON: "release_year"
  • Converts to camelCase in code: releaseYear
  • Converts to PascalCase for classes: ReleaseYear

Automatic Fields

Every model automatically includes timestamp fields:

  • createdAt: DateTime?
  • updatedAt: DateTime?
  • deletedAt: DateTime?

These are added automatically and don't need to be specified in the JSON.


Code Generation Process

1. Parse JSON Configuration

The generator reads the JSON file and creates a Module object:

// lib/models/module.dart
class Module {
  final String name;
  final String api;
  final String modelName;
  final List<String> only;
  List<Field>? fields;
}

// lib/models/field.dart
class Field {
  final String name;
  final String type;
  final String input;
  final bool hidden;
  final bool showList;
  final bool primary;
}

2. Generate Model

Location: lib/modules/{module_name}/data/{model_name}.dart

Generated Code:

  • Class with all fields as properties
  • Constructor with named parameters
  • toMap(): Convert to Map<String, dynamic>
  • fromMap(): Create instance from Map
  • toJson(): Serialize to JSON string
  • fromJson(): Deserialize from JSON string
  • toString(): String representation

Example Output:

class Book {
  final int id;
  final String cover;
  final String name;
  final String author;
  DateTime? createdAt;
  DateTime? updatedAt;
  DateTime? deletedAt;

  Book({
    required this.id,
    required this.cover,
    required this.name,
    required this.author,
    this.createdAt,
    this.updatedAt,
    this.deletedAt,
  });

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'cover': cover,
      'name': name,
      'author': author,
      'created_at': createdAt,
      'updated_at': updatedAt,
      'deleted_at': deletedAt,
    };
  }

  factory Book.fromMap(Map<String, dynamic> map) {
    return Book(
      id: map['id'] ?? 0,
      cover: map['cover'] ?? '',
      name: map['name'] ?? '',
      author: map['author'] ?? '',
      createdAt: DateTime.tryParse(map['created_at'] ?? ''),
      updatedAt: DateTime.tryParse(map['updated_at'] ?? ''),
      deletedAt: DateTime.tryParse(map['deleted_at'] ?? ''),
    );
  }

  String toJson() => json.encode(toMap());

  factory Book.fromJson(String source) =>
      Book.fromMap(json.decode(source));

  @override
  String toString() => 'Book(id: $id, cover: $cover, name: $name, author: $author)';
}

3. Generate Repository

Location: lib/modules/{module_name}/data/{module_name}_repository.dart

Generated Methods:

  • getData(): Fetch list with optional pagination
  • getDetail(id): Fetch single record
  • save(url, params): Create or update record
  • delete(id): Delete record

Features:

  • Error handling with callbacks
  • Success/error callbacks
  • Integration with API helper
  • ResponseData wrapper for consistent responses

4. Generate List View

Files Generated:

  • Controller: lib/modules/{module_name}/controllers/{module_name}_controller.dart
  • View: lib/modules/{module_name}/views/{module_name}_view.dart
  • View Item: lib/modules/{module_name}/views/{module_name}_view_item.dart

List Controller Features:

  • Fetch data from repository
  • Handle loading/error states
  • Navigation to detail/add views
  • Pull-to-refresh support

List View Features:

  • AppBar with add button
  • Loading indicator
  • Error display
  • List of items (only shows fields marked with "list": true)
  • Pull to refresh
  • Tap to view details

5. Generate Add/Edit View

Files Generated:

  • Controller: lib/modules/{module_name}/controllers/{module_name}_add_controller.dart
  • View: lib/modules/{module_name}/views/{module_name}_add_view.dart
  • View Item: lib/modules/{module_name}/views/{module_name}_add_view_item.dart

Add Controller Features:

  • Form validation
  • Edit mode detection
  • Image upload handling
  • Success/error callbacks
  • Auto-navigation on success

Add View Features:

  • Form with validation
  • Text fields for text inputs
  • Image picker for image inputs
  • Submit button with loading state
  • Edit mode support (pre-fills form)

Input Type Handling:

Text Input:

// Generated controller code
final txtName = TextEditingController();

// Form parameters
'name': txtName.text,

Image Input:

// Generated controller code
var coverImage = '';
var coverImageError = '';

setCoverImage(String v) {
  setState(() {
    coverImage = v;
  });
}

// Upload parameters
if (coverImage.isNotEmpty) {
  File file = File(coverImage);
  params['cover_image'] = await dio.MultipartFile.fromFile(
    file.path,
    filename: basename(file.path),
  );
}

6. Generate Detail View

Files Generated:

  • Controller: lib/modules/{module_name}/controllers/{module_name}_detail_controller.dart
  • View: lib/modules/{module_name}/views/{module_name}_detail_view.dart
  • View Item: lib/modules/{module_name}/views/{module_name}_detail_view_item.dart

Detail Controller Features:

  • Fetch single record
  • Edit navigation
  • Delete confirmation
  • Loading states

Detail View Features:

  • Display all field values
  • Edit button
  • Delete button with confirmation
  • Loading indicator
  • Error handling

Generated File Structure

After running ercode generate generator/book.json, the following structure is created:

lib/
└── modules/
    └── book/
        ├── data/
        │   ├── book.dart                    # Model
        │   └── book_repository.dart         # Repository
        ├── controllers/
        │   ├── book_controller.dart         # List controller
        │   ├── book_add_controller.dart     # Add/Edit controller
        │   └── book_detail_controller.dart  # Detail controller
        └── views/
            ├── book_view.dart               # List view
            ├── book_view_item.dart          # List item widget
            ├── book_add_view.dart           # Add/Edit view
            ├── book_add_view_item.dart      # Add/Edit form widget
            ├── book_detail_view.dart        # Detail view
            └── book_detail_view_item.dart   # Detail display widget

Templates

Templates are located in lib/templates/ and use placeholder strings that are replaced during generation:

Template Placeholders

Placeholder Description Example Replacement
@ClassName Pascal case class name Book
@className Pascal case module name Book
@modelName Model class name Book
@varName Camel case variable name book
@filename Snake case file name book
@filenameModel Snake case model file book
@packageName Project package name my_app
@api API endpoint books
@variableName Generated field declarations final String name;
@constructorVar Generated constructor params required this.name,
@toMapVar Generated toMap fields 'name': name,
@fromMapVar Generated fromMap fields name: map['name'] ?? '',
@toStringVar Generated toString fields name: $name,
@varInput Generated input variables final txtName = TextEditingController();
@varParameters Generated form parameters 'name': txtName.text,

Template Files

  1. Model Template (templates/model.dart)

    • Basic model class structure
    • JSON serialization methods
  2. Repository Template (templates/repository.dart)

    • CRUD operation methods
    • API integration
    • Error handling
  3. List Templates (templates/list/)

    • controller.dart: List state management
    • view.dart: List page scaffold
    • view_item.dart: List item widget
  4. Add Templates (templates/add/)

    • controller.dart: Form state management
    • view.dart: Form page scaffold
    • view_item.dart: Form fields
  5. Detail Templates (templates/detail/)

    • controller.dart: Detail state management
    • view.dart: Detail page scaffold
    • view_item.dart: Detail display

Helper Functions

String Extensions (helpers/extension.dart)

// Convert to PascalCase
"book_store".pascalCase  // "BookStore"

// Convert to camelCase
"book_store".camelCase   // "bookStore"

// Convert to snake_case
"Book Store".toLowerCaseWithUnderscore()  // "book_store"

// Convert to spaces
"book_store".toLowerCaseSpace()  // "book store"

API Helper (helpers/api.dart)

Generated API client with methods:

  • get(url, {params, onSuccess, onError}): GET request
  • post(url, params, {onSuccess, onError}): POST request
  • put(url, params, {onSuccess, onError}): PUT request
  • delete(url, {onSuccess, onError}): DELETE request

Features:

  • Automatic auth token injection
  • Request/response logging
  • Error handling
  • Base URL configuration

State Utilities (helpers/state_util.dart)

enum ConnectionStatus { loading, done, error }

// Navigation helper
Get.to(AnotherPage());
Get.back();

Validator Helper (helpers/validator.dart)

Form validation helpers:

  • Required field validation
  • Email validation
  • Min/max length validation
  • Custom pattern validation

RB Helpers (helpers/rb_helpers.dart)

Utility functions:

  • readJsonFile(path): Read and parse JSON config
  • formatterDartFile(content): Format Dart code
  • trace(error, stackTrace): Error logging

Advanced Usage

Custom API Endpoint

{
  "name": "user",
  "api": "users/v2",
  "fields": [...]
}

Generated repository will use /users/v2 instead of /user.

Custom Model Name

{
  "name": "product",
  "modelName": "item",
  "fields": [...]
}
  • Folder: lib/modules/product/
  • Model class: Item
  • Model file: item.dart

Partial Generation

Generate only specific components:

{
  "name": "category",
  "only": ["model", "repository"],
  "fields": [...]
}

Primary Key Configuration

{
  "fields": [
    {
      "name": "id",
      "type": "int",
      "primary": true,
      "hidden": true
    }
  ]
}
  • primary: true: Treats as ID field (skipped in forms)
  • hidden: true: Excluded from create/edit views

Hidden Fields

{
  "fields": [
    {
      "name": "created_by",
      "type": "int",
      "hidden": true
    }
  ]
}

Field exists in model but not in forms (useful for auto-populated server fields).

Force Overwrite

ercode generate generator/book.json force

Replaces existing files without prompts.


Examples

Example 1: Simple Blog Post

Config (generator/post.json):

{
  "name": "post",
  "fields": [
    {
      "name": "id",
      "type": "int",
      "primary": true,
      "hidden": true
    },
    {
      "name": "title",
      "type": "String",
      "list": true
    },
    {
      "name": "content",
      "type": "String"
    },
    {
      "name": "author",
      "type": "String",
      "list": true
    },
    {
      "name": "published",
      "type": "bool"
    }
  ]
}

Generate:

ercode generate generator/post.json

Result:

  • Model with all fields
  • Repository with CRUD operations
  • List showing title and author
  • Form with title, content, author, and published fields
  • Detail view showing all information

Example 2: E-commerce Product

Config (generator/product.json):

{
  "name": "product",
  "api": "products/v1",
  "fields": [
    {
      "name": "id",
      "type": "int",
      "primary": true,
      "hidden": true
    },
    {
      "name": "image",
      "type": "String",
      "input": "image",
      "list": true
    },
    {
      "name": "name",
      "type": "String",
      "list": true
    },
    {
      "name": "price",
      "type": "int",
      "list": true
    },
    {
      "name": "description",
      "type": "String"
    },
    {
      "name": "stock",
      "type": "int"
    },
    {
      "name": "category",
      "type": "String",
      "list": true
    }
  ]
}

Generate:

ercode generate generator/product.json

Result:

  • Product model with image upload support
  • List showing image, name, price, and category
  • Form with image picker, text inputs
  • API calls to /products/v1 endpoint

Example 3: User Profile (Model Only)

Config (generator/profile.json):

{
  "name": "profile",
  "only": ["model"],
  "fields": [
    {
      "name": "id",
      "type": "int",
      "primary": true
    },
    {
      "name": "name",
      "type": "String"
    },
    {
      "name": "email",
      "type": "String"
    },
    {
      "name": "avatar",
      "type": "String"
    },
    {
      "name": "bio",
      "type": "String"
    }
  ]
}

Generate:

ercode generate generator/profile.json

Result:

  • Only generates lib/modules/profile/data/profile.dart
  • No views, controllers, or repository

Troubleshooting

Issue: "File already exists"

Solution: Use force mode to overwrite:

ercode generate generator/book.json force

Issue: Package not found

Solution: Ensure you have the dependencies installed:

flutter pub get

Issue: API calls not working

Solution:

  1. Check lib/helpers/constants.dart has correct baseUrl
  2. Verify API endpoint in JSON config
  3. Check network connectivity
  4. Enable logging in lib/helpers/api.dart

Issue: Import errors after generation

Solution: Run Flutter's code generator:

flutter pub get
dart fix --apply

Issue: JSON parse error

Solution: Validate your JSON:

  • Use a JSON validator
  • Check for trailing commas
  • Ensure all strings are quoted
  • Verify proper bracket matching

Issue: Generated code formatting issues

Solution: Run Dart formatter:

dart format lib/

Issue: Constants file not created

Solution: Run init again:

ercode init

Best Practices

1. Module Organization

  • Use descriptive, lowercase module names
  • Group related modules in subfolders
  • Keep JSON configs in a generator/ folder

2. Field Naming

  • Use snake_case in JSON configurations
  • Avoid reserved Dart keywords
  • Be consistent with backend field names

3. API Structure

  • Design RESTful endpoints
  • Use consistent response formats
  • Return proper HTTP status codes

4. Version Control

  • Commit JSON configs to version control
  • Consider .gitignore for generated code if regenerating frequently
  • Document custom modifications to generated code

5. Customization

  • Modify templates for project-specific needs
  • Extend generated classes carefully
  • Use inheritance for shared functionality

API Response Format

Ercode CLI expects the following response format from your API:

List Response

{
  "message": "Success",
  "data": {
    "data": [
      {"id": 1, "name": "Item 1"},
      {"id": 2, "name": "Item 2"}
    ],
    "current_page": 1,
    "total": 50
  }
}

Non-Paginated List

{
  "message": "Success",
  "data": [
    {"id": 1, "name": "Item 1"},
    {"id": 2, "name": "Item 2"}
  ]
}

Use params['paginate'] = 'no' in repository call.

Single Item Response

{
  "message": "Success",
  "data": {
    "id": 1,
    "name": "Item 1",
    "description": "Description"
  }
}

Success Response (Create/Update/Delete)

{
  "message": "Record created successfully"
}

Dependencies

Ercode CLI automatically installs:

Package Version Purpose
dio ^4.0.6 HTTP client
pretty_dio_logger ^1.2.0-beta-1 Request logging
validators ^3.0.0 Input validation
cached_network_image ^3.2.3 Image caching
image_picker ^0.8.6+1 Image selection
image_crop ^0.4.1 Image cropping
flutter_easyloading ^3.0.5 Loading indicators
path ^1.8.3 Path manipulation

Contributing

To contribute to Ercode CLI:

  1. Fork the repository on GitHub
  2. Create a feature branch
  3. Make your changes
  4. Write/update tests
  5. Submit a pull request

Repository: https://github.com/xrb21/ercode_cli


License

Check the LICENSE file for details.


Support

For issues, questions, or contributions:


Changelog

See CHANGELOG.md for version history and updates.


Version: 1.0.2+1
Last Updated: 2026
Author: xrb21