@application-kit/graphql
v0.3.2
Published
Контракт ошибок GraphQL (сервер и клиент) и типы курсорного листинга для NestJS
Maintainers
Readme
@application-kit/graphql
Контракт ошибок GraphQL для NestJS-приложений с Apollo-клиентом и типы курсорного листинга. Сервер и клиент
делят одно объявление «что лежит в extensions ошибки»: переименование поля ломает сборку, а не прод.
Установка
yarn add @application-kit/graphqlPeer-зависимости: @nestjs/common, @nestjs/graphql, class-transformer, class-validator, graphql,
@apollo/client — обязательные; @nestjs/mercurius, mercurius, @libs-for-dev/nestjs-config-module — optional,
нужны только входу /nest. Зависимость @application-kit/typeorm ставится сама (типы листинга
берут оттуда FiltersMatchMode и SortOrder).
Входы
| Вход | Для чего | Тянет |
|------|----------|-------|
| @application-kit/graphql | сервер: ошибки, форматтер, типы листинга | @nestjs/*, class-validator |
| @application-kit/graphql/client | браузер и SSR: чтение extensions ответа | только @apollo/client, graphql (типы) |
| @application-kit/graphql/nest | периметр Mercurius-сервера: опции драйвера, окружение, конфиг | mercurius, @nestjs/mercurius (типы), @libs-for-dev/nestjs-config-module |
Клиентский вход не содержит импортов серверных зависимостей — его можно собирать в браузерный бандл.
Сервер
BusinessGraphQLError<TMessageCode>— бизнес-ошибка с транспортным кодом (BAD_USER_INPUT,FORBIDDEN,NOT_FOUND) и кодом показываемого текстаmessageCode.matchBusinessError(table, fallback)— таблица «класс доменной ошибки → опции ответа», первая подходящая строка.formatGraphQLError(error, supportId)— единая точка форматирования:HttpException→extensions, техническая ошибка получаетsupportId, бизнесовая — нет (isBusinessGraphQLError).- Типы листинга:
Payload(@ArgsType),PaginatorInputType(потолокlimit200),FilterInputType,SortingInputType,CursorOutputType,ListingResponseInterface.
Словарь кодов сообщений — у приложения
Пакет не знает кодов сообщений: тип кода — параметр без значения по умолчанию. Приложение один раз связывает его со своим объединением, и неизвестный код перестаёт компилироваться:
type MessageCode = 'signIn.invalidCredentials' | 'profile.notFound'
export class BusinessGraphQLError extends BaseBusinessGraphQLError<MessageCode> {}
export type BusinessErrorOptions = BusinessErrorOptionsInterface<MessageCode>Сервер Mercurius (/nest)
createMercuriusOptions({ schemaPath, maxDepth, playground, resolveSupportId })— опцииMercuriusDriver: выключена консоль (playground: false) — выключена и интроспекция схемы; запрос глубжеmaxDepthотвергается до исполнения;errorFormatterпрогоняет каждую ошибку черезformatGraphQLErrorс однимsupportIdна ответ. ПустойschemaPath— схема только в памяти.GraphqlEnvironment—GRAPHQL_PLAYGROUND(дефолтfalse) и необязательныйGRAPHQL_SCHEMA_PATH;GraphqlConfig.createOptions({ schemaPath, maxDepth, resolveSupportId })берёт флаг консоли из окружения, путь — из окружения, если он задан, иначе из вызова. Регистрацию делает приложение:
ConfigsModule.forFeature([GraphqlConfig], [GraphqlEnvironment])
GraphQLModule.forRootAsync({
driver: MercuriusDriver,
inject: [GraphqlConfig],
useFactory: (config: GraphqlConfig) => config.createOptions({ maxDepth: 5, resolveSupportId, schemaPath: 'src/schema.gql' }),
})Источник supportId (трасса, id запроса) пакет не выбирает: резолвер передаёт приложение.
Клиент
supportIdFromError,rejectedCharactersFromError,messageCodeFromError— читатели полейextensionsответа Apollo (CombinedGraphQLErrors): по полю на вызов, перебор всех ошибок ответа.SKIP_GLOBAL_ERROR_TOAST/shouldSkipGlobalErrorToast— ключ контекста Apollo «ошибку операции показывает вызывающий».
Перевода в пакете нет: он отдаёт данные из ошибки (код сообщения, код обращения, отклонённые символы), а текст для пользователя собирает приложение — код → ключ своего словаря → строка на языке пользователя → строка с кодом обращения.
