@application-kit/graphql 0.0.0-stage → 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +55 -2
- package/dist/cjs/client/index.d.ts +4 -0
- package/dist/cjs/client/index.js +20 -0
- package/dist/cjs/client/message-code-from-error.d.ts +1 -0
- package/dist/cjs/client/message-code-from-error.js +12 -0
- package/dist/cjs/client/rejected-characters-from-error.d.ts +1 -0
- package/dist/cjs/client/rejected-characters-from-error.js +19 -0
- package/dist/cjs/client/request-error.d.ts +8 -0
- package/dist/cjs/client/request-error.js +19 -0
- package/dist/cjs/client/support-id-from-error.d.ts +1 -0
- package/dist/cjs/client/support-id-from-error.js +13 -0
- package/dist/cjs/contract/graphql-error-contract.d.ts +17 -0
- package/dist/cjs/contract/graphql-error-contract.js +5 -0
- package/dist/cjs/contract/index.d.ts +1 -0
- package/dist/cjs/contract/index.js +17 -0
- package/dist/cjs/errors/add-support-id-to-graphql-error.d.ts +2 -0
- package/dist/cjs/errors/add-support-id-to-graphql-error.js +21 -0
- package/dist/cjs/errors/business-graphql-error.d.ts +5 -0
- package/dist/cjs/errors/business-graphql-error.js +11 -0
- package/dist/cjs/errors/format-graphql-error.d.ts +2 -0
- package/dist/cjs/errors/format-graphql-error.js +17 -0
- package/dist/cjs/errors/index.d.ts +6 -0
- package/dist/cjs/errors/index.js +22 -0
- package/dist/cjs/errors/is-business-graphql-error.d.ts +2 -0
- package/dist/cjs/errors/is-business-graphql-error.js +14 -0
- package/dist/cjs/errors/map-http-exception-to-graphql-error.d.ts +3 -0
- package/dist/cjs/errors/map-http-exception-to-graphql-error.js +29 -0
- package/dist/cjs/errors/match-business-error.d.ts +7 -0
- package/dist/cjs/errors/match-business-error.js +8 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/listing/cursor-output.type.d.ts +5 -0
- package/dist/cjs/listing/cursor-output.type.js +29 -0
- package/dist/cjs/listing/cursor-type.interface.d.ts +2 -0
- package/dist/cjs/listing/cursor-type.interface.js +2 -0
- package/dist/cjs/listing/filter-input.type.d.ts +6 -0
- package/dist/cjs/listing/filter-input.type.js +36 -0
- package/dist/cjs/listing/index.d.ts +7 -0
- package/dist/cjs/listing/index.js +23 -0
- package/dist/cjs/listing/listing-payload.d.ts +8 -0
- package/dist/cjs/listing/listing-payload.js +41 -0
- package/dist/cjs/listing/listing-response.interface.d.ts +6 -0
- package/dist/cjs/listing/listing-response.interface.js +2 -0
- package/dist/cjs/listing/paginator-input.type.d.ts +4 -0
- package/dist/cjs/listing/paginator-input.type.js +34 -0
- package/dist/cjs/listing/sorting-input.type.d.ts +5 -0
- package/dist/cjs/listing/sorting-input.type.js +31 -0
- package/dist/cjs/package.json +3 -0
- package/dist/esm/client/index.d.ts +4 -0
- package/dist/esm/client/index.js +4 -0
- package/dist/esm/client/message-code-from-error.d.ts +1 -0
- package/dist/esm/client/message-code-from-error.js +8 -0
- package/dist/esm/client/rejected-characters-from-error.d.ts +1 -0
- package/dist/esm/client/rejected-characters-from-error.js +15 -0
- package/dist/esm/client/request-error.d.ts +8 -0
- package/dist/esm/client/request-error.js +13 -0
- package/dist/esm/client/support-id-from-error.d.ts +1 -0
- package/dist/esm/client/support-id-from-error.js +9 -0
- package/dist/esm/contract/graphql-error-contract.d.ts +17 -0
- package/dist/esm/contract/graphql-error-contract.js +2 -0
- package/dist/esm/contract/index.d.ts +1 -0
- package/dist/esm/contract/index.js +1 -0
- package/dist/esm/errors/add-support-id-to-graphql-error.d.ts +2 -0
- package/dist/esm/errors/add-support-id-to-graphql-error.js +17 -0
- package/dist/esm/errors/business-graphql-error.d.ts +5 -0
- package/dist/esm/errors/business-graphql-error.js +7 -0
- package/dist/esm/errors/format-graphql-error.d.ts +2 -0
- package/dist/esm/errors/format-graphql-error.js +13 -0
- package/dist/esm/errors/index.d.ts +6 -0
- package/dist/esm/errors/index.js +6 -0
- package/dist/esm/errors/is-business-graphql-error.d.ts +2 -0
- package/dist/esm/errors/is-business-graphql-error.js +10 -0
- package/dist/esm/errors/map-http-exception-to-graphql-error.d.ts +3 -0
- package/dist/esm/errors/map-http-exception-to-graphql-error.js +25 -0
- package/dist/esm/errors/match-business-error.d.ts +7 -0
- package/dist/esm/errors/match-business-error.js +4 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/listing/cursor-output.type.d.ts +5 -0
- package/dist/esm/listing/cursor-output.type.js +26 -0
- package/dist/esm/listing/cursor-type.interface.d.ts +2 -0
- package/dist/esm/listing/cursor-type.interface.js +1 -0
- package/dist/esm/listing/filter-input.type.d.ts +6 -0
- package/dist/esm/listing/filter-input.type.js +33 -0
- package/dist/esm/listing/index.d.ts +7 -0
- package/dist/esm/listing/index.js +7 -0
- package/dist/esm/listing/listing-payload.d.ts +8 -0
- package/dist/esm/listing/listing-payload.js +38 -0
- package/dist/esm/listing/listing-response.interface.d.ts +6 -0
- package/dist/esm/listing/listing-response.interface.js +1 -0
- package/dist/esm/listing/paginator-input.type.d.ts +4 -0
- package/dist/esm/listing/paginator-input.type.js +31 -0
- package/dist/esm/listing/sorting-input.type.d.ts +5 -0
- package/dist/esm/listing/sorting-input.type.js +28 -0
- package/package.json +91 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 application-kit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,56 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @application-kit/graphql
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Контракт ошибок GraphQL для NestJS-приложений с Apollo-клиентом и типы курсорного листинга. Сервер и клиент
|
|
4
|
+
делят одно объявление «что лежит в `extensions` ошибки»: переименование поля ломает сборку, а не прод.
|
|
5
|
+
|
|
6
|
+
## Установка
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
yarn add @application-kit/graphql
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Peer-зависимости: `@nestjs/common`, `@nestjs/graphql`, `class-transformer`, `class-validator`, `graphql`,
|
|
13
|
+
`@apollo/client`. Все обязательные. Зависимость `@application-kit/typeorm` ставится сама (типы листинга
|
|
14
|
+
берут оттуда `FiltersMatchMode` и `SortOrder`).
|
|
15
|
+
|
|
16
|
+
## Входы
|
|
17
|
+
|
|
18
|
+
| Вход | Для чего | Тянет |
|
|
19
|
+
|------|----------|-------|
|
|
20
|
+
| `@application-kit/graphql` | сервер: ошибки, форматтер, типы листинга | `@nestjs/*`, `class-validator` |
|
|
21
|
+
| `@application-kit/graphql/client` | браузер и SSR: чтение `extensions` ответа | только `@apollo/client`, `graphql` (типы) |
|
|
22
|
+
|
|
23
|
+
Клиентский вход не содержит импортов серверных зависимостей — его можно собирать в браузерный бандл.
|
|
24
|
+
|
|
25
|
+
## Сервер
|
|
26
|
+
|
|
27
|
+
- `BusinessGraphQLError<TMessageCode>` — бизнес-ошибка с транспортным кодом (`BAD_USER_INPUT`, `FORBIDDEN`,
|
|
28
|
+
`NOT_FOUND`) и кодом показываемого текста `messageCode`.
|
|
29
|
+
- `matchBusinessError(table, fallback)` — таблица «класс доменной ошибки → опции ответа», первая подходящая строка.
|
|
30
|
+
- `formatGraphQLError(error, supportId)` — единая точка форматирования: `HttpException` → `extensions`,
|
|
31
|
+
техническая ошибка получает `supportId`, бизнесовая — нет (`isBusinessGraphQLError`).
|
|
32
|
+
- Типы листинга: `Payload` (`@ArgsType`), `PaginatorInputType` (потолок `limit` 200), `FilterInputType`,
|
|
33
|
+
`SortingInputType`, `CursorOutputType`, `ListingResponseInterface`.
|
|
34
|
+
|
|
35
|
+
### Словарь кодов сообщений — у приложения
|
|
36
|
+
|
|
37
|
+
Пакет не знает кодов сообщений: тип кода — параметр без значения по умолчанию. Приложение один раз связывает его
|
|
38
|
+
со своим объединением, и неизвестный код перестаёт компилироваться:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
type MessageCode = 'signIn.invalidCredentials' | 'profile.notFound'
|
|
42
|
+
|
|
43
|
+
export class BusinessGraphQLError extends BaseBusinessGraphQLError<MessageCode> {}
|
|
44
|
+
export type BusinessErrorOptions = BusinessErrorOptionsInterface<MessageCode>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Клиент
|
|
48
|
+
|
|
49
|
+
- `supportIdFromError`, `rejectedCharactersFromError`, `messageCodeFromError` — читатели полей `extensions` ответа
|
|
50
|
+
Apollo (`CombinedGraphQLErrors`): по полю на вызов, перебор всех ошибок ответа.
|
|
51
|
+
- `createDescribeRequestError(messageKeyFromError)` — готовый текст для тоста: ключ словаря по коду с провода,
|
|
52
|
+
запасной текст на техническую ошибку и незнакомый код, `supportId` дописывается строкой.
|
|
53
|
+
- `SKIP_GLOBAL_ERROR_TOAST` / `shouldSkipGlobalErrorToast` — ключ контекста Apollo «ошибку операции показывает вызывающий».
|
|
54
|
+
|
|
55
|
+
Словарь потребителя обязан содержать строку под ключом `SUPPORT_ID_LINE_KEY` (`error.supportIdLine`) с
|
|
56
|
+
плейсхолдером `{id}`; тип этого не выразит, проверка — спекой словаря в приложении.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./message-code-from-error.js"), exports);
|
|
18
|
+
__exportStar(require("./rejected-characters-from-error.js"), exports);
|
|
19
|
+
__exportStar(require("./request-error.js"), exports);
|
|
20
|
+
__exportStar(require("./support-id-from-error.js"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const messageCodeFromError: (error: unknown) => null | string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.messageCodeFromError = void 0;
|
|
4
|
+
const errors_1 = require("@apollo/client/errors");
|
|
5
|
+
const messageCodeOf = (graphqlError) => {
|
|
6
|
+
const extensions = graphqlError.extensions ?? {};
|
|
7
|
+
return extensions.messageCode;
|
|
8
|
+
};
|
|
9
|
+
const messageCodeFromError = (error) => (errors_1.CombinedGraphQLErrors.is(error)
|
|
10
|
+
? error.errors.map((graphqlError) => messageCodeOf(graphqlError)).find((code) => code !== undefined) ?? null
|
|
11
|
+
: null);
|
|
12
|
+
exports.messageCodeFromError = messageCodeFromError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const rejectedCharactersFromError: (error: unknown) => string[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rejectedCharactersFromError = void 0;
|
|
4
|
+
const errors_1 = require("@apollo/client/errors");
|
|
5
|
+
const rejectedCharactersOf = (graphqlError) => {
|
|
6
|
+
const extensions = graphqlError.extensions ?? {};
|
|
7
|
+
return extensions.rejectedCharacters;
|
|
8
|
+
};
|
|
9
|
+
const isString = (item) => typeof item === 'string';
|
|
10
|
+
const isCharacterList = (value) => {
|
|
11
|
+
const isNonEmptyArray = Array.isArray(value) && value.length > 0;
|
|
12
|
+
return isNonEmptyArray && value.every(isString);
|
|
13
|
+
};
|
|
14
|
+
const firstCharacterList = (error) => {
|
|
15
|
+
const lists = error.errors.map((graphqlError) => rejectedCharactersOf(graphqlError));
|
|
16
|
+
return lists.find(isCharacterList) ?? [];
|
|
17
|
+
};
|
|
18
|
+
const rejectedCharactersFromError = (error) => (errors_1.CombinedGraphQLErrors.is(error) ? firstCharacterList(error) : []);
|
|
19
|
+
exports.rejectedCharactersFromError = rejectedCharactersFromError;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const SKIP_GLOBAL_ERROR_TOAST = "skipGlobalErrorToast";
|
|
2
|
+
export declare const shouldSkipGlobalErrorToast: (context: Record<string, unknown>) => boolean;
|
|
3
|
+
export type TranslateFunction = (key: string, named?: Record<string, unknown>) => string;
|
|
4
|
+
export declare const SUPPORT_ID_LINE_KEY = "error.supportIdLine";
|
|
5
|
+
export declare const withSupportId: (message: string, supportId: string, translate: TranslateFunction) => string;
|
|
6
|
+
export type DescribeRequestError = (error: unknown, fallbackMessage: string, translate: TranslateFunction) => string;
|
|
7
|
+
export type MessageKeyFromError = (error: unknown) => null | string;
|
|
8
|
+
export declare const createDescribeRequestError: (messageKeyFromError: MessageKeyFromError) => DescribeRequestError;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDescribeRequestError = exports.withSupportId = exports.SUPPORT_ID_LINE_KEY = exports.shouldSkipGlobalErrorToast = exports.SKIP_GLOBAL_ERROR_TOAST = void 0;
|
|
4
|
+
const support_id_from_error_js_1 = require("./support-id-from-error.js");
|
|
5
|
+
exports.SKIP_GLOBAL_ERROR_TOAST = 'skipGlobalErrorToast';
|
|
6
|
+
const shouldSkipGlobalErrorToast = (context) => {
|
|
7
|
+
const skipFlag = context[exports.SKIP_GLOBAL_ERROR_TOAST];
|
|
8
|
+
return skipFlag === true;
|
|
9
|
+
};
|
|
10
|
+
exports.shouldSkipGlobalErrorToast = shouldSkipGlobalErrorToast;
|
|
11
|
+
exports.SUPPORT_ID_LINE_KEY = 'error.supportIdLine';
|
|
12
|
+
const withSupportId = (message, supportId, translate) => (supportId === '' ? message : `${message}\n${translate(exports.SUPPORT_ID_LINE_KEY, { id: supportId })}`);
|
|
13
|
+
exports.withSupportId = withSupportId;
|
|
14
|
+
const createDescribeRequestError = (messageKeyFromError) => (error, fallbackMessage, translate) => {
|
|
15
|
+
const messageKey = messageKeyFromError(error);
|
|
16
|
+
const message = messageKey === null ? fallbackMessage : translate(messageKey);
|
|
17
|
+
return (0, exports.withSupportId)(message, (0, support_id_from_error_js_1.supportIdFromError)(error), translate);
|
|
18
|
+
};
|
|
19
|
+
exports.createDescribeRequestError = createDescribeRequestError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const supportIdFromError: (error: unknown) => string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.supportIdFromError = void 0;
|
|
4
|
+
const errors_1 = require("@apollo/client/errors");
|
|
5
|
+
const supportIdOf = (graphqlError) => {
|
|
6
|
+
const extensions = graphqlError.extensions ?? {};
|
|
7
|
+
return extensions.supportId;
|
|
8
|
+
};
|
|
9
|
+
const isNonEmptyString = (value) => typeof value === 'string' && value !== '';
|
|
10
|
+
const supportIdFromError = (error) => (errors_1.CombinedGraphQLErrors.is(error)
|
|
11
|
+
? error.errors.map((graphqlError) => supportIdOf(graphqlError)).find(isNonEmptyString) ?? ''
|
|
12
|
+
: '');
|
|
13
|
+
exports.supportIdFromError = supportIdFromError;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GraphQLErrorExtensions } from 'graphql';
|
|
2
|
+
export declare const BUSINESS_GRAPHQL_ERROR_CODES: readonly ["BAD_USER_INPUT", "FORBIDDEN", "NOT_FOUND"];
|
|
3
|
+
export type BusinessGraphQLErrorCode = (typeof BUSINESS_GRAPHQL_ERROR_CODES)[number];
|
|
4
|
+
export declare const INTERNAL_SERVER_ERROR_CODE = "INTERNAL_SERVER_ERROR";
|
|
5
|
+
export type GraphQLErrorWireExtensions = {
|
|
6
|
+
code?: string;
|
|
7
|
+
messageCode?: string;
|
|
8
|
+
rejectedCharacters?: string[];
|
|
9
|
+
statusCode?: number;
|
|
10
|
+
supportId?: string;
|
|
11
|
+
validationErrors?: GraphQLValidationFieldErrorInterface[];
|
|
12
|
+
} & GraphQLErrorExtensions;
|
|
13
|
+
interface GraphQLValidationFieldErrorInterface {
|
|
14
|
+
constraints: string[];
|
|
15
|
+
property: string;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.INTERNAL_SERVER_ERROR_CODE = exports.BUSINESS_GRAPHQL_ERROR_CODES = void 0;
|
|
4
|
+
exports.BUSINESS_GRAPHQL_ERROR_CODES = ['BAD_USER_INPUT', 'FORBIDDEN', 'NOT_FOUND'];
|
|
5
|
+
exports.INTERNAL_SERVER_ERROR_CODE = 'INTERNAL_SERVER_ERROR';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './graphql-error-contract.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./graphql-error-contract.js"), exports);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addSupportIdToGraphQLError = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
const nullable = (value) => value ?? null;
|
|
6
|
+
const addSupportIdToGraphQLError = (gqlError, supportId) => {
|
|
7
|
+
if (supportId === '') {
|
|
8
|
+
return gqlError;
|
|
9
|
+
}
|
|
10
|
+
const { extensions, message, nodes, originalError, path, positions, source } = gqlError;
|
|
11
|
+
const extensionsWithSupportId = { ...extensions, supportId };
|
|
12
|
+
return new graphql_1.GraphQLError(message, {
|
|
13
|
+
extensions: extensionsWithSupportId,
|
|
14
|
+
nodes: nullable(nodes),
|
|
15
|
+
originalError: nullable(originalError),
|
|
16
|
+
path: nullable(path),
|
|
17
|
+
positions: nullable(positions),
|
|
18
|
+
source: nullable(source),
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
exports.addSupportIdToGraphQLError = addSupportIdToGraphQLError;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { GraphQLError } from 'graphql';
|
|
2
|
+
import type { BusinessGraphQLErrorCode, GraphQLErrorWireExtensions } from '../contract/graphql-error-contract.js';
|
|
3
|
+
export declare class BusinessGraphQLError<TMessageCode extends string> extends GraphQLError {
|
|
4
|
+
constructor(message: string, code: BusinessGraphQLErrorCode, messageCode: TMessageCode, extensions?: GraphQLErrorWireExtensions);
|
|
5
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BusinessGraphQLError = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
class BusinessGraphQLError extends graphql_1.GraphQLError {
|
|
6
|
+
constructor(message, code, messageCode, extensions) {
|
|
7
|
+
super(message, { extensions: { ...extensions, code, messageCode } });
|
|
8
|
+
this.name = 'BusinessGraphQLError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.BusinessGraphQLError = BusinessGraphQLError;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatGraphQLError = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const add_support_id_to_graphql_error_js_1 = require("./add-support-id-to-graphql-error.js");
|
|
6
|
+
const is_business_graphql_error_js_1 = require("./is-business-graphql-error.js");
|
|
7
|
+
const map_http_exception_to_graphql_error_js_1 = require("./map-http-exception-to-graphql-error.js");
|
|
8
|
+
const formatGraphQLError = (gqlError, supportId) => {
|
|
9
|
+
const { originalError } = gqlError;
|
|
10
|
+
const mappedError = originalError instanceof common_1.HttpException
|
|
11
|
+
? (0, map_http_exception_to_graphql_error_js_1.mapHttpExceptionToGraphQLError)(gqlError, originalError)
|
|
12
|
+
: gqlError;
|
|
13
|
+
return (0, is_business_graphql_error_js_1.isBusinessGraphQLError)(mappedError)
|
|
14
|
+
? mappedError
|
|
15
|
+
: (0, add_support_id_to_graphql_error_js_1.addSupportIdToGraphQLError)(mappedError, supportId);
|
|
16
|
+
};
|
|
17
|
+
exports.formatGraphQLError = formatGraphQLError;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './add-support-id-to-graphql-error.js';
|
|
2
|
+
export * from './business-graphql-error.js';
|
|
3
|
+
export * from './format-graphql-error.js';
|
|
4
|
+
export * from './is-business-graphql-error.js';
|
|
5
|
+
export * from './map-http-exception-to-graphql-error.js';
|
|
6
|
+
export * from './match-business-error.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./add-support-id-to-graphql-error.js"), exports);
|
|
18
|
+
__exportStar(require("./business-graphql-error.js"), exports);
|
|
19
|
+
__exportStar(require("./format-graphql-error.js"), exports);
|
|
20
|
+
__exportStar(require("./is-business-graphql-error.js"), exports);
|
|
21
|
+
__exportStar(require("./map-http-exception-to-graphql-error.js"), exports);
|
|
22
|
+
__exportStar(require("./match-business-error.js"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isBusinessGraphQLError = void 0;
|
|
4
|
+
const graphql_error_contract_js_1 = require("../contract/graphql-error-contract.js");
|
|
5
|
+
const CLIENT_ERROR_MIN_STATUS = 400;
|
|
6
|
+
const SERVER_ERROR_MIN_STATUS = 500;
|
|
7
|
+
const BUSINESS_ERROR_CODES = new Set(graphql_error_contract_js_1.BUSINESS_GRAPHQL_ERROR_CODES);
|
|
8
|
+
const isBusinessGraphQLError = (error) => {
|
|
9
|
+
const { code, statusCode } = error.extensions;
|
|
10
|
+
return typeof statusCode === 'number'
|
|
11
|
+
? statusCode >= CLIENT_ERROR_MIN_STATUS && statusCode < SERVER_ERROR_MIN_STATUS
|
|
12
|
+
: typeof code === 'string' && BUSINESS_ERROR_CODES.has(code);
|
|
13
|
+
};
|
|
14
|
+
exports.isBusinessGraphQLError = isBusinessGraphQLError;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapHttpExceptionToGraphQLError = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
const isRecord = (value) => typeof value === 'object' && value !== null;
|
|
7
|
+
const nullable = (value) => value ?? null;
|
|
8
|
+
const mapHttpExceptionToGraphQLError = (gqlError, originalError) => {
|
|
9
|
+
const { extensions, nodes, path, positions, source } = gqlError;
|
|
10
|
+
const response = originalError.getResponse();
|
|
11
|
+
const payload = isRecord(response) ? response : { message: response };
|
|
12
|
+
const message = typeof payload.message === 'string' ? payload.message : gqlError.message;
|
|
13
|
+
const code = Array.isArray(payload.validationErrors) ? common_1.UnprocessableEntityException.name : common_1.HttpException.name;
|
|
14
|
+
const extensionsOnWire = {
|
|
15
|
+
...extensions,
|
|
16
|
+
...payload,
|
|
17
|
+
code,
|
|
18
|
+
statusCode: originalError.getStatus(),
|
|
19
|
+
};
|
|
20
|
+
return new graphql_1.GraphQLError(message, {
|
|
21
|
+
extensions: extensionsOnWire,
|
|
22
|
+
nodes: nullable(nodes),
|
|
23
|
+
originalError,
|
|
24
|
+
path: nullable(path),
|
|
25
|
+
positions: nullable(positions),
|
|
26
|
+
source: nullable(source),
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
exports.mapHttpExceptionToGraphQLError = mapHttpExceptionToGraphQLError;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BusinessGraphQLErrorCode } from '../contract/graphql-error-contract.js';
|
|
2
|
+
export interface BusinessErrorOptionsInterface<TMessageCode extends string> {
|
|
3
|
+
code: BusinessGraphQLErrorCode;
|
|
4
|
+
messageCode: TMessageCode;
|
|
5
|
+
}
|
|
6
|
+
export type BusinessErrorTable<TOptions> = readonly [new (...arguments_: never[]) => Error, TOptions][];
|
|
7
|
+
export declare const matchBusinessError: <TOptions>(table: BusinessErrorTable<TOptions>, fallback: TOptions) => (commandError: Error) => TOptions;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.matchBusinessError = void 0;
|
|
4
|
+
const matchBusinessError = (table, fallback) => (commandError) => {
|
|
5
|
+
const matched = table.find(([errorClass]) => commandError instanceof errorClass);
|
|
6
|
+
return matched?.[1] ?? fallback;
|
|
7
|
+
};
|
|
8
|
+
exports.matchBusinessError = matchBusinessError;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./contract/index.js"), exports);
|
|
18
|
+
__exportStar(require("./errors/index.js"), exports);
|
|
19
|
+
__exportStar(require("./listing/index.js"), exports);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CursorOutputType = void 0;
|
|
13
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
14
|
+
let CursorOutputType = class CursorOutputType {
|
|
15
|
+
next;
|
|
16
|
+
prev;
|
|
17
|
+
};
|
|
18
|
+
exports.CursorOutputType = CursorOutputType;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, graphql_1.Field)(() => String, { nullable: true }),
|
|
21
|
+
__metadata("design:type", Object)
|
|
22
|
+
], CursorOutputType.prototype, "next", void 0);
|
|
23
|
+
__decorate([
|
|
24
|
+
(0, graphql_1.Field)(() => String, { nullable: true }),
|
|
25
|
+
__metadata("design:type", Object)
|
|
26
|
+
], CursorOutputType.prototype, "prev", void 0);
|
|
27
|
+
exports.CursorOutputType = CursorOutputType = __decorate([
|
|
28
|
+
(0, graphql_1.ObjectType)()
|
|
29
|
+
], CursorOutputType);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.FilterInputType = void 0;
|
|
13
|
+
const listing_1 = require("@application-kit/typeorm/listing");
|
|
14
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
15
|
+
(0, graphql_1.registerEnumType)(listing_1.FiltersMatchMode, { name: 'FiltersMatchMode' });
|
|
16
|
+
let FilterInputType = class FilterInputType {
|
|
17
|
+
field;
|
|
18
|
+
matchMode;
|
|
19
|
+
value;
|
|
20
|
+
};
|
|
21
|
+
exports.FilterInputType = FilterInputType;
|
|
22
|
+
__decorate([
|
|
23
|
+
(0, graphql_1.Field)(() => String),
|
|
24
|
+
__metadata("design:type", String)
|
|
25
|
+
], FilterInputType.prototype, "field", void 0);
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, graphql_1.Field)(() => listing_1.FiltersMatchMode),
|
|
28
|
+
__metadata("design:type", String)
|
|
29
|
+
], FilterInputType.prototype, "matchMode", void 0);
|
|
30
|
+
__decorate([
|
|
31
|
+
(0, graphql_1.Field)(() => String),
|
|
32
|
+
__metadata("design:type", String)
|
|
33
|
+
], FilterInputType.prototype, "value", void 0);
|
|
34
|
+
exports.FilterInputType = FilterInputType = __decorate([
|
|
35
|
+
(0, graphql_1.InputType)()
|
|
36
|
+
], FilterInputType);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './cursor-output.type.js';
|
|
2
|
+
export * from './cursor-type.interface.js';
|
|
3
|
+
export * from './filter-input.type.js';
|
|
4
|
+
export * from './listing-payload.js';
|
|
5
|
+
export * from './listing-response.interface.js';
|
|
6
|
+
export * from './paginator-input.type.js';
|
|
7
|
+
export * from './sorting-input.type.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./cursor-output.type.js"), exports);
|
|
18
|
+
__exportStar(require("./cursor-type.interface.js"), exports);
|
|
19
|
+
__exportStar(require("./filter-input.type.js"), exports);
|
|
20
|
+
__exportStar(require("./listing-payload.js"), exports);
|
|
21
|
+
__exportStar(require("./listing-response.interface.js"), exports);
|
|
22
|
+
__exportStar(require("./paginator-input.type.js"), exports);
|
|
23
|
+
__exportStar(require("./sorting-input.type.js"), exports);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FilterInputType } from './filter-input.type.js';
|
|
2
|
+
import { PaginatorInputType } from './paginator-input.type.js';
|
|
3
|
+
import { SortingInputType } from './sorting-input.type.js';
|
|
4
|
+
export declare class Payload {
|
|
5
|
+
filters?: FilterInputType[];
|
|
6
|
+
paginator: PaginatorInputType;
|
|
7
|
+
sorting?: SortingInputType[];
|
|
8
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.Payload = void 0;
|
|
13
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
14
|
+
const class_transformer_1 = require("class-transformer");
|
|
15
|
+
const class_validator_1 = require("class-validator");
|
|
16
|
+
const filter_input_type_js_1 = require("./filter-input.type.js");
|
|
17
|
+
const paginator_input_type_js_1 = require("./paginator-input.type.js");
|
|
18
|
+
const sorting_input_type_js_1 = require("./sorting-input.type.js");
|
|
19
|
+
let Payload = class Payload {
|
|
20
|
+
filters = [];
|
|
21
|
+
paginator = new paginator_input_type_js_1.PaginatorInputType();
|
|
22
|
+
sorting = [];
|
|
23
|
+
};
|
|
24
|
+
exports.Payload = Payload;
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, graphql_1.Field)(() => [filter_input_type_js_1.FilterInputType], { nullable: true }),
|
|
27
|
+
__metadata("design:type", Array)
|
|
28
|
+
], Payload.prototype, "filters", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, graphql_1.Field)(() => paginator_input_type_js_1.PaginatorInputType, { nullable: true }),
|
|
31
|
+
(0, class_transformer_1.Type)(() => paginator_input_type_js_1.PaginatorInputType),
|
|
32
|
+
(0, class_validator_1.ValidateNested)(),
|
|
33
|
+
__metadata("design:type", paginator_input_type_js_1.PaginatorInputType)
|
|
34
|
+
], Payload.prototype, "paginator", void 0);
|
|
35
|
+
__decorate([
|
|
36
|
+
(0, graphql_1.Field)(() => [sorting_input_type_js_1.SortingInputType], { nullable: true }),
|
|
37
|
+
__metadata("design:type", Array)
|
|
38
|
+
], Payload.prototype, "sorting", void 0);
|
|
39
|
+
exports.Payload = Payload = __decorate([
|
|
40
|
+
(0, graphql_1.ArgsType)()
|
|
41
|
+
], Payload);
|