# Metro CLI Araci

<div id="introduction"></div>

## Giris

Metro, Nylo framework'unun arka planinda calisan bir CLI aracidir.
Gelistirmeyi hizlandirmak icin bircok yararli arac saglar.

<div id="install"></div>

## Kurulum

`nylo init` kullanarak yeni bir Nylo projesi olusturdugunuzda, `metro` komutu terminaliniz icin otomatik olarak yapilandirilir. Herhangi bir Nylo projesinde hemen kullanmaya baslayabilirsiniz.

Tum kullanilabilir komutlari gormek icin proje dizininizden `metro` komutunu calistirin:

``` bash
metro
```

Asagidakine benzer bir cikti gormelisiniz.

``` bash
Metro - Nylo's Companion to Build Flutter apps by Anthony Gordon

Usage:
    command [options] [arguments]

Options
    -h

All commands:

[Widget Commands]
  make:page
  make:stateful_widget
  make:stateless_widget
  make:state_managed_widget
  make:navigation_hub
  make:journey_widget
  make:bottom_sheet_modal
  make:button
  make:form

[Helper Commands]
  make:model
  make:provider
  make:api_service
  make:controller
  make:event
  make:theme
  make:route_guard
  make:config
  make:interceptor
  make:command
  make:env
  make:key
```

<div id="make-controller"></div>

## Controller olusturma

- [Yeni bir controller olusturma](#making-a-new-controller "Metro ile yeni bir controller olusturma")
- [Zorunlu controller olusturma](#forcefully-make-a-controller "Metro ile zorunlu controller olusturma")
<div id="making-a-new-controller"></div>

### Yeni bir controller olusturma

Terminalde asagidaki komutu calistirarak yeni bir controller olusturabilirsiniz.

``` bash
metro make:controller profile_controller
```

Bu, `lib/app/controllers/` dizininde mevcut degilse yeni bir controller olusturacaktir.

<div id="forcefully-make-a-controller"></div>

### Zorunlu controller olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir controller varsa uzerine yazilacaktir.

``` bash
metro make:controller profile_controller --force
```

<div id="make-model"></div>

## Model olusturma

- [Yeni bir model olusturma](#making-a-new-model "Metro ile yeni bir model olusturma")
- [JSON'dan model olusturma](#make-model-from-json "Metro ile JSON'dan yeni bir model olusturma")
- [Zorunlu model olusturma](#forcefully-make-a-model "Metro ile zorunlu model olusturma")
<div id="making-a-new-model"></div>

### Yeni bir model olusturma

Terminalde asagidaki komutu calistirarak yeni bir model olusturabilirsiniz.

``` bash
metro make:model product
```

Yeni olusturulan model `lib/app/models/` dizinine yerlestirilecektir.

<div id="make-model-from-json"></div>

### JSON'dan model olusturma

**Argumenler:**

`--json` veya `-j` bayragi kullanildiginda, bir JSON verisi uzerinden yeni bir model olusturulacaktir.

``` bash
metro make:model product --json
```

Ardindan JSON verinizi terminale yapistirabilirsiniz ve sizin icin bir model olusturulacaktir.

<div id="forcefully-make-a-model"></div>

### Zorunlu model olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir model varsa uzerine yazilacaktir.

``` bash
metro make:model product --force
```

<div id="make-page"></div>

## Sayfa olusturma

- [Yeni bir sayfa olusturma](#making-a-new-page "Metro ile yeni bir sayfa olusturma")
- [Controller ile sayfa olusturma](#create-a-page-with-a-controller "Metro ile controller'li yeni bir sayfa olusturma")
- [Auth sayfasi olusturma](#create-an-auth-page "Metro ile yeni bir auth sayfasi olusturma")
- [Baslangic sayfasi olusturma](#create-an-initial-page "Metro ile yeni bir baslangic sayfasi olusturma")
- [Zorunlu sayfa olusturma](#forcefully-make-a-page "Metro ile zorunlu sayfa olusturma")

<div id="making-a-new-page"></div>

### Yeni bir sayfa olusturma

Terminalde asagidaki komutu calistirarak yeni bir sayfa olusturabilirsiniz.

``` bash
metro make:page product_page
```

Bu, `lib/resources/pages/` dizininde mevcut degilse yeni bir sayfa olusturacaktir.

<div id="create-a-page-with-a-controller"></div>

### Controller ile sayfa olusturma

Terminalde asagidaki komutu calistirarak controller'li yeni bir sayfa olusturabilirsiniz.

**Argumenler:**

`--controller` veya `-c` bayragi kullanildiginda, controller'li yeni bir sayfa olusturulacaktir.

``` bash
metro make:page product_page -c
```

<div id="create-an-auth-page"></div>

### Auth sayfasi olusturma

Terminalde asagidaki komutu calistirarak yeni bir auth sayfasi olusturabilirsiniz.

**Argumenler:**

`--auth` veya `-a` bayragi kullanildiginda, yeni bir auth sayfasi olusturulacaktir.

``` bash
metro make:page login_page -a
```

<div id="create-an-initial-page"></div>

### Baslangic sayfasi olusturma

Terminalde asagidaki komutu calistirarak yeni bir baslangic sayfasi olusturabilirsiniz.

**Argumenler:**

`--initial` veya `-i` bayragi kullanildiginda, yeni bir baslangic sayfasi olusturulacaktir.

``` bash
metro make:page home_page -i
```

<div id="forcefully-make-a-page"></div>

### Zorunlu sayfa olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir sayfa varsa uzerine yazilacaktir.

``` bash
metro make:page product_page --force
```

<div id="make-stateless-widget"></div>

## Stateless widget olusturma

- [Yeni bir stateless widget olusturma](#making-a-new-stateless-widget "Metro ile yeni bir stateless widget olusturma")
- [Zorunlu stateless widget olusturma](#forcefully-make-a-stateless-widget "Metro ile zorunlu stateless widget olusturma")
<div id="making-a-new-stateless-widget"></div>

### Yeni bir stateless widget olusturma

Terminalde asagidaki komutu calistirarak yeni bir stateless widget olusturabilirsiniz.

``` bash
metro make:stateless_widget product_rating_widget
```

Yukaridaki komut, `lib/resources/widgets/` dizininde mevcut degilse yeni bir widget olusturacaktir.

Tüm `make:*` komutları, dosyayı bir alt dizine yerleştirmek için adda yol ayırıcısı kabul eder:

``` bash
metro make:stateless_widget login/BrandPanel
```

Bu, widget'ı `lib/resources/widgets/login/brand_panel.dart` konumunda oluşturur.

<div id="forcefully-make-a-stateless-widget"></div>

### Zorunlu stateless widget olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir widget varsa uzerine yazilacaktir.

``` bash
metro make:stateless_widget product_rating_widget --force
```

<div id="make-stateful-widget"></div>

## Stateful widget olusturma

- [Yeni bir stateful widget olusturma](#making-a-new-stateful-widget "Metro ile yeni bir stateful widget olusturma")
- [Zorunlu stateful widget olusturma](#forcefully-make-a-stateful-widget "Metro ile zorunlu stateful widget olusturma")

<div id="making-a-new-stateful-widget"></div>

### Yeni bir stateful widget olusturma

Terminalde asagidaki komutu calistirarak yeni bir stateful widget olusturabilirsiniz.

``` bash
metro make:stateful_widget product_rating_widget
```

Yukaridaki komut, `lib/resources/widgets/` dizininde mevcut degilse yeni bir widget olusturacaktir.

<div id="forcefully-make-a-stateful-widget"></div>

### Zorunlu stateful widget olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir widget varsa uzerine yazilacaktir.

``` bash
metro make:stateful_widget product_rating_widget --force
```

<div id="make-journey-widget"></div>

## Journey widget olusturma

- [Yeni bir journey widget olusturma](#making-a-new-journey-widget "Metro ile yeni bir journey widget olusturma")
- [Zorunlu journey widget olusturma](#forcefully-make-a-journey-widget "Metro ile zorunlu journey widget olusturma")

<div id="making-a-new-journey-widget"></div>

### Yeni bir journey widget olusturma

Terminalde asagidaki komutu calistirarak yeni bir journey widget olusturabilirsiniz.

``` bash
metro make:journey_widget product_journey --parent="[NAVIGATION_HUB]"

# BaseNavigationHub varsa tam örnek
metro make:journey_widget welcome,user_dob,user_photos --parent="Base"
```

Yukaridaki komut, `lib/resources/widgets/` dizininde mevcut degilse yeni bir widget olusturacaktir.

`--parent` argumani, yeni journey widget'in eklenmesi gereken ust widget'i belirtmek icin kullanilir.

Ornek

``` bash
metro make:navigation_hub onboarding
```

Ardindan, yeni journey widget'leri ekleyin.
``` bash
metro make:journey_widget welcome,user_dob,user_photos --parent="onboarding"
```

<div id="forcefully-make-a-journey-widget"></div>

### Zorunlu journey widget olusturma
**Argumenler:**
`--force` veya `-f` bayragi kullanildiginda, mevcut bir widget varsa uzerine yazilacaktir.

``` bash
metro make:journey_widget product_journey --force --parent="[YOUR_NAVIGATION_HUB]"
```

<div id="make-api-service"></div>

## API Servisi olusturma

- [Yeni bir API Servisi olusturma](#making-a-new-api-service "Metro ile yeni bir API Servisi olusturma")
- [Model ile yeni bir API Servisi olusturma](#making-a-new-api-service-with-a-model "Metro ile model'li yeni bir API Servisi olusturma")
- [Postman ile API Servisi olusturma](#make-api-service-using-postman "Postman ile API servisleri olusturma")
- [Zorunlu API Servisi olusturma](#forcefully-make-an-api-service "Metro ile zorunlu API Servisi olusturma")

<div id="making-a-new-api-service"></div>

### Yeni bir API Servisi olusturma

Terminalde asagidaki komutu calistirarak yeni bir API servisi olusturabilirsiniz.

``` bash
metro make:api_service user_api_service
```

Yeni olusturulan API servisi `lib/app/networking/` dizinine yerlestirilecektir.

<div id="making-a-new-api-service-with-a-model"></div>

### Model ile yeni bir API Servisi olusturma

Terminalde asagidaki komutu calistirarak model'li yeni bir API servisi olusturabilirsiniz.

**Argumenler:**

`--model` veya `-m` secenegi kullanildiginda, model'li yeni bir API servisi olusturulacaktir.

``` bash
metro make:api_service user --model="User"
```

Yeni olusturulan API servisi `lib/app/networking/` dizinine yerlestirilecektir.

### Zorunlu API Servisi olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir API Servisi varsa uzerine yazilacaktir.

``` bash
metro make:api_service user --force
```

<div id="make-event"></div>

## Event olusturma

- [Yeni bir event olusturma](#making-a-new-event "Metro ile yeni bir event olusturma")
- [Zorunlu event olusturma](#forcefully-make-an-event "Metro ile zorunlu event olusturma")

<div id="making-a-new-event"></div>

### Yeni bir event olusturma

Terminalde asagidaki komutu calistirarak yeni bir event olusturabilirsiniz.

``` bash
metro make:event login_event
```

Bu, `lib/app/events` dizininde yeni bir event olusturacaktir.

Olayı bir alt dizinde düzenlemek için yol ayırıcısı kullanın:

``` bash
metro make:event auth/login_event
```

Bu, olayı `lib/app/events/auth/login_event.dart` konumunda oluşturur.

<div id="forcefully-make-an-event"></div>

### Zorunlu event olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir event varsa uzerine yazilacaktir.

``` bash
metro make:event login_event --force
```

<div id="make-provider"></div>

## Provider olusturma

- [Yeni bir provider olusturma](#making-a-new-provider "Metro ile yeni bir provider olusturma")
- [Zorunlu provider olusturma](#forcefully-make-a-provider "Metro ile zorunlu provider olusturma")

<div id="making-a-new-provider"></div>

### Yeni bir provider olusturma

Asagidaki komutu kullanarak uygulamanizda yeni provider'lar olusturun.

``` bash
metro make:provider firebase_provider
```

Yeni olusturulan provider `lib/app/providers/` dizinine yerlestirilecektir.

Provider'ı bir alt dizinde düzenlemek için yol ayırıcısı kullanın:

``` bash
metro make:provider integrations/firebase_provider
```

Bu, provider'ı `lib/app/providers/integrations/firebase_provider.dart` konumunda oluşturur.

<div id="forcefully-make-a-provider"></div>

### Zorunlu provider olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir provider varsa uzerine yazilacaktir.

``` bash
metro make:provider firebase_provider --force
```

<div id="make-theme"></div>

## Tema olusturma

- [Yeni bir tema olusturma](#making-a-new-theme "Metro ile yeni bir tema olusturma")
- [Zorunlu tema olusturma](#forcefully-make-a-theme "Metro ile zorunlu tema olusturma")

<div id="making-a-new-theme"></div>

### Yeni bir tema olusturma

Terminalde asagidaki komutu calistirarak tema olusturabilirsiniz.

``` bash
metro make:theme bright_theme
```

Bu, `lib/resources/themes/` dizininde yeni bir tema olusturacaktir.

<div id="forcefully-make-a-theme"></div>

### Zorunlu tema olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir tema varsa uzerine yazilacaktir.

``` bash
metro make:theme bright_theme --force
```

<div id="make-forms"></div>

## Form olusturma

- [Yeni bir form olusturma](#making-a-new-form "Metro ile yeni bir form olusturma")
- [Zorunlu form olusturma](#forcefully-make-a-form "Metro ile zorunlu form olusturma")

<div id="making-a-new-form"></div>

### Yeni bir form olusturma

Terminalde asagidaki komutu calistirarak yeni bir form olusturabilirsiniz.

``` bash
metro make:form car_advert_form
```

Bu, `lib/app/forms` dizininde yeni bir form olusturacaktir.

Formu bir alt dizinde düzenlemek için yol ayırıcısı kullanın:

``` bash
metro make:form checkout/car_advert_form
```

Bu, formu `lib/app/forms/checkout/car_advert_form.dart` konumunda oluşturur.

<div id="forcefully-make-a-form"></div>

### Zorunlu form olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir form varsa uzerine yazilacaktir.

``` bash
metro make:form login_form --force
```

<div id="make-route-guard"></div>

## Route Guard olusturma

- [Yeni bir route guard olusturma](#making-a-new-route-guard "Metro ile yeni bir route guard olusturma")
- [Zorunlu route guard olusturma](#forcefully-make-a-route-guard "Metro ile zorunlu route guard olusturma")

<div id="making-a-new-route-guard"></div>

### Yeni bir route guard olusturma

Terminalde asagidaki komutu calistirarak bir route guard olusturabilirsiniz.

``` bash
metro make:route_guard premium_content
```

Bu, `lib/app/route_guards` dizininde yeni bir route guard olusturacaktir.

Guard'ı bir alt dizinde düzenlemek için yol ayırıcısı kullanın:

``` bash
metro make:route_guard subscriptions/premium_content
```

Bu, guard'ı `lib/app/route_guards/subscriptions/premium_content.dart` konumunda oluşturur.

<div id="forcefully-make-a-route-guard"></div>

### Zorunlu route guard olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir route guard varsa uzerine yazilacaktir.

``` bash
metro make:route_guard premium_content --force
```

<div id="make-config-file"></div>

## Config dosyasi olusturma

- [Yeni bir config dosyasi olusturma](#making-a-new-config-file "Metro ile yeni bir config dosyasi olusturma")
- [Zorunlu config dosyasi olusturma](#forcefully-make-a-config-file "Metro ile zorunlu config dosyasi olusturma")

<div id="making-a-new-config-file"></div>

### Yeni bir config dosyasi olusturma

Terminalde asagidaki komutu calistirarak yeni bir config dosyasi olusturabilirsiniz.

``` bash
metro make:config shopping_settings
```

Bu, `lib/app/config` dizininde yeni bir config dosyasi olusturacaktir.

<div id="forcefully-make-a-config-file"></div>

### Zorunlu config dosyasi olusturma

**Argumenler:**

`--force` veya `-f` bayragi kullanildiginda, mevcut bir config dosyasi varsa uzerine yazilacaktir.

``` bash
metro make:config app_config --force
```


<div id="make-command"></div>

## Komut olusturma

- [Yeni bir komut olusturma](#making-a-new-command "Metro ile yeni bir komut olusturma")
- [Zorunlu komut olusturma](#forcefully-make-a-command "Metro ile zorunlu komut olusturma")

<div id="making-a-new-command"></div>

### Yeni bir komut olusturma

Terminalde asagidaki komutu calistirarak yeni bir komut olusturabilirsiniz.

``` bash
metro make:command my_command
```

Bu, `lib/app/commands` dizininde yeni bir komut olusturacaktir.

<div id="forcefully-make-a-command"></div>

### Zorunlu komut olusturma

**Argumenler:**
`--force` veya `-f` bayragi kullanildiginda, mevcut bir komut varsa uzerine yazilacaktir.

``` bash
metro make:command my_command --force
```


<div id="make-state-managed-widget"></div>

## State Managed Widget olusturma

Terminalde asagidaki komutu calistirarak yeni bir state managed widget olusturabilirsiniz.

``` bash
metro make:state_managed_widget product_rating_widget
```

Yukaridaki komut `lib/resources/widgets/` dizininde yeni bir widget olusturacaktir.

`--force` veya `-f` bayragi kullanildiginda, mevcut bir widget varsa uzerine yazilacaktir.

``` bash
metro make:state_managed_widget product_rating_widget --force
```

<div id="make-navigation-hub"></div>

## Navigation Hub olusturma

Terminalde asagidaki komutu calistirarak yeni bir navigation hub olusturabilirsiniz.

``` bash
metro make:navigation_hub dashboard
```

Bu, `lib/resources/pages/` dizininde yeni bir navigation hub olusturacak ve route'u otomatik olarak ekleyecektir.

**Argumenler:**

| Bayrak | Kisaltma | Aciklama |
|------|-------|-------------|
| `--auth` | `-a` | Auth sayfasi olarak olustur |
| `--initial` | `-i` | Baslangic sayfasi olarak olustur |
| `--force` | `-f` | Mevcutsa uzerine yaz |

``` bash
# Başlangıç sayfası olarak oluştur
metro make:navigation_hub dashboard --initial
```

<div id="make-bottom-sheet-modal"></div>

## Bottom Sheet Modal olusturma

Terminalde asagidaki komutu calistirarak yeni bir bottom sheet modal olusturabilirsiniz.

``` bash
metro make:bottom_sheet_modal payment_options
```

Bu, `lib/resources/widgets/` dizininde yeni bir bottom sheet modal olusturacaktir.

`--force` veya `-f` bayragi kullanildiginda, mevcut bir modal varsa uzerine yazilacaktir.

``` bash
metro make:bottom_sheet_modal payment_options --force
```

<div id="make-button"></div>

## Button olusturma

Terminalde asagidaki komutu calistirarak yeni bir button widget'i olusturabilirsiniz.

``` bash
metro make:button checkout_button
```

Bu, `lib/resources/widgets/` dizininde yeni bir button widget'i olusturacaktir.

`--force` veya `-f` bayragi kullanildiginda, mevcut bir button varsa uzerine yazilacaktir.

``` bash
metro make:button checkout_button --force
```

<div id="make-interceptor"></div>

## Interceptor olusturma

Terminalde asagidaki komutu calistirarak yeni bir ag interceptor'u olusturabilirsiniz.

``` bash
metro make:interceptor auth_interceptor
```

Bu, `lib/app/networking/dio/interceptors/` dizininde yeni bir interceptor olusturacaktir.

`--force` veya `-f` bayragi kullanildiginda, mevcut bir interceptor varsa uzerine yazilacaktir.

``` bash
metro make:interceptor auth_interceptor --force
```

<div id="make-env-file"></div>

## Env dosyasi olusturma

Terminalde asagidaki komutu calistirarak yeni bir ortam dosyasi olusturabilirsiniz.

``` bash
metro make:env .env.staging
```

Bu, proje kokunde yeni bir `.env` dosyasi olusturacaktir.

<div id="make-key"></div>

## Anahtar olusturma

Ortam sifreleme icin guvenli bir `APP_KEY` olusturun. Bu, v7'deki sifrelenmis `.env` dosyalari icin kullanilir.

``` bash
metro make:key
```

**Argumenler:**

| Bayrak / Secenek | Kisaltma | Aciklama |
|---------------|-------|-------------|
| `--force` | `-f` | Mevcut APP_KEY'in uzerine yaz |
| `--file` | `-e` | Hedef .env dosyasi (varsayilan: `.env`) |

``` bash
# Anahtar oluştur ve mevcut anahtarın üzerine yaz
metro make:key --force

# Belirli bir env dosyası için anahtar oluştur
metro make:key --file=.env.production
```

<div id="build-app-icons"></div>

## Uygulama Simgeleri Olusturma

Asagidaki komutu calistirarak IOS ve Android icin tum uygulama simgelerini olusturabilirsiniz.

``` bash
dart run flutter_launcher_icons:main
```

Bu, `pubspec.yaml` dosyanizdaki <b>flutter_icons</b> yapilandirmasini kullanir.

<div id="custom-commands"></div>

## Ozel Komutlar

Ozel komutlar, Nylo'nun CLI'sini kendi projenize ozel komutlarla genisletmenize olanak tanir. Bu ozellik, tekrarlayan gorevleri otomatiklestirmenizi, dagitim is akislarini uygulamanizi veya projenizin komut satiri araclariniza dogrudan herhangi bir ozel islevsellik eklemenizi saglar.

- [Ozel komutlar olusturma](#creating-custom-commands)
- [Ozel Komutlari Calistirma](#running-custom-commands)
- [Komutlara secenek ekleme](#adding-options-to-custom-commands)
- [Komutlara bayrak ekleme](#adding-flags-to-custom-commands)
- [Yardimci metotlar](#custom-command-helper-methods)

> **Not:** Su anda ozel komutlarinizda nylo_framework.dart'i ice aktaramazsiniz, bunun yerine ny_cli.dart kullanin.

<div id="creating-custom-commands"></div>

## Ozel Komutlar Olusturma

Yeni bir ozel komut olusturmak icin `make:command` ozelligini kullanabilirsiniz:

```bash
metro make:command current_time
```

Komutunuz icin `--category` secenegini kullanarak bir kategori belirtebilirsiniz:

```bash
# Kategori belirt
metro make:command current_time --category="project"
```

Bu, `lib/app/commands/current_time.dart` yolunda asagidaki yapiyla yeni bir komut dosyasi olusturacaktir:

``` dart
import 'package:nylo_framework/metro/ny_cli.dart';

void main(arguments) => _CurrentTimeCommand(arguments).run();

/// Current Time Command
///
/// Usage:
///   metro app:current_time
class _CurrentTimeCommand extends NyCustomCommand {
  _CurrentTimeCommand(super.arguments);

  @override
  CommandBuilder builder(CommandBuilder command) {
    command.addOption('format', defaultValue: 'HH:mm:ss');
    return command;
  }

  @override
  Future<void> handle(CommandResult result) async {
      final format = result.getString("format");

      // Mevcut zamanı al
      final now = DateTime.now();
      final DateFormat dateFormat = DateFormat(format);

      // Mevcut zamanı biçimlendir
      final formattedTime = dateFormat.format(now);
      info("The current time is " + formattedTime);
  }
}
```

Komut, tum kayitli komutlarin listesini iceren `lib/app/commands/commands.json` dosyasina otomatik olarak kaydedilecektir:

```json
[
  {
    "name": "install_firebase",
    "category": "project",
    "script": "install_firebase.dart"
  },
  {
    "name": "current_time",
    "category": "app",
    "script": "current_time.dart"
  }
]
```

<div id="running-custom-commands"></div>

## Ozel Komutlari Calistirma

Olusturulduktan sonra, ozel komutunuzu Metro kisayolunu veya tam Dart komutunu kullanarak calistirabilirsiniz:

```bash
metro app:current_time
```

`metro`'yu arguman olmadan calistirdiginizda, ozel komutlarinizi "Custom Commands" bolumu altinda menude listelendigini goreceksiniz:

```
[Custom Commands]
  app:app_icon
  app:clear_pub
  project:install_firebase
  project:deploy
```

Komutunuz icin yardim bilgilerini goruntulemek icin `--help` veya `-h` bayragini kullanin:

```bash
metro project:install_firebase --help
```

<div id="adding-options-to-custom-commands"></div>

## Komutlara Secenek Ekleme

Secenekler, komutunuzun kullanicilardan ek girdi almasini saglar. `builder` metodunda komutunuza secenek ekleyebilirsiniz:

```dart
@override
CommandBuilder builder(CommandBuilder command) {

  // Varsayilan degerli bir secenek ekle
  command.addOption(
    'environment',     // seçenek adı
    abbr: 'e',         // kısa form kısaltması
    help: 'Target deployment environment', // yardım metni
    defaultValue: 'development',  // varsayılan değer
    allowed: ['development', 'staging', 'production'] // izin verilen değerler
  );

  return command;
}
```

Ardindan komutunuzun `handle` metodunda secenek degerine erisin:

```dart
@override
Future<void> handle(CommandResult result) async {
  final environment = result.getString('environment');
  info('Deploying to $environment environment...');

  // Komut uygulaması...
}
```

Ornek kullanim:

```bash
metro project:deploy --environment=production
# or using abbreviation
metro project:deploy -e production
```

<div id="adding-flags-to-custom-commands"></div>

## Komutlara Bayrak Ekleme

Bayraklar, acilip kapanabilen boole secenekleridir. `addFlag` metodunu kullanarak komutunuza bayrak ekleyin:

```dart
@override
CommandBuilder builder(CommandBuilder command) {

  command.addFlag(
    'verbose',       // bayrak adı
    abbr: 'v',       // kısa form kısaltması
    help: 'Enable verbose output', // yardım metni
    defaultValue: false  // varsayılan olarak kapalı
  );

  return command;
}
```

Ardindan komutunuzun `handle` metodunda bayrak durumunu kontrol edin:

```dart
@override
Future<void> handle(CommandResult result) async {
  final verbose = result.getBool('verbose');

  if (verbose) {
    info('Verbose mode enabled');
    // Ek günlük kaydı...
  }

  // Komut uygulaması...
}
```

Örnek kullanım:

```bash
metro project:deploy --verbose
# or using abbreviation
metro project:deploy -v
```

<div id="custom-command-helper-methods"></div>

## Yardimci Metotlar

`NyCustomCommand` temel sinifi, yaygin gorevlere yardimci olmak icin cesitli yardimci metotlar saglar:

#### Mesaj Yazdirma

Farkli renklerde mesaj yazdirmak icin bazi metotlar:

| |  |
|-------------|-------------|
| [`info`](#custom-command-helper-formatting)      | Mavi metin ile bilgi mesaji yazdir |
| [`error`](#custom-command-helper-formatting)     | Kirmizi metin ile hata mesaji yazdir |
| [`success`](#custom-command-helper-formatting)   | Yesil metin ile basari mesaji yazdir |
| [`warning`](#custom-command-helper-formatting)   | Sari metin ile uyari mesaji yazdir |

#### Islem Calistirma

Islemleri calistirin ve ciktilarini konsolda goruntulen:

| |  |
|-------------|-------------|
| [`addPackage`](#custom-command-helper-add-package) | `pubspec.yaml`'a paket ekle |
| [`addPackages`](#custom-command-helper-add-packages) | `pubspec.yaml`'a birden fazla paket ekle |
| [`runProcess`](#custom-command-helper-run-process) | Harici bir islem calistir ve ciktiyi konsolda goruntule |
| [`prompt`](#custom-command-helper-prompt)    | Kullanici girdisini metin olarak topla |
| [`confirm`](#custom-command-helper-confirm)   | Evet/hayir sorusu sor ve boole sonuc dondur |
| [`select`](#custom-command-helper-select)    | Secenekler listesi sun ve kullanicinin birini secmesine izin ver |
| [`multiSelect`](#custom-command-helper-multi-select) | Kullanicinin listeden birden fazla secenek secmesine izin ver |

#### Ag Istekleri

Konsol uzerinden ag istekleri yapma:

| |  |
|-------------|-------------|
| [`api`](#custom-command-helper-multi-select) | Nylo API istemcisini kullanarak API cagrisi yap |


#### Yukleme Spinner'i

Bir fonksiyon calistirilirken yukleme spinner'i goruntuler:

| |  |
|-------------|-------------|
| [`withSpinner`](#using-with-spinner) | Bir fonksiyon calistirilirken yukleme spinner'i goster |
| [`createSpinner`](#manual-spinner-control) | Manuel kontrol icin spinner ornegi olustur |

#### Ozel Komut Yardimlari

Komut argumanlarini yonetmek icin asagidaki yardimci metotlari da kullanabilirsiniz:

| |  |
|-------------|-------------|
| [`getString`](#custom-command-helper-get-string) | Komut argumanlarindan string deger al |
| [`getBool`](#custom-command-helper-get-bool)   | Komut argumanlarindan boole deger al |
| [`getInt`](#custom-command-helper-get-int)    | Komut argumanlarindan tamsayi deger al |
| [`sleep`](#custom-command-helper-sleep) | Belirtilen sure boyunca calismayi duraklat |


### Harici Islemleri Calistirma

```dart
// Çıktısı konsolda görüntülenen bir işlem çalıştır
await runProcess('flutter build web --release');

// İşlemi sessizce çalıştır
await runProcess('flutter pub get', silent: true);

// Belirli bir dizinde işlem çalıştır
await runProcess('git pull', workingDirectory: './my-project');
```

### Paket Yonetimi

<div id="custom-command-helper-add-package"></div>
<div id="custom-command-helper-add-packages"></div>

```dart
// pubspec.yaml'a paket ekle
addPackage('firebase_core', version: '^2.4.0');

// pubspec.yaml'a geliştirici paketi ekle
addPackage('build_runner', dev: true);

// Birden fazla paketi aynı anda ekle
addPackages(['firebase_auth', 'firebase_storage', 'quickalert']);
```

<div id="custom-command-helper-formatting"></div>

### Cikti Bicimlendirme

```dart
// Renk kodlamayla durum mesajları yazdır
info('Processing files...');    // Mavi metin
error('Operation failed');      // Kırmızı metin
success('Deployment complete'); // Yeşil metin
warning('Outdated package');    // Sarı metin
```

<div id="interactive-input-methods"></div>

## Etkilesimli Giris Metotlari

`NyCustomCommand` temel sinifi, terminalde kullanici girdisi toplamak icin cesitli metotlar saglar. Bu metotlar, ozel komutlariniz icin etkilesimli komut satiri arayuzleri olusturmayi kolaylastirir.

<div id="custom-command-helper-prompt"></div>

### Metin Girdisi

```dart
String prompt(String question, {String defaultValue = ''})
```

Kullaniciya bir soru goruntuleyen ve metin yanitini toplayan metot.

**Parametreler:**
- `question`: Goruntulenmesi gereken soru veya istem
- `defaultValue`: Kullanici sadece Enter'a bastiginda opsiyonel varsayilan deger

**Dondurur:** Kullanicinin girdisini string olarak veya girdi saglanmadiysa varsayilan degeri

**Ornek:**
```dart
final name = prompt('What is your project name?', defaultValue: 'my_app');
final description = prompt('Enter a project description:');
```

<div id="custom-command-helper-confirm"></div>

### Onay

```dart
bool confirm(String question, {bool defaultValue = false})
```

Kullaniciya evet/hayir sorusu sorar ve boole sonuc dondurur.

**Parametreler:**
- `question`: Sorulacak evet/hayir sorusu
- `defaultValue`: Varsayilan cevap (evet icin true, hayir icin false)

**Dondurur:** Kullanici evet yanit verdiyse `true`, hayir yanit verdiyse `false`

**Ornek:**
```dart
if (confirm('Would you like to continue?', defaultValue: true)) {
  // Kullanici onayladi veya Enter'a basti (varsayilani kabul etti)
  await runProcess('flutter pub get');
} else {
  // Kullanici reddetti
  info('Operation canceled');
}
```

<div id="custom-command-helper-select"></div>

### Tekli Secim

```dart
String select(String question, List<String> options, {String? defaultOption})
```

Secenekler listesi sunar ve kullanicinin birini secmesine izin verir.

**Parametreler:**
- `question`: Secim istemi
- `options`: Kullanilabilir secenekler listesi
- `defaultOption`: Opsiyonel varsayilan secim

**Dondurur:** Secilen secenegi string olarak

**Ornek:**
```dart
final environment = select(
  'Select deployment environment:',
  ['development', 'staging', 'production'],
  defaultOption: 'development'
);

info('Deploying to $environment environment...');
```

<div id="custom-command-helper-multi-select"></div>

### Coklu Secim

```dart
List<String> multiSelect(String question, List<String> options)
```

Kullanicinin listeden birden fazla secenek secmesine izin verir.

**Parametreler:**
- `question`: Secim istemi
- `options`: Kullanilabilir secenekler listesi

**Dondurur:** Secilen seceneklerin listesi

**Ornek:**
```dart
final packages = multiSelect(
  'Select packages to install:',
  ['firebase_auth', 'dio', 'provider', 'shared_preferences', 'path_provider']
);

if (packages.isNotEmpty) {
  info('Installing ${packages.length} packages...');
  addPackages(packages);
  await runProcess('flutter pub get');
}
```

<div id="custom-command-helper-api"></div>

## API Yardimci Metodu

`api` yardimci metodu, ozel komutlarinizdan ag istekleri yapmayi kolaylastirir.

```dart
Future<T?> api<T>(Future<T?> Function(ApiService) request) async
```

## Temel Kullanim Ornekleri

### GET Istegi

```dart
// Veri getir
final userData = await api((request) =>
  request.get('https://api.example.com/users/1')
);
```

### POST Istegi

```dart
// Kaynak olustur
final result = await api((request) =>
  request.post(
    'https://api.example.com/items',
    data: {'name': 'New Item', 'price': 19.99}
  )
);
```

### PUT Istegi

```dart
// Kaynagi guncelle
final updateResult = await api((request) =>
  request.put(
    'https://api.example.com/items/42',
    data: {'name': 'Updated Item', 'price': 29.99}
  )
);
```

### DELETE Istegi

```dart
// Kaynagi sil
final deleteResult = await api((request) => request.delete('https://api.example.com/items/42'));
```

### PATCH Istegi

```dart
// Kaynagi kismen guncelle
final patchResult = await api((request) => request.patch(
    'https://api.example.com/items/42',
    data: {'price': 24.99}
  )
);
```

### Sorgu Parametreleri ile

```dart
// Sorgu parametreleri ekle
final searchResults = await api((request) => request.get(
    'https://api.example.com/search',
    queryParameters: {'q': 'keyword', 'limit': 10}
  )
);
```

### Spinner ile

```dart
// Daha iyi UI icin spinner ile kullan
final data = await withSpinner(
  task: () async {
    final data = await api((request) => request.get('https://api.example.com/config'));
    // Veriyi isle
  },
  message: 'Loading configuration',
);
```


<div id="using-spinners"></div>

## Spinner Islevi

Spinner'lar, ozel komutlarinizdaki uzun sureli islemler sirasinda gorsel geri bildirim saglar. Komutunuz asenkron gorevleri yuruturken bir mesajla birlikte animasyonlu bir gosterge goruntuleyerek ilerleme ve durum gostererek kullanici deneyimini iyilestirir.

- [Spinner ile kullanim](#using-with-spinner)
- [Manuel spinner kontrolu](#manual-spinner-control)
- [Ornekler](#spinner-examples)

<div id="using-with-spinner"></div>

## Spinner ile kullanim

`withSpinner` metodu, gorev basladiginda otomatik olarak baslayan ve tamamlandiginda veya basarisiz oldugunda duran bir spinner animasyonu ile asenkron bir gorevi sarmalamaniza olanak tanir:

```dart
Future<T> withSpinner<T>({
  required Future<T> Function() task,
  required String message,
  String? successMessage,
  String? errorMessage,
}) async
```

**Parametreler:**
- `task`: Calistirilacak asenkron fonksiyon
- `message`: Spinner calisirken goruntulenmesi gereken metin
- `successMessage`: Basarili tamamlama durumunda goruntulenmesi gereken opsiyonel mesaj
- `errorMessage`: Gorev basarisiz oldugunda goruntulenmesi gereken opsiyonel mesaj

**Dondurur:** Gorev fonksiyonunun sonucu

**Ornek:**
```dart
@override
Future<void> handle(CommandResult result) async {
  // Spinner ile bir gorev calistir
  final projectFiles = await withSpinner(
    task: () async {
      // Uzun sureli gorev (orn. proje dosyalarini analiz et)
      await sleep(2);
      return ['pubspec.yaml', 'lib/main.dart', 'README.md'];
    },
    message: 'Analyzing project structure',
    successMessage: 'Project analysis complete',
    errorMessage: 'Failed to analyze project',
  );

  // Sonuclarla devam et
  info('Found ${projectFiles.length} key files');
}
```

<div id="manual-spinner-control"></div>

## Manuel Spinner Kontrolu

Spinner durumunu manuel olarak kontrol etmeniz gereken daha karmasik senaryolar icin bir spinner ornegi olusturabilirsiniz:

```dart
ConsoleSpinner createSpinner(String message)
```

**Parametreler:**
- `message`: Spinner calisirken goruntulenmesi gereken metin

**Dondurur:** Manuel olarak kontrol edebileceginiz bir `ConsoleSpinner` ornegi

**Manuel kontrollu ornek:**
```dart
@override
Future<void> handle(CommandResult result) async {
  // Bir spinner ornegi olustur
  final spinner = createSpinner('Deploying to production');
  spinner.start();

  try {
    // Birinci gorev
    await runProcess('flutter clean', silent: true);
    spinner.update('Building release version');

    // Ikinci gorev
    await runProcess('flutter build web --release', silent: true);
    spinner.update('Uploading to server');

    // Ucuncu gorev
    await runProcess('./deploy.sh', silent: true);

    // Basariyla tamamla
    spinner.stop(completionMessage: 'Deployment completed successfully', success: true);
  } catch (e) {
    // Hatayı isle
    spinner.stop(completionMessage: 'Deployment failed: $e', success: false);
    rethrow;
  }
}
```

<div id="spinner-examples"></div>

## Ornekler

### Spinner ile Basit Gorev

```dart
@override
Future<void> handle(CommandResult result) async {
  await withSpinner(
    task: () async {
      // Bagimlilikları yukle
      await runProcess('flutter pub get', silent: true);
      return true;
    },
    message: 'Installing dependencies',
    successMessage: 'Dependencies installed successfully',
  );
}
```

### Birden Fazla Ardisik Islem

```dart
@override
Future<void> handle(CommandResult result) async {
  // Spinner ile birinci islem
  await withSpinner(
    task: () => runProcess('flutter clean', silent: true),
    message: 'Cleaning project',
  );

  // Spinner ile ikinci islem
  await withSpinner(
    task: () => runProcess('flutter pub get', silent: true),
    message: 'Updating dependencies',
  );

  // Spinner ile ucuncu islem
  final buildSuccess = await withSpinner(
    task: () async {
      await runProcess('flutter build apk --release', silent: true);
      return true;
    },
    message: 'Building release APK',
    successMessage: 'Release APK built successfully',
  );

  if (buildSuccess) {
    success('Build process completed');
  }
}
```

### Manuel Kontrollu Karmasik Is Akisi

```dart
@override
Future<void> handle(CommandResult result) async {
  final spinner = createSpinner('Starting deployment process');
  spinner.start();

  try {
    // Durum guncellemeleriyle birden fazla adim calistir
    spinner.update('Step 1: Cleaning project');
    await runProcess('flutter clean', silent: true);

    spinner.update('Step 2: Fetching dependencies');
    await runProcess('flutter pub get', silent: true);

    spinner.update('Step 3: Building release');
    await runProcess('flutter build web --release', silent: true);

    // Islemi tamamla
    spinner.stop(completionMessage: 'Deployment completed successfully', success: true);

  } catch (e) {
    spinner.stop(completionMessage: 'Deployment failed: $e', success: false);
  }
}
```

Ozel komutlarinizda spinner kullanimi, uzun sureli islemler sirasinda kullanicilara net gorsel geri bildirim saglayarak daha cilali ve profesyonel bir komut satiri deneyimi olusturur.

<div id="custom-command-helper-get-string"></div>

### Seceneklerden string deger alma

```dart
String getString(String name, {String defaultValue = ''})
```

**Parametreler:**

- `name`: Alinacak secenegin adi
- `defaultValue`: Secenek saglanmadiysa opsiyonel varsayilan deger

**Dondurur:** Secenegin degerini string olarak

**Ornek:**
```dart
@override
CommandBuilder builder(CommandBuilder command) {
  command.addOption("name", defaultValue: "Anthony");
  return command;
}

Future<void> handle(CommandResult result) async {
  final name = result.getString('name');
  info('Hello, $name!');
}
```

<div id="custom-command-helper-get-bool"></div>

### Seceneklerden boole deger alma

```dart
bool getBool(String name, {bool defaultValue = false})
```

**Parametreler:**
- `name`: Alinacak secenegin adi
- `defaultValue`: Secenek saglanmadiysa opsiyonel varsayilan deger

**Dondurur:** Secenegin degerini boole olarak


**Ornek:**
```dart
@override
CommandBuilder builder(CommandBuilder command) {
  command.addFlag("verbose", defaultValue: false);
  return command;
}

Future<void> handle(CommandResult result) async {
  final verbose = result.getBool('verbose');
  if (verbose) {
    info('Verbose mode enabled');
  } else {
    info('Verbose mode disabled');
  }
}
```

<div id="custom-command-helper-get-int"></div>

### Seceneklerden tamsayi deger alma

```dart
int getInt(String name, {int defaultValue = 0})
```

**Parametreler:**
- `name`: Alinacak secenegin adi
- `defaultValue`: Secenek saglanmadiysa opsiyonel varsayilan deger

**Dondurur:** Secenegin degerini tamsayi olarak

**Ornek:**
```dart
@override
CommandBuilder builder(CommandBuilder command) {
  command.addOption("count", defaultValue: 5);
  return command;
}

Future<void> handle(CommandResult result) async {
  final count = result.getInt('count');
  info('Count is set to $count');
}
```

<div id="custom-command-helper-sleep"></div>

### Belirtilen sure boyunca bekleme

```dart
void sleep(int seconds)
```

**Parametreler:**
- `seconds`: Beklenecek saniye sayisi

**Dondurur:** Yok

**Ornek:**
```dart
@override
Future<void> handle(CommandResult result) async {
  info('Sleeping for 5 seconds...');
  await sleep(5);
  info('Awake now!');
}
```

<div id="output-formatting"></div>

## Cikti Bicimlendirme

Temel `info`, `error`, `success` ve `warning` metotlarinin otesinde, `NyCustomCommand` ek cikti yardimlari saglar:

```dart
@override
Future<void> handle(CommandResult result) async {
  // Düz metin yazdır (renk yok)
  line('Processing your request...');

  // Boş satırlar yazdır
  newLine();       // bir boş satır
  newLine(3);      // üç boş satır

  // Soluk yorum yazdır (gri metin)
  comment('This is a background note');

  // Belirgin bir uyarı kutusu yazdır
  alert('Important: Please read carefully');

  // Ask, prompt için takma addır
  final name = ask('What is your name?');

  // Hassas veriler için gizli girdi (örn. şifreler, API anahtarları)
  final apiKey = promptSecret('Enter your API key:');

  // Komutu hata mesajı ve çıkış koduyla iptal et
  if (name.isEmpty) {
    abort('Name is required');  // kod 1 ile çıkar
  }
}
```

| Metot | Aciklama |
|--------|-------------|
| `line(String message)` | Renksiz duz metin yazdir |
| `newLine([int count = 1])` | Bos satirlar yazdir |
| `comment(String message)` | Soluk/gri metin yazdir |
| `alert(String message)` | Belirgin bir uyari kutusu yazdir |
| `ask(String question, {String defaultValue})` | `prompt` icin takma ad |
| `promptSecret(String question)` | Hassas veriler icin gizli girdi |
| `abort([String? message, int exitCode = 1])` | Komutu hata ile sonlandir |

<div id="file-system-helpers"></div>

## Dosya Sistemi Yardimlari

`NyCustomCommand`, yaygin islemler icin `dart:io`'yu manuel olarak ice aktarmaniz gerekmemesi icin yerlesik dosya sistemi yardimlari icerir.

### Dosya Okuma ve Yazma

```dart
@override
Future<void> handle(CommandResult result) async {
  // Dosyanın var olup olmadığını kontrol et
  if (fileExists('lib/config/app.dart')) {
    info('Config file found');
  }

  // Dizinin var olup olmadığını kontrol et
  if (directoryExists('lib/app/models')) {
    info('Models directory found');
  }

  // Dosyayı oku (asenkron)
  String content = await readFile('pubspec.yaml');

  // Dosyayı oku (senkron)
  String contentSync = readFileSync('pubspec.yaml');

  // Dosyaya yaz (asenkron)
  await writeFile('lib/generated/output.dart', 'class Output {}');

  // Dosyaya yaz (senkron)
  writeFileSync('lib/generated/output.dart', 'class Output {}');

  // Dosyaya içerik ekle
  await appendFile('log.txt', 'New log entry\n');

  // Dizinin var olduğundan emin ol (yoksa oluştur)
  await ensureDirectory('lib/generated');

  // Dosyayı sil
  await deleteFile('lib/generated/output.dart');

  // Dosyayı kopyala
  await copyFile('lib/config/app.dart', 'lib/config/app.bak.dart');
}
```

| Metot | Aciklama |
|--------|-------------|
| `fileExists(String path)` | Dosya mevcutsa `true` dondurur |
| `directoryExists(String path)` | Dizin mevcutsa `true` dondurur |
| `readFile(String path)` | Dosyayi string olarak okur (asenkron) |
| `readFileSync(String path)` | Dosyayi string olarak okur (senkron) |
| `writeFile(String path, String content)` | Dosyaya icerik yazar (asenkron) |
| `writeFileSync(String path, String content)` | Dosyaya icerik yazar (senkron) |
| `appendFile(String path, String content)` | Dosyaya icerik ekler |
| `ensureDirectory(String path)` | Yoksa dizin olusturur |
| `deleteFile(String path)` | Dosya siler |
| `copyFile(String source, String destination)` | Dosya kopyalar |

<div id="json-yaml-helpers"></div>

## JSON ve YAML Yardimlari

Yerlesik yardimlarla JSON ve YAML dosyalarini okuyun ve yazin.

```dart
@override
Future<void> handle(CommandResult result) async {
  // JSON dosyasını Map olarak oku
  Map<String, dynamic> config = await readJson('config.json');

  // JSON dosyasını List olarak oku
  List<dynamic> items = await readJsonArray('lib/app/commands/commands.json');

  // Veriyi JSON dosyasına yaz (varsayılan olarak güzel biçimlendirilmiş)
  await writeJson('output.json', {'name': 'MyApp', 'version': '1.0.0'});

  // Sıkıştırılmış JSON yaz
  await writeJson('output.json', data, pretty: false);

  // JSON dizi dosyasına öğe ekle
  // Dosya [{"name": "a"}] içeriyorsa bu, o diziye ekler
  await appendToJsonArray(
    'lib/app/commands/commands.json',
    {'name': 'my_command', 'category': 'app', 'script': 'my_command.dart'},
    uniqueKey: 'name',  // bu anahtara göre tekrarlananları önler
  );

  // YAML dosyasını Map olarak oku
  Map<String, dynamic> pubspec = await readYaml('pubspec.yaml');
  info('Project: ${pubspec['name']}');
}
```

| Metot | Aciklama |
|--------|-------------|
| `readJson(String path)` | JSON dosyasini `Map<String, dynamic>` olarak okur |
| `readJsonArray(String path)` | JSON dosyasini `List<dynamic>` olarak okur |
| `writeJson(String path, dynamic data, {bool pretty = true})` | Veriyi JSON olarak yazar |
| `appendToJsonArray(String path, Map item, {String? uniqueKey})` | JSON dizi dosyasina ekler |
| `readYaml(String path)` | YAML dosyasini `Map<String, dynamic>` olarak okur |

<div id="case-conversion-helpers"></div>

## Buyuk-Kucuk Harf Donusturme Yardimlari

`recase` paketini ice aktarmadan stringleri adlandirma kurallari arasinda donusturun.

```dart
@override
Future<void> handle(CommandResult result) async {
  String input = 'user profile page';

  info(snakeCase(input));    // user_profile_page
  info(camelCase(input));    // userProfilePage
  info(pascalCase(input));   // UserProfilePage
  info(titleCase(input));    // User Profile Page
  info(kebabCase(input));    // user-profile-page
  info(constantCase(input)); // USER_PROFILE_PAGE
}
```

| Metot | Cikti Formati | Ornek |
|--------|--------------|---------|
| `snakeCase(String input)` | `snake_case` | `user_profile` |
| `camelCase(String input)` | `camelCase` | `userProfile` |
| `pascalCase(String input)` | `PascalCase` | `UserProfile` |
| `titleCase(String input)` | `Title Case` | `User Profile` |
| `kebabCase(String input)` | `kebab-case` | `user-profile` |
| `constantCase(String input)` | `CONSTANT_CASE` | `USER_PROFILE` |

<div id="project-path-helpers"></div>

## Proje Yol Yardimlari

Standart Nylo proje dizinleri icin getter'lar. Bunlar proje kokunue gore goreceli yollar dondurur.

```dart
@override
Future<void> handle(CommandResult result) async {
  info(modelsPath);       // lib/app/models
  info(controllersPath);  // lib/app/controllers
  info(widgetsPath);      // lib/resources/widgets
  info(pagesPath);        // lib/resources/pages
  info(commandsPath);     // lib/app/commands
  info(configPath);       // lib/config
  info(providersPath);    // lib/app/providers
  info(eventsPath);       // lib/app/events
  info(networkingPath);   // lib/app/networking
  info(themesPath);       // lib/resources/themes

  // Proje köküne göre özel bir yol oluştur
  String customPath = projectPath('lib/app/services/auth_service.dart');
}
```

| Ozellik | Yol |
|----------|------|
| `modelsPath` | `lib/app/models` |
| `controllersPath` | `lib/app/controllers` |
| `widgetsPath` | `lib/resources/widgets` |
| `pagesPath` | `lib/resources/pages` |
| `commandsPath` | `lib/app/commands` |
| `configPath` | `lib/config` |
| `providersPath` | `lib/app/providers` |
| `eventsPath` | `lib/app/events` |
| `networkingPath` | `lib/app/networking` |
| `themesPath` | `lib/resources/themes` |
| `projectPath(String relativePath)` | Proje icinde goreceli bir yolu cozumler |

<div id="platform-helpers"></div>

## Platform Yardimlari

Platformu kontrol edin ve ortam degiskenlerine erisin.

```dart
@override
Future<void> handle(CommandResult result) async {
  // Platform kontrolleri
  if (isWindows) {
    info('Running on Windows');
  } else if (isMacOS) {
    info('Running on macOS');
  } else if (isLinux) {
    info('Running on Linux');
  }

  // Mevcut çalışma dizini
  info('Working in: $workingDirectory');

  // Sistem ortam değişkenlerini oku
  String home = env('HOME', '/default/path');
}
```

| Ozellik / Metot | Aciklama |
|-------------------|-------------|
| `isWindows` | Windows uzerinde calisiyorsa `true` |
| `isMacOS` | macOS uzerinde calisiyorsa `true` |
| `isLinux` | Linux uzerinde calisiyorsa `true` |
| `workingDirectory` | Mevcut calisma dizini yolu |
| `env(String key, [String defaultValue = ''])` | Sistem ortam degiskenini okur |

<div id="dart-flutter-commands"></div>

## Dart ve Flutter Komutlari

Yaygin Dart ve Flutter CLI komutlarini yardimci metotlar olarak calistirin. Her biri islem cikis kodunu dondurur.

```dart
@override
Future<void> handle(CommandResult result) async {
  // Bir Dart dosyasını veya dizini biçimlendir
  await dartFormat('lib/app/models/user.dart');

  // dart analyze çalıştır
  int analyzeResult = await dartAnalyze('lib/');

  // flutter pub get çalıştır
  await flutterPubGet();

  // flutter clean çalıştır
  await flutterClean();

  // Ek argümanlarla bir hedef için derle
  await flutterBuild('apk', args: ['--release', '--split-per-abi']);
  await flutterBuild('web', args: ['--release']);

  // flutter test çalıştır
  await flutterTest();
  await flutterTest('test/unit/');  // belirli dizin
}
```

| Metot | Aciklama |
|--------|-------------|
| `dartFormat(String path)` | Dosya veya dizinde `dart format` calistirir |
| `dartAnalyze([String? path])` | `dart analyze` calistirir |
| `flutterPubGet()` | `flutter pub get` calistirir |
| `flutterClean()` | `flutter clean` calistirir |
| `flutterBuild(String target, {List<String> args})` | `flutter build <target>` calistirir |
| `flutterTest([String? path])` | `flutter test` calistirir |

<div id="dart-file-manipulation"></div>

## Dart Dosya Manipulasyonu

Iskele araclari olustururken kullanisli olan Dart dosyalarini programatik olarak duzenleme yardimlari.

```dart
@override
Future<void> handle(CommandResult result) async {
  // Dart dosyasına import ifadesi ekle (tekrarları önler)
  await addImport(
    'lib/bootstrap/providers.dart',
    "import '/app/providers/firebase_provider.dart';",
  );

  // Dosyadaki son kapanış parantezinden önce kod ekle
  // Kayıt haritalarına giriş eklemek için kullanışlı
  await insertBeforeClosingBrace(
    'lib/bootstrap/providers.dart',
    '  FirebaseProvider(),',
  );

  // Dosyanın belirli bir string içerip içermediğini kontrol et
  bool hasImport = await fileContains(
    'lib/bootstrap/providers.dart',
    'firebase_provider',
  );

  // Dosyanın bir regex kalıbıyla eşleşip eşleşmediğini kontrol et
  bool hasClass = await fileContainsPattern(
    'lib/app/models/user.dart',
    RegExp(r'class User'),
  );
}
```

| Metot | Aciklama |
|--------|-------------|
| `addImport(String filePath, String importStatement)` | Dart dosyasina import ekler (zaten mevcutsa atlar) |
| `insertBeforeClosingBrace(String filePath, String code)` | Dosyadaki son `}` oncesine kod ekler |
| `fileContains(String filePath, String identifier)` | Dosyanin bir string icerip icermedigini kontrol eder |
| `fileContainsPattern(String filePath, Pattern pattern)` | Dosyanin bir kalipla eslesip eslesmedigini kontrol eder |

<div id="directory-helpers"></div>

## Dizin Yardimlari

Dizinlerle calisma ve dosya bulma yardimlari.

```dart
@override
Future<void> handle(CommandResult result) async {
  // Dizin iceriklerini listele
  var entities = listDirectory('lib/app/models');
  for (var entity in entities) {
    info(entity.path);
  }

  // Tekrarli olarak listele
  var allEntities = listDirectory('lib/', recursive: true);

  // Kriterlere uyan dosyalari bul
  List<File> dartFiles = findFiles(
    'lib/app/models',
    extension: '.dart',
    recursive: true,
  );

  // Dosyalari ad kalibina gore bul
  List<File> testFiles = findFiles(
    'test/',
    namePattern: RegExp(r'_test\.dart$'),
  );

  // Dizini tekrarli olarak sil
  await deleteDirectory('build/');

  // Dizini kopyala (tekrarli)
  await copyDirectory('lib/templates', 'lib/generated');
}
```

| Metot | Aciklama |
|--------|-------------|
| `listDirectory(String path, {bool recursive = false})` | Dizin iceriklerini listeler |
| `findFiles(String directory, {String? extension, Pattern? namePattern, bool recursive = true})` | Kriterlere uyan dosyalari bulur |
| `deleteDirectory(String path)` | Dizini tekrarli olarak siler |
| `copyDirectory(String source, String destination)` | Dizini tekrarli olarak kopyalar |

<div id="validation-helpers"></div>

## Dogrulama Yardimlari

Kod uretimi icin kullanici girdisini dogrulama ve temizleme yardimlari.

```dart
@override
Future<void> handle(CommandResult result) async {
  // Dart tanimlayicisini dogrula
  if (!isValidDartIdentifier('MyClass')) {
    error('Invalid Dart identifier');
  }

  // Bos olmayan ilk argumani zorunlu kil
  String name = requireArgument(result, message: 'Please provide a name');

  // Sinif adini temizle (PascalCase, sonekleri kaldir)
  String className = cleanClassName('user_model', removeSuffixes: ['_model']);
  // Dondurur: 'User'

  // Dosya adini temizle (uzantili snake_case)
  String fileName = cleanFileName('UserModel', extension: '.dart');
  // Dondurur: 'user_model.dart'
}
```

| Metot | Aciklama |
|--------|-------------|
| `isValidDartIdentifier(String name)` | Dart tanimlayici adini dogrular |
| `requireArgument(CommandResult result, {String? message})` | Bos olmayan ilk argumani gerektirir veya iptal eder |
| `cleanClassName(String name, {List<String> removeSuffixes})` | Sinif adini temizler ve PascalCase'e donusturur |
| `cleanFileName(String name, {String extension = '.dart'})` | Dosya adini temizler ve snake_case'e donusturur |

<div id="file-scaffolding"></div>

## Dosya Iskele Sistemi

Iskele sistemini kullanarak icerikli bir veya birden fazla dosya olusturun.

### Tekli Dosya

```dart
@override
Future<void> handle(CommandResult result) async {
  await scaffold(
    path: 'lib/app/services/auth_service.dart',
    content: '''
class AuthService {
  Future<bool> login(String email, String password) async {
    // TODO: giris islemini uygula
    return false;
  }
}
''',
    force: false,  // mevcutsa uzerine yazma
    successMessage: 'AuthService created',
  );
}
```

### Birden Fazla Dosya

```dart
@override
Future<void> handle(CommandResult result) async {
  await scaffoldMany([
    ScaffoldFile(
      path: 'lib/app/models/product.dart',
      content: 'class Product {}',
      successMessage: 'Product model created',
    ),
    ScaffoldFile(
      path: 'lib/app/networking/product_api_service.dart',
      content: 'class ProductApiService {}',
      successMessage: 'Product API service created',
    ),
  ], force: false);
}
```

`ScaffoldFile` sinifi su degerleri kabul eder:

| Ozellik | Tip | Aciklama |
|----------|------|-------------|
| `path` | `String` | Olusturulacak dosya yolu |
| `content` | `String` | Dosya icerigi |
| `successMessage` | `String?` | Basari durumunda gosterilen mesaj |

<div id="task-runner"></div>

## Gorev Calistiricisi

Otomatik durum ciktisi ile adlandirilmis bir dizi gorev calistirin.

### Temel Gorev Calistiricisi

```dart
@override
Future<void> handle(CommandResult result) async {
  await runTasks([
    CommandTask(
      'Clean project',
      () => runProcess('flutter clean', silent: true),
    ),
    CommandTask(
      'Fetch dependencies',
      () => runProcess('flutter pub get', silent: true),
    ),
    CommandTask(
      'Run tests',
      () => runProcess('flutter test', silent: true),
      stopOnError: true,  // bu basarisiz olursa hatti durdur (varsayilan)
    ),
  ]);
}
```

### Spinner'li Gorev Calistiricisi

```dart
@override
Future<void> handle(CommandResult result) async {
  await runTasksWithSpinner([
    CommandTask(
      name: 'Preparing release',
      action: () async {
        await flutterClean();
        await flutterPubGet();
      },
    ),
    CommandTask(
      name: 'Building APK',
      action: () => flutterBuild('apk', args: ['--release']),
    ),
  ]);
}
```

`CommandTask` sinifi su degerleri kabul eder:

| Ozellik | Tip | Varsayilan | Aciklama |
|----------|------|---------|-------------|
| `name` | `String` | zorunlu | Ciktida gosterilen gorev adi |
| `action` | `Future<void> Function()` | zorunlu | Calistirilacak asenkron fonksiyon |
| `stopOnError` | `bool` | `true` | Bu basarisiz olursa kalan gorevlerin durdurulup durdurulmayacagi |

<div id="table-output"></div>

## Tablo Ciktisi

Konsolda bicimlendirilmis ASCII tabloları goruntuleyin.

```dart
@override
Future<void> handle(CommandResult result) async {
  table(
    ['Name', 'Version', 'Status'],
    [
      ['nylo_framework', '7.0.0', 'installed'],
      ['nylo_support', '7.0.0', 'installed'],
      ['dio', '5.4.0', 'installed'],
    ],
  );
}
```

Cikti:

```
┌─────────────────┬─────────┬───────────┐
│ Name            │ Version │ Status    │
├─────────────────┼─────────┼───────────┤
│ nylo_framework  │ 7.0.0   │ installed │
│ nylo_support    │ 7.0.0   │ installed │
│ dio             │ 5.4.0   │ installed │
└─────────────────┴─────────┴───────────┘
```

<div id="progress-bar"></div>

## Ilerleme Cubugu

Bilinen oge sayisina sahip islemler icin ilerleme cubugu goruntuleyin.

### Manuel Ilerleme Cubugu

```dart
@override
Future<void> handle(CommandResult result) async {
  // 100 oge icin ilerleme cubugu olustur
  final progress = progressBar(100, message: 'Processing files');
  progress.start();

  for (int i = 0; i < 100; i++) {
    await Future.delayed(Duration(milliseconds: 50));
    progress.tick();  // 1 artir
  }

  progress.complete('All files processed');
}
```

### Ilerleme ile Ogeleri Isleme

```dart
@override
Future<void> handle(CommandResult result) async {
  final files = findFiles('lib/', extension: '.dart');

  // Ogeler otomatik ilerleme takibiyle isle
  final results = await withProgress<File, String>(
    items: files,
    process: (file, index) async {
      // her dosyayi isle
      return file.path;
    },
    message: 'Analyzing Dart files',
    completionMessage: 'Analysis complete',
  );

  info('Processed ${results.length} files');
}
```

### Senkron Ilerleme

```dart
@override
Future<void> handle(CommandResult result) async {
  final items = ['a', 'b', 'c', 'd', 'e'];

  final results = withProgressSync<String, String>(
    items: items,
    process: (item, index) {
      // senkron isleme
      return item.toUpperCase();
    },
    message: 'Converting items',
  );

  info('Results: $results');
}
```

`ConsoleProgressBar` sinifi su metodlari saglar:

| Metot | Aciklama |
|--------|-------------|
| `start()` | Ilerleme cubugunu baslatir |
| `tick([int amount = 1])` | Ilerlemeyi arttirir |
| `update(int value)` | Ilerlemeyi belirli bir degere ayarlar |
| `updateMessage(String newMessage)` | Goruntulunen mesaji degistirir |
| `complete([String? completionMessage])` | Opsiyonel mesajla tamamlar |
| `stop()` | Tamamlamadan durdurur |
| `current` | Mevcut ilerleme degeri (getter) |
| `percentage` | Yuzde olarak ilerleme (getter) |