Files
BarevClub/packages/services/src/context.ts
T

84 lines
3.1 KiB
TypeScript

import type { Db } from '@barev/db';
import type { OrderStatus } from '@barev/core';
/** Доменные события. Воркер превращает их в уведомления на языке получателя. */
export type DomainEvent =
| { type: 'order.created'; orderId: string }
| { type: 'order.status'; orderId: string; from: OrderStatus; to: OrderStatus }
/** событие без смены статуса, например «Я на месте» */
| { type: 'order.event'; orderId: string; code: string }
| { type: 'order.rescheduled'; orderId: string }
| { type: 'order.unassigned'; orderId: string; providerId: string }
| { type: 'offer.created'; offerId: string }
| { type: 'offer.declined'; offerId: string }
| { type: 'offer.expired'; offerId: string }
| { type: 'company.order'; orderId: string; companyId: string }
| { type: 'order.reminder'; orderId: string; hours: 24 | 1 }
| { type: 'gift.activated'; clientId: string; endsAt: string }
/** оператор сменил статус шага переезда — клиенту сообщение в бота */
| { type: 'lead.step'; stepId: string }
/** оператор ответил в чате консьержа — ответ уходит в чат с ботом */
| { type: 'concierge.reply'; messageId: string }
/** оператор включил подписку по заявке из приложения */
| { type: 'subscription.activated'; subscriptionId: string }
/** уведомления операторам в рабочий бот */
| { type: 'concierge.message'; messageId: string }
| { type: 'lead.submitted'; leadId: string }
| { type: 'clientRequest.created'; requestId: string }
| { type: 'webRequest.created'; requestId: string };
export interface Notifier {
emit(event: DomainEvent): Promise<void> | void;
}
export interface Ctx {
db: Db;
notify: Notifier;
now: () => Date;
}
export const silentNotifier: Notifier = { emit: () => {} };
/** Ошибка бизнес-логики. code переводится на фронте как errors.<code>. */
export class DomainError extends Error {
constructor(
public code: DomainErrorCode,
public details?: Record<string, unknown>,
) {
super(code);
this.name = 'DomainError';
}
}
export type DomainErrorCode =
| 'NOT_FOUND'
| 'FORBIDDEN'
| 'CONSENT_REQUIRED'
| 'SERVICE_UNAVAILABLE'
| 'INVALID_PARAMS'
| 'SLOT_UNAVAILABLE'
| 'ADDRESS_REQUIRED'
| 'TRANSITION_NOT_ALLOWED'
| 'CHECKLIST_INCOMPLETE'
| 'PHOTO_REQUIRED'
| 'ESTIMATE_NOT_ACCEPTED'
| 'CANCEL_VIA_OPERATOR'
| 'RESCHEDULE_VIA_OPERATOR'
| 'AGENCY_CODE_INVALID'
| 'AGENCY_ALREADY_SET'
| 'OFFER_NOT_ACTIVE'
| 'PROVIDER_BUSY'
| 'ALREADY_ASSIGNED'
| 'INVITE_INVALID'
| 'NOT_PAID_STATE'
| 'PHONE_INVALID'
| 'CONTACT_INVALID'
| 'NAME_REQUIRED'
| 'PROVIDER_NOT_LINKED'
| 'CARD_EXPIRED'
| 'OFFER_NOT_AVAILABLE'
| 'OFFER_LIMIT_REACHED';
/** Имя очереди BullMQ, через которую API и боты передают события воркеру */
export const EVENTS_QUEUE = 'barev-events';