Files
slm-design/DRAFT/level-3/domains/presets.md

90 lines
4.2 KiB
Markdown
Raw Normal View History

# Presets и SSR
2026-07-30 13:22:45 +03:00
> Пояснение повторяемой assembly Domain.
2026-07-30 13:22:45 +03:00
## Связанные правила
2026-07-30 13:22:45 +03:00
- [`SLM-L3-PRESET-R009`](../../rules/level-3.md#slm-l3-preset-r009)
- [`SLM-L3-ASSEMBLY-R010`](../../rules/level-3.md#slm-l3-assembly-r010)
- [`SLM-L3-ENVIRONMENT-A012`](../../rules/level-3.md#slm-l3-environment-a012)
- [`SLM-L3-FACTORY-R006`](../../rules/level-3.md#slm-l3-factory-r006)
2026-07-30 13:22:45 +03:00
## Роль preset
2026-07-30 13:22:45 +03:00
Preset -- именованная повторяемая assembly одной business factory для конкретного execution context. Он выбирает concrete implementations ports, создаёт `AuthApi` и передаёт caller lifecycle operations, определённые module-владельцами resources.
```text
authFactory
2026-07-30 13:22:45 +03:00
├── presets/application -> browser-compatible AuthApi
├── presets/request -> request-scoped AuthApi
└── presets/server-action -> server action AuthApi
```
2026-07-30 13:22:45 +03:00
Среда определяется preset и adapters, а не `mode` внутри factory. Tests создают per-test assembly напрямую через factory и не требуют общего `presets/testing`.
2026-07-30 13:22:45 +03:00
## Структура и public API
2026-07-30 13:22:45 +03:00
```text
domains/auth/presets/application/
├── adapters/
├── create-application-auth.ts
├── create-application-auth.test.ts
└── index.ts
```
2026-07-30 13:22:45 +03:00
`application` -- пример имени. Preset называется по execution scope или устойчивому назначению: `application`, `request`, `server-action`. Он не называется по temporary consumer, если configuration не предназначена для повторного использования.
```ts
2026-07-30 13:22:45 +03:00
export const createApplicationAuth = (): AuthApi => {
return authFactory({
phone: createApplicationAuthPhoneAdapter(),
session: createApplicationAuthSessionAdapter(),
})
}
```
2026-07-30 13:22:45 +03:00
Preset не добавляет scenario, не меняет error mapping и не скрывает business rule. Он также не становится монополией на factory: явный composition graph owner может собрать одноразовый graph, если он принимает на себя все обязанности assembly.
2026-07-30 13:22:45 +03:00
## Scope и lifecycle
2026-07-30 13:22:45 +03:00
Preset объявляет ожидаемый scope API instance. Application preset используется в application scope; request preset создаёт новый instance для каждого request. Graph owner удерживает instance только в этом scope и не хранит request data в application singleton.
2026-07-30 13:22:45 +03:00
Если assembly создаёт lifecycle resource, caller получает явный cleanup handle:
```ts
2026-07-30 13:22:45 +03:00
export type AuthRequestAssembly = {
api: AuthApi
dispose: () => void | Promise<void>
}
export const createAuthForRequest = (
input: AuthRequestInput,
2026-07-30 13:22:45 +03:00
): AuthRequestAssembly => {
const session = createRequestSessionAdapter(input)
return {
api: authFactory({
phone: createRequestAuthPhoneAdapter(input),
session,
}),
dispose: session.dispose,
}
}
```
2026-07-30 13:22:45 +03:00
Factory и preset construction не запускают I/O или subscriptions. Если domain lifecycle должен начать resource, module-владелец выражает это отдельной API operation; graph owner вызывает её после начала scope и выполняет предоставленный cleanup при его завершении.
## Server-only boundary
2026-07-30 13:22:45 +03:00
Server preset имеет отдельный entrypoint и marker выбранного framework/build system:
```ts
import 'server-only'
export { createAuthForRequest } from './create-auth-for-request'
```
2026-07-30 13:22:45 +03:00
Этот entrypoint не реэкспортируется через `business`, `react` или client-compatible preset. Server adapter может иметь собственный marker для защиты от ошибочного прямого import.
2026-07-30 13:22:45 +03:00
Framework module не вызывает preset и не создаёт factory. Он получает готовый `AuthApi` от graph owner, поэтому React lifecycle не смешивается с concrete assembly.