@pcg/graphql-kit 1.0.0-alpha.1 → 1.0.0-alpha.3

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.
@@ -0,0 +1,43 @@
1
+ import { GraphQLError, GraphQLFormattedError } from "graphql";
2
+ import { ApolloError } from "@apollo/client/core";
3
+ import { ErrorResponse } from "@apollo/client/link/error";
4
+
5
+ //#region src/graphql-error-log.d.ts
6
+ declare const getErrorMessages: (error: ErrorResponse | ApolloError) => string[];
7
+ declare const logErrorMessages: (error: ApolloError | ErrorResponse, printStack?: boolean) => void;
8
+ //#endregion
9
+ //#region src/types.d.ts
10
+ interface ErrorStackItem {
11
+ key: string;
12
+ message: string;
13
+ context: Record<string, unknown>;
14
+ stacktrace?: string;
15
+ }
16
+ declare class NestJsGraphQLError extends GraphQLError {
17
+ extensions: {
18
+ context: {
19
+ scope?: string;
20
+ action?: string;
21
+ requestId?: string;
22
+ userId?: string;
23
+ [attributeName: string]: unknown;
24
+ };
25
+ key: string;
26
+ statusCode: number;
27
+ errorStack?: ErrorStackItem[];
28
+ format: 'NESTJS';
29
+ [attributeName: string]: unknown;
30
+ };
31
+ }
32
+ type NestJsGraphQLErrors = readonly NestJsGraphQLError[];
33
+ declare class NestJsApolloError extends ApolloError {
34
+ graphQLErrors: NestJsGraphQLErrors;
35
+ }
36
+ //#endregion
37
+ //#region src/tools.d.ts
38
+ declare const isNestJsApolloError: (err: GraphQLFormattedError) => err is NestJsApolloError;
39
+ declare const isNestJsGraphQLError: (err: GraphQLFormattedError) => err is NestJsGraphQLError;
40
+ declare const getFirstNestJsGraphQLError: (err: GraphQLFormattedError) => NestJsGraphQLError | null;
41
+ //#endregion
42
+ export { ErrorStackItem, NestJsApolloError, NestJsGraphQLError, NestJsGraphQLErrors, getErrorMessages, getFirstNestJsGraphQLError, isNestJsApolloError, isNestJsGraphQLError, logErrorMessages };
43
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,79 @@
1
+ import { GraphQLError, print } from "graphql";
2
+ import { ApolloError } from "@apollo/client/core";
3
+
4
+ //#region src/tools.ts
5
+ const isNestJsApolloError = (err) => {
6
+ return Object.prototype.hasOwnProperty.call(err, "graphQLErrors");
7
+ };
8
+ const isNestJsGraphQLError = (err) => {
9
+ const nestError = err;
10
+ return Boolean(nestError.extensions) && Boolean(nestError.extensions.context);
11
+ };
12
+ const getFirstNestJsGraphQLError = (err) => {
13
+ if (!isNestJsApolloError(err)) return null;
14
+ return err.graphQLErrors[0] ?? null;
15
+ };
16
+
17
+ //#endregion
18
+ //#region src/graphql-error-log.ts
19
+ const getErrorMessages = (error) => {
20
+ const messages = [];
21
+ const { graphQLErrors, networkError } = error;
22
+ const operation = "operation" in error ? error.operation : void 0;
23
+ const stack = "stack" in error ? error.stack : void 0;
24
+ let printedQuery;
25
+ if (operation) printedQuery = print(operation.query);
26
+ if (graphQLErrors) graphQLErrors.forEach((error$1) => {
27
+ if (isNestJsGraphQLError(error$1)) messages.push(`[NestJs GraphQL Error] ${error$1.message} (${error$1.extensions.key})`);
28
+ else messages.push(`[GraphQL Error] ${error$1.message}`);
29
+ if (operation) {
30
+ messages.push(logOperation(printedQuery, error$1.locations));
31
+ if (Object.keys(operation.variables).length) messages.push(`with variables: ${JSON.stringify(operation.variables, null, 2)}`);
32
+ }
33
+ if (isNestJsGraphQLError(error$1)) {
34
+ messages.push(`with context: ${JSON.stringify(error$1.extensions.context, null, 2)}`);
35
+ if (error$1.extensions.errorStack) messages.push(`with stack: ${JSON.stringify(error$1.extensions.errorStack, null, 2)}`);
36
+ }
37
+ });
38
+ if (networkError) messages.push(`[GraphQL Network Error] ${networkError}`);
39
+ if (stack) messages.push(stack);
40
+ return messages;
41
+ };
42
+ const logErrorMessages = (error, printStack = true) => {
43
+ getErrorMessages(error).forEach((message) => {
44
+ const result = /\[([\w ]*)](.*)/.exec(message);
45
+ if (result) {
46
+ const [, tag, msg] = result;
47
+ console.log(`%c${tag}`, "color:white;border-radius:3px;background:#ff4400;font-weight:bold;padding:2px 6px;", msg);
48
+ } else console.log(message);
49
+ });
50
+ if (printStack) {
51
+ let stack = (/* @__PURE__ */ new Error()).stack;
52
+ if (stack == null) return;
53
+ const newLineIndex = stack.indexOf("\n");
54
+ stack = stack.slice(stack.indexOf("\n", newLineIndex + 1));
55
+ console.log(`%c${stack}`, "color:grey;");
56
+ }
57
+ };
58
+ const logOperation = (printedQuery, locations) => {
59
+ const lines = printedQuery.split("\n");
60
+ const l = lines.length;
61
+ const result = lines.slice();
62
+ const lineMap = {};
63
+ for (let i = 0; i < l; i++) lineMap[i] = i;
64
+ if (locations) for (const { line, column } of locations) {
65
+ const index = lineMap[line];
66
+ result.splice(index, 0, "▲".padStart(column, " "));
67
+ for (let i = index + 1; i < l; i++) lineMap[i]++;
68
+ }
69
+ return result.join("\n");
70
+ };
71
+
72
+ //#endregion
73
+ //#region src/types.ts
74
+ var NestJsGraphQLError = class extends GraphQLError {};
75
+ var NestJsApolloError = class extends ApolloError {};
76
+
77
+ //#endregion
78
+ export { NestJsApolloError, NestJsGraphQLError, getErrorMessages, getFirstNestJsGraphQLError, isNestJsApolloError, isNestJsGraphQLError, logErrorMessages };
79
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["messages: string[]","printedQuery: string","error","lineMap: Record<number, number>"],"sources":["../src/tools.ts","../src/graphql-error-log.ts","../src/types.ts"],"sourcesContent":["import { type GraphQLFormattedError } from 'graphql';\n\nimport { type NestJsApolloError, type NestJsGraphQLError } from './types';\n\nexport const isNestJsApolloError = (err: GraphQLFormattedError): err is NestJsApolloError => {\n return Object.prototype.hasOwnProperty.call(err, 'graphQLErrors');\n};\n\nexport const isNestJsGraphQLError = (err: GraphQLFormattedError): err is NestJsGraphQLError => {\n const nestError = err as NestJsGraphQLError;\n return Boolean(nestError.extensions) && Boolean(nestError.extensions.context);\n};\n\nexport const getFirstNestJsGraphQLError = (err: GraphQLFormattedError): NestJsGraphQLError | null => {\n if (!isNestJsApolloError(err)) {\n return null;\n }\n\n return err.graphQLErrors[0] ?? null;\n};\n","import { type ApolloError } from '@apollo/client/core';\nimport { type ErrorResponse } from '@apollo/client/link/error';\nimport { print } from 'graphql';\n\nimport { isNestJsGraphQLError } from './tools';\n\nexport const getErrorMessages = (error: ErrorResponse | ApolloError) => {\n const messages: string[] = [];\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- Safe to use in Apollo Client 3.x\n const { graphQLErrors, networkError } = error;\n const operation = 'operation' in error ? error.operation : undefined;\n const stack = 'stack' in error ? error.stack : undefined;\n let printedQuery: string;\n\n if (operation) {\n printedQuery = print(operation.query);\n }\n\n if (graphQLErrors) {\n graphQLErrors.forEach((error) => {\n if (isNestJsGraphQLError(error)) {\n messages.push(`[NestJs GraphQL Error] ${error.message} (${error.extensions.key})`);\n } else {\n messages.push(`[GraphQL Error] ${error.message}`);\n }\n\n if (operation) {\n messages.push(logOperation(printedQuery, error.locations));\n if (Object.keys(operation.variables).length) {\n messages.push(`with variables: ${JSON.stringify(operation.variables, null, 2)}`);\n }\n }\n\n if (isNestJsGraphQLError(error)) {\n messages.push(`with context: ${JSON.stringify(error.extensions.context, null, 2)}`);\n\n if (error.extensions.errorStack) {\n messages.push(`with stack: ${JSON.stringify(error.extensions.errorStack, null, 2)}`);\n }\n }\n });\n }\n\n if (networkError) {\n messages.push(`[GraphQL Network Error] ${networkError}`);\n }\n\n if (stack) {\n messages.push(stack);\n }\n\n return messages;\n};\n\nexport const logErrorMessages = (error: ApolloError | ErrorResponse, printStack = true) => {\n getErrorMessages(error).forEach((message) => {\n const result = /\\[([\\w ]*)](.*)/.exec(message);\n if (result) {\n const [, tag, msg] = result;\n console.log(`%c${tag}`, 'color:white;border-radius:3px;background:#ff4400;font-weight:bold;padding:2px 6px;', msg);\n } else {\n console.log(message);\n }\n });\n\n if (printStack) {\n let stack = new Error().stack;\n if (stack == null) {\n return;\n }\n\n const newLineIndex = stack.indexOf('\\n');\n stack = stack.slice(stack.indexOf('\\n', newLineIndex + 1));\n console.log(`%c${stack}`, 'color:grey;');\n }\n};\n\ninterface ErrorLocation {\n line: number;\n column: number;\n}\n\nconst logOperation = (printedQuery: string, locations: readonly ErrorLocation[] | undefined) => {\n const lines = printedQuery.split('\\n');\n const l = lines.length;\n const result = lines.slice();\n const lineMap: Record<number, number> = {\n };\n for (let i = 0; i < l; i++) {\n lineMap[i] = i;\n }\n\n if (locations) {\n for (const { line, column } of locations) {\n const index = lineMap[line];\n result.splice(index, 0, '▲'.padStart(column, ' '));\n // Offset remaining lines\n for (let i = index + 1; i < l; i++) {\n lineMap[i]++;\n }\n }\n }\n\n return result.join('\\n');\n};\n","import { ApolloError } from '@apollo/client/core';\nimport { GraphQLError } from 'graphql';\n\nexport interface ErrorStackItem {\n key: string;\n message: string;\n context: Record<string, unknown>;\n stacktrace?: string;\n}\n\nexport class NestJsGraphQLError extends GraphQLError {\n declare extensions: {\n context: {\n scope?: string;\n action?: string;\n requestId?: string;\n userId?: string;\n [attributeName: string]: unknown;\n };\n key: string;\n statusCode: number;\n errorStack?: ErrorStackItem[];\n format: 'NESTJS';\n [attributeName: string]: unknown;\n };\n}\n\nexport type NestJsGraphQLErrors = readonly NestJsGraphQLError[];\n\nexport class NestJsApolloError extends ApolloError {\n declare graphQLErrors: NestJsGraphQLErrors;\n}\n"],"mappings":";;;;AAIA,MAAa,uBAAuB,QAAyD;AAC3F,QAAO,OAAO,UAAU,eAAe,KAAK,KAAK,gBAAgB;;AAGnE,MAAa,wBAAwB,QAA0D;CAC7F,MAAM,YAAY;AAClB,QAAO,QAAQ,UAAU,WAAW,IAAI,QAAQ,UAAU,WAAW,QAAQ;;AAG/E,MAAa,8BAA8B,QAA0D;AACnG,KAAI,CAAC,oBAAoB,IAAI,CAC3B,QAAO;AAGT,QAAO,IAAI,cAAc,MAAM;;;;;ACZjC,MAAa,oBAAoB,UAAuC;CACtE,MAAMA,WAAqB,EAAE;CAE7B,MAAM,EAAE,eAAe,iBAAiB;CACxC,MAAM,YAAY,eAAe,QAAQ,MAAM,YAAY;CAC3D,MAAM,QAAQ,WAAW,QAAQ,MAAM,QAAQ;CAC/C,IAAIC;AAEJ,KAAI,UACF,gBAAe,MAAM,UAAU,MAAM;AAGvC,KAAI,cACF,eAAc,SAAS,YAAU;AAC/B,MAAI,qBAAqBC,QAAM,CAC7B,UAAS,KAAK,0BAA0BA,QAAM,QAAQ,IAAIA,QAAM,WAAW,IAAI,GAAG;MAElF,UAAS,KAAK,mBAAmBA,QAAM,UAAU;AAGnD,MAAI,WAAW;AACb,YAAS,KAAK,aAAa,cAAcA,QAAM,UAAU,CAAC;AAC1D,OAAI,OAAO,KAAK,UAAU,UAAU,CAAC,OACnC,UAAS,KAAK,mBAAmB,KAAK,UAAU,UAAU,WAAW,MAAM,EAAE,GAAG;;AAIpF,MAAI,qBAAqBA,QAAM,EAAE;AAC/B,YAAS,KAAK,iBAAiB,KAAK,UAAUA,QAAM,WAAW,SAAS,MAAM,EAAE,GAAG;AAEnF,OAAIA,QAAM,WAAW,WACnB,UAAS,KAAK,eAAe,KAAK,UAAUA,QAAM,WAAW,YAAY,MAAM,EAAE,GAAG;;GAGxF;AAGJ,KAAI,aACF,UAAS,KAAK,2BAA2B,eAAe;AAG1D,KAAI,MACF,UAAS,KAAK,MAAM;AAGtB,QAAO;;AAGT,MAAa,oBAAoB,OAAoC,aAAa,SAAS;AACzF,kBAAiB,MAAM,CAAC,SAAS,YAAY;EAC3C,MAAM,SAAS,kBAAkB,KAAK,QAAQ;AAC9C,MAAI,QAAQ;GACV,MAAM,GAAG,KAAK,OAAO;AACrB,WAAQ,IAAI,KAAK,OAAO,sFAAsF,IAAI;QAElH,SAAQ,IAAI,QAAQ;GAEtB;AAEF,KAAI,YAAY;EACd,IAAI,yBAAQ,IAAI,OAAO,EAAC;AACxB,MAAI,SAAS,KACX;EAGF,MAAM,eAAe,MAAM,QAAQ,KAAK;AACxC,UAAQ,MAAM,MAAM,MAAM,QAAQ,MAAM,eAAe,EAAE,CAAC;AAC1D,UAAQ,IAAI,KAAK,SAAS,cAAc;;;AAS5C,MAAM,gBAAgB,cAAsB,cAAoD;CAC9F,MAAM,QAAQ,aAAa,MAAM,KAAK;CACtC,MAAM,IAAI,MAAM;CAChB,MAAM,SAAS,MAAM,OAAO;CAC5B,MAAMC,UAAkC,EACvC;AACD,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,SAAQ,KAAK;AAGf,KAAI,UACF,MAAK,MAAM,EAAE,MAAM,YAAY,WAAW;EACxC,MAAM,QAAQ,QAAQ;AACtB,SAAO,OAAO,OAAO,GAAG,IAAI,SAAS,QAAQ,IAAI,CAAC;AAElD,OAAK,IAAI,IAAI,QAAQ,GAAG,IAAI,GAAG,IAC7B,SAAQ;;AAKd,QAAO,OAAO,KAAK,KAAK;;;;;AC7F1B,IAAa,qBAAb,cAAwC,aAAa;AAmBrD,IAAa,oBAAb,cAAuC,YAAY"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pcg/graphql-kit",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.3",
4
4
  "description": "GraphQL utilities and error handling for NestJS Apollo",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -14,6 +14,9 @@
14
14
  "type": "module",
15
15
  "main": "dist/index.js",
16
16
  "types": "dist/index.d.ts",
17
+ "files": [
18
+ "dist"
19
+ ],
17
20
  "dependencies": {
18
21
  "@apollo/client": "^3.13.0",
19
22
  "graphql": "^16.10.0"
@@ -1,4 +0,0 @@
1
-
2
- > @pcg/graphql-kit@1.0.0-alpha.0 lint /Users/vangolenko/node/pcg/packages/graphql-kit
3
- > eslint "src/**/*.ts" --fix
4
-
package/CHANGELOG.md DELETED
@@ -1,7 +0,0 @@
1
- # @pcg/graphql-kit
2
-
3
- ## 1.0.0-alpha.1
4
-
5
- ### Minor Changes
6
-
7
- - Initial release of @pcg/graphql-kit package. GraphQL utilities and error handling for NestJS Apollo.
package/eslint.config.js DELETED
@@ -1,5 +0,0 @@
1
- import deepEslint, { defineConfig } from '@deepvision/eslint-plugin';
2
-
3
- export default defineConfig([
4
- deepEslint.configs.vue,
5
- ]);
@@ -1,105 +0,0 @@
1
- import { type ApolloError } from '@apollo/client/core';
2
- import { type ErrorResponse } from '@apollo/client/link/error';
3
- import { print } from 'graphql';
4
-
5
- import { isNestJsGraphQLError } from './tools';
6
-
7
- export const getErrorMessages = (error: ErrorResponse | ApolloError) => {
8
- const messages: string[] = [];
9
- // eslint-disable-next-line @typescript-eslint/no-deprecated -- Safe to use in Apollo Client 3.x
10
- const { graphQLErrors, networkError } = error;
11
- const operation = 'operation' in error ? error.operation : undefined;
12
- const stack = 'stack' in error ? error.stack : undefined;
13
- let printedQuery: string;
14
-
15
- if (operation) {
16
- printedQuery = print(operation.query);
17
- }
18
-
19
- if (graphQLErrors) {
20
- graphQLErrors.forEach((error) => {
21
- if (isNestJsGraphQLError(error)) {
22
- messages.push(`[NestJs GraphQL Error] ${error.message} (${error.extensions.key})`);
23
- } else {
24
- messages.push(`[GraphQL Error] ${error.message}`);
25
- }
26
-
27
- if (operation) {
28
- messages.push(logOperation(printedQuery, error.locations));
29
- if (Object.keys(operation.variables).length) {
30
- messages.push(`with variables: ${JSON.stringify(operation.variables, null, 2)}`);
31
- }
32
- }
33
-
34
- if (isNestJsGraphQLError(error)) {
35
- messages.push(`with context: ${JSON.stringify(error.extensions.context, null, 2)}`);
36
-
37
- if (error.extensions.errorStack) {
38
- messages.push(`with stack: ${JSON.stringify(error.extensions.errorStack, null, 2)}`);
39
- }
40
- }
41
- });
42
- }
43
-
44
- if (networkError) {
45
- messages.push(`[GraphQL Network Error] ${networkError}`);
46
- }
47
-
48
- if (stack) {
49
- messages.push(stack);
50
- }
51
-
52
- return messages;
53
- };
54
-
55
- export const logErrorMessages = (error: ApolloError | ErrorResponse, printStack = true) => {
56
- getErrorMessages(error).forEach((message) => {
57
- const result = /\[([\w ]*)](.*)/.exec(message);
58
- if (result) {
59
- const [, tag, msg] = result;
60
- console.log(`%c${tag}`, 'color:white;border-radius:3px;background:#ff4400;font-weight:bold;padding:2px 6px;', msg);
61
- } else {
62
- console.log(message);
63
- }
64
- });
65
-
66
- if (printStack) {
67
- let stack = new Error().stack;
68
- if (stack == null) {
69
- return;
70
- }
71
-
72
- const newLineIndex = stack.indexOf('\n');
73
- stack = stack.slice(stack.indexOf('\n', newLineIndex + 1));
74
- console.log(`%c${stack}`, 'color:grey;');
75
- }
76
- };
77
-
78
- interface ErrorLocation {
79
- line: number;
80
- column: number;
81
- }
82
-
83
- const logOperation = (printedQuery: string, locations: readonly ErrorLocation[] | undefined) => {
84
- const lines = printedQuery.split('\n');
85
- const l = lines.length;
86
- const result = lines.slice();
87
- const lineMap: Record<number, number> = {
88
- };
89
- for (let i = 0; i < l; i++) {
90
- lineMap[i] = i;
91
- }
92
-
93
- if (locations) {
94
- for (const { line, column } of locations) {
95
- const index = lineMap[line];
96
- result.splice(index, 0, '▲'.padStart(column, ' '));
97
- // Offset remaining lines
98
- for (let i = index + 1; i < l; i++) {
99
- lineMap[i]++;
100
- }
101
- }
102
- }
103
-
104
- return result.join('\n');
105
- };
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './graphql-error-log';
2
- export * from './tools';
3
- export * from './types';
package/src/tools.ts DELETED
@@ -1,20 +0,0 @@
1
- import { type GraphQLFormattedError } from 'graphql';
2
-
3
- import { type NestJsApolloError, type NestJsGraphQLError } from './types';
4
-
5
- export const isNestJsApolloError = (err: GraphQLFormattedError): err is NestJsApolloError => {
6
- return Object.prototype.hasOwnProperty.call(err, 'graphQLErrors');
7
- };
8
-
9
- export const isNestJsGraphQLError = (err: GraphQLFormattedError): err is NestJsGraphQLError => {
10
- const nestError = err as NestJsGraphQLError;
11
- return Boolean(nestError.extensions) && Boolean(nestError.extensions.context);
12
- };
13
-
14
- export const getFirstNestJsGraphQLError = (err: GraphQLFormattedError): NestJsGraphQLError | null => {
15
- if (!isNestJsApolloError(err)) {
16
- return null;
17
- }
18
-
19
- return err.graphQLErrors[0] ?? null;
20
- };
package/src/types.ts DELETED
@@ -1,32 +0,0 @@
1
- import { ApolloError } from '@apollo/client/core';
2
- import { GraphQLError } from 'graphql';
3
-
4
- export interface ErrorStackItem {
5
- key: string;
6
- message: string;
7
- context: Record<string, unknown>;
8
- stacktrace?: string;
9
- }
10
-
11
- export class NestJsGraphQLError extends GraphQLError {
12
- declare extensions: {
13
- context: {
14
- scope?: string;
15
- action?: string;
16
- requestId?: string;
17
- userId?: string;
18
- [attributeName: string]: unknown;
19
- };
20
- key: string;
21
- statusCode: number;
22
- errorStack?: ErrorStackItem[];
23
- format: 'NESTJS';
24
- [attributeName: string]: unknown;
25
- };
26
- }
27
-
28
- export type NestJsGraphQLErrors = readonly NestJsGraphQLError[];
29
-
30
- export class NestJsApolloError extends ApolloError {
31
- declare graphQLErrors: NestJsGraphQLErrors;
32
- }
@@ -1,219 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { GraphQLError } from 'graphql';
3
- import {
4
- describe,
5
- expect,
6
- it,
7
- vi,
8
- } from 'vitest';
9
-
10
- import {
11
- getErrorMessages,
12
- logErrorMessages,
13
- } from '@/graphql-error-log.js';
14
- import { NestJsGraphQLError } from '@/types.js';
15
-
16
- describe('graphql-error-log', () => {
17
- describe('getErrorMessages', () => {
18
- it('should return empty array for error without graphQLErrors and networkError', () => {
19
- const error: any = {
20
- graphQLErrors: undefined,
21
- networkError: undefined,
22
- };
23
- const messages = getErrorMessages(error);
24
- expect(messages).toEqual([]);
25
- });
26
-
27
- it('should handle graphQLErrors', () => {
28
- const error: any = {
29
- graphQLErrors: [new GraphQLError('Test GraphQL Error')],
30
- networkError: undefined,
31
- };
32
- const messages = getErrorMessages(error);
33
- expect(messages).toContain('[GraphQL Error] Test GraphQL Error');
34
- });
35
-
36
- it('should handle NestJsGraphQLError with key', () => {
37
- const nestError = new NestJsGraphQLError('NestJs Error', {
38
- extensions: {
39
- context: {
40
- userId: '123',
41
- },
42
- key: 'CUSTOM_ERROR',
43
- statusCode: 400,
44
- },
45
- });
46
- const error: any = {
47
- graphQLErrors: [nestError],
48
- networkError: undefined,
49
- };
50
- const messages = getErrorMessages(error);
51
- expect(messages.some((msg: string) => msg.includes('[NestJs GraphQL Error]'))).toBe(true);
52
- expect(messages.some((msg: string) => msg.includes('CUSTOM_ERROR'))).toBe(true);
53
- });
54
-
55
- it('should handle network errors', () => {
56
- const networkError = new Error('Network failure');
57
- const error: any = {
58
- graphQLErrors: undefined,
59
- networkError,
60
- };
61
- const messages = getErrorMessages(error);
62
- expect(messages).toContain('[GraphQL Network Error] Error: Network failure');
63
- });
64
-
65
- it('should handle both graphQLErrors and networkError', () => {
66
- const graphqlError = new GraphQLError('GraphQL Error');
67
- const networkError = new Error('Network Error');
68
- const error: any = {
69
- graphQLErrors: [graphqlError],
70
- networkError,
71
- };
72
- const messages = getErrorMessages(error);
73
- expect(messages.some((msg: string) => msg.includes('GraphQL Error'))).toBe(true);
74
- expect(messages.some((msg: string) => msg.includes('Network Error'))).toBe(true);
75
- });
76
-
77
- it('should handle multiple graphQLErrors', () => {
78
- const error: any = {
79
- graphQLErrors: [
80
- new GraphQLError('Error 1'),
81
- new GraphQLError('Error 2'),
82
- new GraphQLError('Error 3'),
83
- ],
84
- networkError: undefined,
85
- };
86
- const messages = getErrorMessages(error);
87
- expect(messages.filter((msg: string) => msg.includes('[GraphQL Error]')).length).toBe(3);
88
- });
89
-
90
- it('should include context for NestJsGraphQLError', () => {
91
- const nestError = new NestJsGraphQLError('NestJs Error', {
92
- extensions: {
93
- context: {
94
- userId: '123',
95
- scope: 'admin',
96
- },
97
- key: 'AUTH_ERROR',
98
- statusCode: 401,
99
- },
100
- });
101
- const error: any = {
102
- graphQLErrors: [nestError],
103
- networkError: undefined,
104
- };
105
- const messages = getErrorMessages(error);
106
- expect(messages.some((msg: string) => msg.includes('with context'))).toBe(true);
107
- expect(messages.some((msg: string) => msg.includes('userId'))).toBe(true);
108
- });
109
-
110
- it('should include errorStack for NestJsGraphQLError', () => {
111
- const nestError = new NestJsGraphQLError('NestJs Error', {
112
- extensions: {
113
- context: {
114
- userId: '123',
115
- },
116
- key: 'ERROR',
117
- statusCode: 400,
118
- errorStack: [
119
- {
120
- key: 'VALIDATION_ERROR',
121
- message: 'Invalid input',
122
- context: {
123
- field: 'email',
124
- },
125
- },
126
- ],
127
- },
128
- });
129
- const error: any = {
130
- graphQLErrors: [nestError],
131
- networkError: undefined,
132
- };
133
- const messages = getErrorMessages(error);
134
- expect(messages.some((msg: string) => msg.includes('with stack'))).toBe(true);
135
- });
136
- });
137
-
138
- describe('logErrorMessages', () => {
139
- it('should call console.log for each message', () => {
140
- const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
141
- const error: any = {
142
- graphQLErrors: [new GraphQLError('Test Error')],
143
- networkError: undefined,
144
- };
145
-
146
- logErrorMessages(error, false);
147
-
148
- expect(consoleSpy).toHaveBeenCalled();
149
- consoleSpy.mockRestore();
150
- });
151
-
152
- it('should format error tags correctly', () => {
153
- const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
154
- const error: any = {
155
- graphQLErrors: [new GraphQLError('Test Error')],
156
- networkError: undefined,
157
- };
158
-
159
- logErrorMessages(error, false);
160
-
161
- const calls = consoleSpy.mock.calls.map((call: any) => call[0]);
162
- expect(calls.some((call: any) => typeof call === 'string' && call.includes('GraphQL Error'))).toBe(true);
163
-
164
- consoleSpy.mockRestore();
165
- });
166
-
167
- it('should include stack trace when printStack is true', () => {
168
- const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
169
- const error: any = {
170
- graphQLErrors: [new GraphQLError('Test Error')],
171
- networkError: undefined,
172
- };
173
-
174
- logErrorMessages(error, true);
175
-
176
- const calls = consoleSpy.mock.calls;
177
- expect(calls.length).toBeGreaterThan(0);
178
-
179
- consoleSpy.mockRestore();
180
- });
181
-
182
- it('should handle NestJsGraphQLError tags correctly', () => {
183
- const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
184
- const nestError = new NestJsGraphQLError('NestJs Error', {
185
- extensions: {
186
- context: {
187
- },
188
- key: 'CUSTOM_ERROR',
189
- statusCode: 400,
190
- },
191
- });
192
- const error: any = {
193
- graphQLErrors: [nestError],
194
- networkError: undefined,
195
- };
196
-
197
- logErrorMessages(error, false);
198
-
199
- const calls = consoleSpy.mock.calls.map((call: any) => call[0]);
200
- expect(calls.some((call: any) => typeof call === 'string' && call.includes('NestJs GraphQL Error'))).toBe(true);
201
-
202
- consoleSpy.mockRestore();
203
- });
204
-
205
- it('should handle default printStack value', () => {
206
- const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
207
- const error: any = {
208
- graphQLErrors: [new GraphQLError('Test Error')],
209
- networkError: undefined,
210
- };
211
-
212
- logErrorMessages(error);
213
-
214
- expect(consoleSpy).toHaveBeenCalled();
215
-
216
- consoleSpy.mockRestore();
217
- });
218
- });
219
- });
@@ -1,152 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { GraphQLError } from 'graphql';
3
- import {
4
- describe,
5
- expect,
6
- it,
7
- } from 'vitest';
8
-
9
- import {
10
- getFirstNestJsGraphQLError,
11
- isNestJsApolloError,
12
- isNestJsGraphQLError,
13
- } from '@/tools.js';
14
- import { NestJsGraphQLError } from '@/types.js';
15
-
16
- type TestError = GraphQLError | Record<string, unknown>;
17
-
18
- describe('tools', () => {
19
- describe('isNestJsApolloError', () => {
20
- it('should identify apollo errors with graphQLErrors property', () => {
21
- const apolloError: TestError = {
22
- message: 'test',
23
- graphQLErrors: [],
24
- };
25
- expect(isNestJsApolloError(apolloError as any)).toBe(true);
26
- });
27
-
28
- it('should return false for objects without graphQLErrors property', () => {
29
- const notApolloError: TestError = {
30
- message: 'test',
31
- };
32
- expect(isNestJsApolloError(notApolloError as any)).toBe(false);
33
- });
34
-
35
- it('should return true for errors with non-empty graphQLErrors', () => {
36
- const apolloError: TestError = {
37
- message: 'Apollo Error',
38
- graphQLErrors: [new GraphQLError('Internal error')],
39
- };
40
- expect(isNestJsApolloError(apolloError as any)).toBe(true);
41
- });
42
- });
43
-
44
- describe('isNestJsGraphQLError', () => {
45
- it('should identify graphql errors with extensions.context', () => {
46
- const graphqlError: TestError = {
47
- message: 'test',
48
- extensions: {
49
- context: {
50
- },
51
- },
52
- };
53
- expect(isNestJsGraphQLError(graphqlError as any)).toBe(true);
54
- });
55
-
56
- it('should return false for errors without extensions', () => {
57
- const graphqlError: TestError = {
58
- message: 'test',
59
- };
60
- expect(isNestJsGraphQLError(graphqlError as any)).toBe(false);
61
- });
62
-
63
- it('should return false for errors without extensions.context', () => {
64
- const graphqlError: TestError = {
65
- message: 'test',
66
- extensions: {
67
- key: 'VALUE',
68
- },
69
- };
70
- expect(isNestJsGraphQLError(graphqlError as any)).toBe(false);
71
- });
72
-
73
- it('should return true for errors with context and additional properties', () => {
74
- const graphqlError: TestError = {
75
- message: 'test',
76
- extensions: {
77
- context: {
78
- scope: 'user',
79
- action: 'login',
80
- requestId: '123',
81
- },
82
- key: 'UNAUTHORIZED',
83
- statusCode: 401,
84
- },
85
- };
86
- expect(isNestJsGraphQLError(graphqlError as any)).toBe(true);
87
- });
88
-
89
- it('should handle errors with null context', () => {
90
- const graphqlError: TestError = {
91
- message: 'test',
92
- extensions: {
93
- context: null,
94
- },
95
- };
96
- expect(isNestJsGraphQLError(graphqlError as any)).toBe(false);
97
- });
98
- });
99
-
100
- describe('getFirstNestJsGraphQLError', () => {
101
- it('should return null if error is not apollo error', () => {
102
- const error: TestError = {
103
- message: 'test',
104
- };
105
- expect(getFirstNestJsGraphQLError(error as any)).toBeNull();
106
- });
107
-
108
- it('should return null if graphQLErrors is empty', () => {
109
- const error: TestError = {
110
- message: 'test',
111
- graphQLErrors: [],
112
- };
113
- expect(getFirstNestJsGraphQLError(error as any)).toBeNull();
114
- });
115
-
116
- it('should return first graphql error from apollo error', () => {
117
- const firstError = new GraphQLError('First error');
118
- const secondError = new GraphQLError('Second error');
119
- const error: TestError = {
120
- message: 'Apollo Error',
121
- graphQLErrors: [firstError, secondError],
122
- };
123
- expect(getFirstNestJsGraphQLError(error as any)).toBe(firstError);
124
- });
125
-
126
- it('should return single graphql error from apollo error', () => {
127
- const error = new GraphQLError('Single error');
128
- const apolloError: TestError = {
129
- message: 'Apollo Error',
130
- graphQLErrors: [error],
131
- };
132
- expect(getFirstNestJsGraphQLError(apolloError as any)).toBe(error);
133
- });
134
-
135
- it('should handle NestJsGraphQLError specifically', () => {
136
- const nestError = new NestJsGraphQLError('NestJs error', {
137
- extensions: {
138
- context: {
139
- userId: '123',
140
- },
141
- key: 'CUSTOM_ERROR',
142
- statusCode: 400,
143
- },
144
- });
145
- const apolloError: TestError = {
146
- message: 'Apollo Error',
147
- graphQLErrors: [nestError],
148
- };
149
- expect(getFirstNestJsGraphQLError(apolloError as any)).toBe(nestError);
150
- });
151
- });
152
- });
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "moduleResolution": "bundler",
6
- },
7
- "include": ["src/**/*.ts", "tests/**/*.ts"],
8
- "exclude": ["node_modules", "dist"],
9
- }
package/tsconfig.lib.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "moduleResolution": "bundler",
6
- },
7
- "include": ["src/**/*.ts"],
8
- "exclude": ["node_modules", "dist"],
9
- }
package/tsdown.config.ts DELETED
@@ -1,11 +0,0 @@
1
- import { defineConfig } from 'tsdown';
2
-
3
- export default defineConfig({
4
- entry: ['src/index.ts'],
5
- tsconfig: '../../tsconfig.build.json',
6
- outDir: 'dist',
7
- dts: true,
8
- clean: true,
9
- sourcemap: true,
10
- format: 'esm',
11
- });
package/vitest.config.ts DELETED
@@ -1,19 +0,0 @@
1
- // / <reference types="vitest" />
2
- // eslint-disable-next-line node/no-unpublished-import
3
- import { defineConfig } from 'vitest/config';
4
-
5
- export default defineConfig({
6
- test: {
7
- environment: 'node',
8
- include: ['tests/**/*.test.ts'],
9
- globals: true,
10
- typecheck: {
11
- tsconfig: './tsconfig.json',
12
- },
13
- },
14
- resolve: {
15
- alias: {
16
- '@': new URL('./src', import.meta.url).pathname,
17
- },
18
- },
19
- });