Monorepo skeleton, Prisma schema, core domain and services with tests

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zabudko-ruandClaude Opus 5.5 committed 2026-10-17 19:45:51 +04:00
commit 45d7512d2b
64 files changed
+9483

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
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 };
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';