This commit is contained in:
2026-07-30 20:48:05 +03:00
parent d3b37eb4bd
commit 4ce6bae61c
23 changed files with 340 additions and 1694 deletions

View File

@@ -8,10 +8,14 @@
- [`SLM-L2-PRESET-R011`](../../rules/level-2.md#slm-l2-preset-r011)
- [`SLM-L2-DEPENDENCY-A012`](../../rules/level-2.md#slm-l2-dependency-a012)
- [`SLM-L2-ENVIRONMENT-A013`](../../rules/level-2.md#slm-l2-environment-a013)
- [`SLM-L2-BUSINESS-A019`](../../rules/level-2.md#slm-l2-business-a019)
- [`SLM-L2-PRESET-A020`](../../rules/level-2.md#slm-l2-preset-a020)
- [`SLM-L2-ADAPTER-R021`](../../rules/level-2.md#slm-l2-adapter-r021)
- [`SLM-L2-BUSINESS-A022`](../../rules/level-2.md#slm-l2-business-a022)
## Назначение
Preset является SLM-модулем в Group `presets`. Он создаёт API одной business-фабрики для конкретного повторяемого контекста выполнения.
Preset является SLM-модулем в Group `presets`. Он создаёт API одной business-фабрики для конкретного повторяемого контекста выполнения. Каждый доменный пакет содержит минимум один preset-модуль.
```text
authFactory
@@ -20,29 +24,39 @@ authFactory
└── presets/server-action → AuthApi server action
```
Архитектура не требует обязательный `base` или изоморфный preset и не ограничивает количество presets. Проект создаёт только те сборки, которые нужны его реальным средам и областям использования.
Архитектура не требует `base` или изоморфный preset и не ограничивает максимальное количество presets. Обязательный preset должен соответствовать реальному поддерживаемому контексту, а не существовать только для заполнения структуры.
Если фабрика используется в одном месте и отдельная повторяемая конфигурация не возникает, место сборки графа может вызвать её напрямую.
Место сборки графа в `composition` может вызвать фабрику напрямую для одноразовой конфигурации. Такая сборка не отменяет обязательный preset пакета и при наличии технических зависимостей использует публичные adapter-модули, а не inline implementations.
## Один контракт API
Каждый preset выбирает технические реализации, но вызывает одну и ту же фабрику и возвращает один контракт `DomainApi`:
Каждый preset вызывает одну и ту же фабрику и возвращает один контракт `DomainApi`. При наличии технических зависимостей preset выбирает их публичные adapter-модули:
```ts
import type { AuthApi } from '@/domains/auth/business'
import { authFactory } from '@/domains/auth/business/factory'
import { createPhoneHttpAdapter } from '@/domains/auth/adapters/phone-http'
import { createBrowserSessionAdapter } from '@/domains/auth/adapters/browser-session'
export const createBrowserAuth = (): AuthApi => {
return authFactory({
phone: createHttpPhoneAdapter(),
phone: createPhoneHttpAdapter(),
session: createBrowserSessionAdapter(),
})
}
```
```ts
import type { AuthApi } from '@/domains/auth/business'
import { authFactory } from '@/domains/auth/business/factory'
import { createRequestPhoneAdapter } from '@/domains/auth/adapters/request-phone'
import { createRequestSessionAdapter } from '@/domains/auth/adapters/request-session'
export const createAuthForRequest = (
input: AuthRequestInput,
): AuthApi => {
return authFactory({
phone: createServerPhoneAdapter(input),
phone: createRequestPhoneAdapter(input),
session: createRequestSessionAdapter(input),
})
}
@@ -54,10 +68,13 @@ Server preset может обращаться к database напрямую че
## Cross-domain input
Preset зависимого домена принимает готовый API аргументом:
Preset зависимого домена принимает готовый API аргументом. Cross-domain API не является adapter и не размещается в Group `adapters`:
```ts
import type { AuthApi } from '@/domains/auth/business'
import type { UserApi } from '@/domains/user/business'
import { userFactory } from '@/domains/user/business/factory'
import { createUserProfileAdapter } from '@/domains/user/adapters/profile'
export type CreateUserForRequestInput = {
authApi: Pick<AuthApi, 'getSession'>