# Metro Live

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

## Giriş

<!-- uncertain: newly created translation; needs full human review -->

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

<!-- uncertain: "Nylo Live" bu dosyada "Backpack"/"Metro" gibi bir özellik özel adı olarak kabul edilip çevrilmeden bırakıldı; dosyanın devamında "Live" sözcüğü de aynı şekilde ele alındı -->

**Nylo Live**, Metro'nun uygulamanız debug (veya profile) modunda çalışırken Dart VM servisi üzerinden ona erişmesini sağlar. Uygulamayı hiçbir kuruluma gerek kalmadan Dart Tooling Daemon üzerinden bulur ve yalnızca mevcut projeden derlenmiş uygulamalara bağlanır.

Nylo Live, debug ve profile derlemelerinde varsayılan olarak açıktır; bir release derlemesi hiçbir şey kaydetmez. Yalnızca uygulamayı okuyan komutlar (`live:status`, `live:run data`, `live:run routes`, ...) profile derlemelerinde de çalışır. Uygulamayı değiştiren komutlar (`route`, `storage`, `auth`, seeder'lar, ...) bir debug derlemesi gerektirir.

Başka her şey çalışmadan önce, bunu bir provider'dan kendiniz kapatın:

``` dart
class AppProvider implements NyProvider {
  @override
  setup(Nylo nylo) async {
    nylo.useLive(false);
    return nylo;
  }

  @override
  boot(Nylo nylo) async {}
}
```

<div id="metro-live-shell"></div>

## metro live Kabuğu

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

Çalışan uygulamanıza bağlı bir kabuk açın:

``` bash
metro live
```

Nylo Live, projenin çalışan uygulamalarını bulur ve birine bağlanır -- birden fazla çalışıyorsa seçmenizi ister. Bağlandıktan sonra, prompt ekrandaki cihazı ve o an açık olan rotayı gösterir:

``` plaintext
Nylo Live · my_app
Connected to iPhone 15 Pro (debug)
Type help to see commands, and exit to leave.
iPhone 15 Pro /home ›
```

Live komutları kabuğun içinde `metro live:` önekini kaybeder -- `metro live:status` yerine `status`, `metro live:run route /profile` yerine `route /profile`. Birkaç komut yalnızca kabuğun içinde çalışır: `seed`, `seed:rollback`, `export`, `reload` ve `restart`. Tüm komutları listelemek için `help`, bir komutun seçeneklerini görmek için `help <command>` yazın. Çıkmak için `exit` (veya Ctrl+D) yazın.

Bağlıyken uygulama yeniden başlarsa, kabuk kendiliğinden yeniden bağlanır.

<div id="shared-options"></div>

### Ortak Seçenekler

Her live komutu -- kabuğun içinde veya `metro live:*` olarak -- aynı seçenekleri kabul eder:

| Seçenek | Açıklama |
|--------|-------------|
| `-d, --device <#\|name>` | Uygulamayı `metro live:devices` içindeki numarasıyla veya cihaz adıyla hedefleyin |
| `--all` | Bu projenin çalışan her uygulamasında çalıştırın |
| `--json` | Makine tarafından okunabilir JSON yazdırın |
| `--uri` | Uygulamaları bulmak yerine bu VM servis adresini kullanın |
| `--timeout` | Bulma sırasında her uygulama için beklenecek saniye (varsayılan `3`) |

`@path` olarak yazılan bir seçenek değeri o dosyadan okunur -- büyük bir `--data` yükü için kullanışlıdır:

``` bash
metro live:run route /profile --data @user.json
```

Değer gerçekten `@` ile başlıyorsa, `@@` ile başlatın.

<div id="tab-completion-and-history"></div>

### Sekme Tamamlama ve Geçmiş

Kabuğun içinde Tab tuşu, bağlı uygulamaya göre komut adlarını, seçenekleri, rotaları, storage ve Backpack anahtarlarını ve seeder adlarını tamamlar. Geçmiş `.dart_tool/nylo/live_history` içinde tutulur ve oturumlar arasında korunur.

<div id="running-a-script"></div>

### Bir Betik Çalıştırma

Bir dosyayı `metro live`'a yönlendirerek, satır başına bir komut olacak şekilde betik olarak çalıştırın; başarısız olan ilk komutta durur:

``` bash
metro live < seeds/demo.live
```

Boş satırlar ve `#` ile başlayan satırlar atlanır.

<div id="live-devices"></div>

## live:devices

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

Bu projenin çalışan uygulamalarını, `-d` için numaralandırılmış şekilde listeler:

``` bash
metro live:devices
```
``` plaintext
Running apps for my_app:
#  DEVICE          PLATFORM  MODE   ROUTE   APP
1  iPhone 15 Pro   ios       debug  /home   my_app
2  Pixel 8         android   debug  /login  my_app
```

<div id="live-status"></div>

## live:status

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

Uygulamayı, cihazı, derleme modunu, mevcut rotayı ve yığını, dili, temayı ve bir kullanıcının oturum açıp açmadığını gösterir:

``` bash
metro live:status
```
``` plaintext
App            my_app (development)
Device         iPhone 15 Pro · ios 17.4
Mode           debug
Route          /home
Stack          /home
Locale         en
Theme          default
Authenticated  yes
Live commands  cart:seed
Seeders        demo_user
```

<div id="live-run"></div>

## live:run

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

Uygulamayı inceleyen veya yöneten yerleşik bir komut çalıştırır:

``` bash
metro live:run <command> [arguments]
```

| Komut | Açıklama |
|---------|-------------|
| `data` | Ekrandaki sayfanın verilerini ve alanlarını göster |
| `routes` | Kayıtlı rotaları listele |
| `route` | İsteğe bağlı `--data` ile bir sayfa aç |
| `back` | Bir sayfa geri git, veya bir rotaya geri dön |
| `deeplink` | Bir deep link aç, veya nasıl kurulduklarını göster |
| `storage` | Yerel storage'ı listele, veya bir değeri göster, kaydet ya da sil |
| `storage:clear` | İsteğe bağlı `--keep` ile yerel storage'ı temizle |
| `backpack` | Backpack değerlerini listele, veya birini göster, kaydet ya da sil |
| `auth` | Kimin oturum açtığını göster, veya oturum aç ya da kapat |
| `locale` | Uygulamanın dilini değiştir |
| `theme` | Uygulamanın temasını değiştir |
| `state` | `updateState` ile bir duruma veri gönder |
| `event` | Kendi event'lerinizden birini tetikle |
| `toast` | Bir toast bildirimi göster |

`metro live` içinde, `live:run` kısmını atlayın -- `metro live:run route /profile` yerine `route /profile`:

``` bash
metro live:run route /profile --data '{"id": 42}'
metro live:run storage SK_COINS 10
metro live:run backpack auth_user
metro live:run auth login --data '{"id": 42}'
metro live:run deeplink myapp://product/42
metro live:run state HomePage --data '{"count": 2}'
metro live:run event LogoutEvent --data '{"reason": "test"}'
metro live:run toast "Item saved" --title Success
```

`data`, sayfanızın durumunun bildirdiği alanları da çalışan uygulamadan doğrudan okur -- Flutter'da reflection olmadığından, bu yalnızca fiilen ekranda olan bir durum için çalışır:

``` bash
metro live:run data HomePage
```

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

## Live Komutlar

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

Yukarıdaki yerleşik komutların yanında, uygulamanın içinde çalışacak kendi komutlarınızı kaydedin.

<div id="creating-a-live-command"></div>

### Live Komut Oluşturma

``` bash
metro make:command seed_cart --live
```

| Seçenek | Açıklama |
|--------|-------------|
| `--category`, `-c` | Komutun kategorisi (varsayılan: `app`) |
| `--description` | Komutun `--help`'inde gösterilen tek satırlık açıklama |
| `--force`, `-f` | Dosya zaten mevcut olsa bile oluşturur |

Bu, `lib/app/commands/` içinde bir `LiveCommand` oluşturur, onu `commands.json` içinde `"type": "live"` olarak işaretler, `lib/bootstrap/live_commands.dart` içinde kaydeder ve `app_provider.dart` içindeki `nylo.configure(...)`'a `liveCommands: liveCommands` bağlar:

``` dart
class SeedCartCommand extends LiveCommand {
  @override
  CommandBuilder builder(CommandBuilder command) {
    command.addOption('count', abbr: 'c', defaultValue: '3');
    command.addFlag('open', help: 'Open the cart afterwards');
    return command;
  }

  @override
  Future<void> handle(CommandResult result) async {
    final int count = result.getInt('count') ?? 3;
    await CartItem.seed(count: count);
    success('Seeded $count cart items');
  }
}
```

`LiveCommand`, Metro'nun kendi komutlarıyla aynı `builder`/`handle` şeklini paylaşır, ancak `handle` **uygulamanın içinde** çalışır, bu yüzden `NyStorage`, `routeTo`, `Auth` ve modellerinizi kullanabilir. `package:nylo_framework/live.dart`, `LiveCommand`'ı `Seeder`, `StorageSnapshot`, `LiveException` ve `LiveOutput` ile birlikte dışa aktarır.

<div id="running-a-live-command"></div>

### Live Komutu Çalıştırma

Yeni bir live komutunun, çalışan uygulama onu çalıştırabilmeden önce bir hot restart'a ihtiyacı vardır. Ardından, terminalden:

``` bash
metro app:seed_cart --count 5
```

<div id="seeders"></div>

## Seeder'lar

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

<!-- uncertain: yeni Nylo terimi "Seeder" bu dosyada daha önce gecmiyordu; Türkçe karşılığı olmadığından ödünç sözcük olarak, kesme işaretiyle çekimlenerek bırakıldı -->

Bir `Seeder`, çalışan uygulamanızı bilinen bir duruma sokar -- oturum açılmış, onboarding tamamlanmış, örnek kayıtlar -- ve onu tekrar geri çıkarır.

<div id="creating-a-seeder"></div>

### Seeder Oluşturma

``` bash
metro make:seeder demo_user
```

| Seçenek | Açıklama |
|--------|-------------|
| `--description` | `seed` seeder'ları listelerken gösterilen tek satırlık açıklama |
| `--force`, `-f` | Dosya zaten mevcut olsa bile oluşturur |

Bu, `lib/app/seeders/` içinde bir `Seeder` oluşturur, `lib/bootstrap/seeders.dart` içinde kaydeder ve `nylo.configure(...)`'a `seeders: seeders` bağlar:

``` dart
class DemoUserSeeder extends Seeder {
  @override
  String get description => 'Jane Doe, signed in, onboarding done';

  @override
  Future<void> up() async {
    await Auth.authenticate(data: {'name': 'Jane Doe', 'token': 'demo'});
    await saveToStorage({'onboarding_complete': true});
    success('Signed in as Jane Doe');
  }

  @override
  Future<void> down() async {
    await restore();
  }
}
```

`up()`'ın değiştirdiği her storage ve Backpack değeri otomatik olarak kaydedilir, böylece varsayılan `down()` (`restore()`) her birini -- hot restart'ı bile aşarak -- tam olarak eskisi gibi, ters sırayla geri getirir. Bir seeder'ın içinden başkalarını da onun parçası olarak çalıştırmak için `seed(otherSeeders)` çağırın; onların değişiklikleri de kaydedilir ve geri alınır.

<div id="seeding-and-rolling-back"></div>

### Seed Etme ve Geri Alma

Seed etme, geri alma ve dışa aktarma yalnızca `metro live` kabuğunun içinde çalışır:

``` plaintext
› seed demo_user
Seeding demo_user
  + storage    SK_ONBOARDING  added
  ✓ Signed in as Jane Doe
✓ Seeded demo_user in 42ms
Undo with seed:rollback demo_user

› seed:rollback demo_user
Rolling back demo_user
  - storage    SK_ONBOARDING  removed
✓ Rolled back demo_user in 8ms
```

Tek başına `seed`, kayıtlı seeder'ları listeler. `--fresh`, seed etmeden önce storage ve Backpack'i temizler; `--restart` ise ardından uygulamayı hot restart yapar, böylece uygulama zaten seed edilmiş olarak açılır:

``` plaintext
› seed demo_user --fresh --restart
```

<div id="storage-snapshots"></div>

## Depolama Anlık Görüntüleri

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

<!-- uncertain: yeni terim "Storage Snapshots", "Depolama Anlık Görüntüleri" olarak çevrildi (anlık görüntü = snapshot); bu dosyada daha önce bir karşılığı yoktu -->

`export`, uygulamanın o an storage ve Backpack'te tuttuğu her şeyi -- bir seeder olarak, veya taşınabilir bir JSON dosyası olarak -- kaydeder; `seed <file>` ise bunu geri yükler.

<div id="exporting-a-snapshot"></div>

### Anlık Görüntü Dışa Aktarma

Neyin yakalanacağının önizlemesini görmek için adsız çalıştırın:

``` plaintext
› export
Storage on iPhone 15 Pro (2 values, 96 B)
KEY          TYPE    VALUE
SK_THEME     string  dark
SK_USER      model   {id: 1, name: Jane Doe}

Backpack (0 values)
Backpack is empty

Save it as a seeder with export <name>, or as a file with export --to <path>.json
```

`lib/app/seeders/` içinde bir seeder olarak kaydetmek için ona bir ad verin (`make:seeder` ile aynı, ama zaten yakalanan değerlerle doldurulmuş olarak):

``` plaintext
› export pro_user
```

Ya da bunun yerine bir dosyaya yazın:

``` plaintext
› export pro_user --to snapshots/pro_user.json
```

| Seçenek | Açıklama |
|--------|-------------|
| `--to <path>` | Anlık görüntüyü bir seeder yerine bu JSON dosyasına yaz |
| `--description` | Seeder için tek satırlık açıklama |
| `--only <keys>` | Dışa aktarılacak, virgülle ayrılmış anahtarlar; `*` her şeyle eşleşir, örn. `--only SK_USER,onboarding_*` |
| `--except <keys>` | Dışarıda bırakılacak, virgülle ayrılmış anahtarlar, örn. `--except 'cache_*'` |
| `--backpack` / `--no-backpack` | Backpack değerlerini dahil et (varsayılan: dahil) |
| `--force`, `-f` | Zaten var olan bir seeder'ın veya dosyanın yerini al |

Bir `Model`, veya kayıtlı bir decoder'a sahip herhangi bir sınıf, sınıf adıyla etiketlenir; böylece düz bir map yerine kendi decoder'ından geri gelir. `export`, anlık görüntü kimlik bilgilerine benzeyen anahtarlar içerdiğinde ve muhtemelen `--except` kullanmanız gerekecek kadar büyük olduğunda uyarır.

<div id="loading-a-snapshot"></div>

### Anlık Görüntü Yükleme

``` plaintext
› seed snapshots/pro_user.json
```

Bir dosyayı yüklemek, bir seeder ile aynı şekilde kaydedilir, böylece `seed:rollback <name>` (dosya adı, veya `--as` ile verilen ad) bunu da geri alır. Kod tarafında, bir seeder yakalanmış bir anlık görüntüyü `importSnapshot` ile uygulayabilir:

``` dart
class ProUserSeeder extends Seeder {
  @override
  Future<void> up() async {
    await importSnapshot(snapshot);
  }

  static const Map<String, Object?> snapshot = {
    'storage': {
      'SK_USER': {'type': 'model', 'model': 'User', 'value': {'id': 1}},
    },
    'backpack': {},
  };
}
```

`export` tam olarak bu şekli yazar, böylece `--to` ile yazılan bir dosya doğrudan bir seeder'ın `snapshot` alanına yapıştırılabilir.

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

## Sayfa Aksiyonları

<div class="ny-doc-strip">
<span class="ny-doc-strip-label">Gereksinimler</span>
<span class="ny-doc-strip-item">Nylo 7.2.0+</span>
<span class="ny-doc-strip-dot"></span>
<span class="ny-doc-strip-item">nylo_support 7.30.0+</span>
</div>

Bir sayfadaki `path.actions`, `stateAction(...)` çağrısını elle oluşturmadan o sayfayı dışarıdan çağırmak için size bir `PageStateActions` verir:

``` dart
class ProductPage extends NyStatefulWidget {
  static RouteView path = ("/product", (_) => ProductPage());
  static final actions = path.actions;

  ProductPage({super.key}) : super(child: () => _ProductPageState());
}

ProductPage.actions.showToast("Added to bag");
ProductPage.actions.refreshPage();
```

Yerleşik aksiyonların tam listesini ve kendi tipli aksiyonlarınızı nasıl tanımlayacağınızı görmek için [Sayfa Aksiyonlarını Çağırma](/docs/7.x/state-management#page-actions-shortcut) sayfasına bakın. Nylo Live aynı aksiyonları okur ve kullanır: `metro live:run data`, ekrandaki bir sayfanın `actions` altında neler sunduğunu listeler; `metro live:run state` ise bir sayfaya verileri doğrudan durumunun adıyla gönderir.
