Skip to content

Сервисы

Паттерн

Каждый сервис — это класс-синглтон, экспортируемый как единственный экземпляр:

ts
import { clientService } from '@diealltagsfeen/frontend-api-client'

Сервисы — тонкие обёртки над HTTP-клиентом пакета (http). Метод строит путь и делегирует вызов в http.get/post/put/patch/delete, который резолвит хост, проверяет контракт ответа и централизованно обрабатывает ошибки. Никакой трансформации данных в сервисах нет — ответ возвращается как есть.

Сигнатуры методов

Публичные методы — async-функции, которые:

  • Принимают параметры: примитив (id), уже собранный queryString: string для списков, либо типизированный объект DTO для тела запроса.
  • Возвращают Promise<ApiResult<T>> — типизированный успешный ответ либо null.
ts
// Примитив-идентификатор
const client = await clientService.GetById(123)

// Тело запроса — типизированный DTO
await clientService.Update(updateClientRequestDto)

// Объект с несколькими полями
await clientService.UpdateStatus({ clientId: 123, status: 400 })

// Список с фильтрами — query-string собирает вызывающий код
const result = await clientService.GetTable(queryString)

Построение query-string для списков

Большинство GetTable-методов принимают готовую строку запроса (queryString: string) — её формирует вызывающий код. Бэкенд ожидает поля в PascalCase (Pagination.CurrentPage, Pagination.RowsPerPage, Pagination.SortBy, Pagination.Descending, *Filters):

ts
const params = new URLSearchParams()
params.append('Pagination.CurrentPage', String(page))
params.append('Pagination.RowsPerPage', String(rowsPerPage))
params.append('Pagination.SortBy', sortBy)
params.append('Pagination.Descending', String(descending))
statusFilters.forEach((s) => params.append('ClientStatusFilters', String(s)))

const result = await clientService.GetTable(params.toString())

Часть сервисов (модуль учёта рабочего времени) принимает типизированный объект параметров и собирает query-string внутри метода — смотрите сигнатуру конкретного метода в API Reference.

Тип ответа ApiResult

ts
type ApiResult<T> = ApiSuccess<T> | null
type ApiSuccess<T> = { successfully: true } & T

Успешный ответ всегда содержит дискриминатор successfully: true и полезную нагрузку конкретного эндпоинта. Параметр-дженерик T объявляет форму ответа:

ts
async Get(): Promise<ApiResult<GetWorkTimeSettingsResponseDto>> {
  return await http.get<GetWorkTimeSettingsResponseDto>('managerTimeTracker', 'Api/WorkTimeSettings')
}

Перед обращением к полям проверяйте результат на истинность — это сужает тип к ApiSuccess<T>:

ts
const result = await workTimeSettingsAccessService.Get()
if (result) {
  // result: ApiSuccess<GetWorkTimeSettingsResponseDto>
  useSettings(result.settings)
}

Обработка ошибок

Обработка ошибок централизована в HTTP-обёртке (http). При неуспешном ответе или сетевой ошибке она бросает исключение и вызывает колбэк onError, переданный в init():

  • Тело с полем type (RFC-7807) → ProblemDetailsError (поля type, title, detail, data).
  • Прочие неуспешные ответы → ApiError (поля httpStatus, status, type, title, data).
  • Сетевая/axios-ошибка → логируется через onError и пробрасывается дальше.

Сами сервисы исключения не ловят. Если нужно обработать ошибку — оборачивайте вызов в try/catch:

ts
import { ApiError, ProblemDetailsError } from '@diealltagsfeen/frontend-api-client'

try {
  const result = await clientService.Create(body)
} catch (e) {
  if (e instanceof ProblemDetailsError && e.type === 'client-exists') {
    // обработать конкретную бизнес-ошибку
  } else if (e instanceof ApiError) {
    // общая ошибка API: e.status, e.title
  }
}

Загрузка файлов

Методы загрузки принимают FormData и передают его как тело запроса:

ts
const formData = new FormData()
formData.append('ClientId', String(clientId))
formData.append('Files[0].FileType', String(fileType))
formData.append('Files[0].File', file)

await clientService.AddFiles(formData)

Скачивание файлов

Для бинарных ответов используется низкоуровневый метод http.blob — соответствующие сервисные методы возвращают Blob (контракт successfully не проверяется):

ts
const blob = await datevExportAccessService.Export(queryString) // → Blob