# Миграция с версии 0.9.x на 0.10.0

## Query

### Результат `trigger` агента и хука — конверт вместо сырого промиса

`trigger` на уровне агента (`CommandAgent.trigger`) и хука (`useCommand`) теперь возвращает `TTriggerPromise<TData>` — промис, который **никогда не реджектится**. Итог мутации приходит конвертом `TTriggerResult<TData>`, дискриминированным по полю `status`:

```typescript
type TTriggerResult<TData> =
  | { status: "success"; data: TData; error?: undefined }
  | { status: "error"; data?: undefined; error: unknown };
```

`Command.trigger` (уровень ядра) **не изменился** — по-прежнему возвращает сырой `Promise<TData>`, реджектящийся ошибкой.

#### try/catch → проверка конверта

`try/catch` вокруг `await trigger(...)` больше не срабатывает — ветка `catch` стала мёртвым кодом. Переходите на проверку конверта:

```tsx
// Было
try {
    const data = await trigger({ text });     // ❌ данные напрямую
    console.log(data);
} catch (err) {
    console.error(err);                       // ❌ больше не вызовется
}

// Стало
const result = await trigger({ text });
if (result.status === 'error') {
    console.error(result.error);              // ✅
} else {
    console.log(result.data);                 // ✅
}
```

#### Нужна прежняя «бросающая» семантика → `.unwrap()`

Если код рассчитывает на сырой результат (данные при успехе, исключение при ошибке), добавьте `.unwrap()` — это в точности прежний контракт:

```typescript
// Было
const data = await agent.trigger({ text: 'Задача' });            // ❌

// Стало
const data = await agent.trigger({ text: 'Задача' }).unwrap();   // ✅
```

#### Fire-and-forget: защитный `.catch()` больше не нужен

```typescript
// Было
trigger({ amount: 100 }).catch(() => {
    // подавление реджекта, ошибка — через state.isError
});                                           // ❌ мёртвый код

// Стало
void trigger({ amount: 100 });                // ✅ промис не реджектится
```

#### Типы

Если в сигнатурах фигурировал тип триггера из хука/агента, обновите его:

```typescript
// Было
let onSubmit: (args: TArgs) => Promise<TData>;          // ❌

// Стало
import type { TTriggerPromise } from '@fozy-labs/rx-toolkit';

let onSubmit: (args: TArgs) => TTriggerPromise<TData>;  // ✅
```

### Что не изменилось

- `Command.trigger` — сырой `Promise<TData>`; при ошибке реджектится. Обернуть его в конверт вручную можно новым хелпером `wrapTrigger`:

  ```typescript
  import { wrapTrigger } from '@fozy-labs/rx-toolkit';

  const result = await wrapTrigger(addTodoCommand.trigger({ text: 'Задача' }));
  ```

- Реактивное состояние (`TCommandAgentState`: `status`, `data`, `error`, `isLoading`, `isSuccess`, `isError`, `retry`) — код, читающий состояние из `useCommand`/`state$`, менять не нужно.
- Ретраи и request id — `retry()` и стабильность ключа идемпотентности работают как раньше.

Подробнее о конверте — в [API агента команды](../query/api/command-agent.md#результат-trigger).
