@avantstay/graphql-ts-client 12.1.0 → 12.3.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.
@@ -0,0 +1,27 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined")
5
+ return require.apply(this, arguments);
6
+ throw new Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ // src/types.ts
10
+ var GraphQLClientError = class extends Error {
11
+ constructor(responseData) {
12
+ super();
13
+ this.responseData = responseData;
14
+ Object.setPrototypeOf(this, GraphQLClientError.prototype);
15
+ }
16
+ get message() {
17
+ return this.response.errors.map((it) => it.message).join(";\n");
18
+ }
19
+ get response() {
20
+ return this.responseData;
21
+ }
22
+ };
23
+
24
+ export {
25
+ __require,
26
+ GraphQLClientError
27
+ };
package/dist/index.js CHANGED
@@ -487,7 +487,7 @@ var prettier = __toESM(require("prettier"));
487
487
  // package.json
488
488
  var package_default = {
489
489
  name: "@avantstay/graphql-ts-client",
490
- version: "12.1.0",
490
+ version: "12.3.0",
491
491
  description: "GraphQL Typescript Client Generator",
492
492
  homepage: "https://github.com/avantstay/graphql-ts-client",
493
493
  bugs: {
@@ -508,6 +508,16 @@ var package_default = {
508
508
  require: "./dist/index.js",
509
509
  types: "./dist/index.d.ts"
510
510
  },
511
+ "./endpoint": {
512
+ import: "./dist/endpoint.mjs",
513
+ require: "./dist/endpoint.js",
514
+ types: "./dist/endpoint.d.ts"
515
+ },
516
+ "./dist": {
517
+ import: "./dist/index.mjs",
518
+ require: "./dist/index.js",
519
+ types: "./dist/index.d.ts"
520
+ },
511
521
  "./dist/endpoint": {
512
522
  import: "./dist/endpoint.mjs",
513
523
  require: "./dist/endpoint.js",
@@ -581,7 +591,7 @@ var package_default = {
581
591
  };
582
592
  // src/generateTypescriptClient.ts
583
593
  var tempDir = fs.realpathSync(import_os.default.tmpdir());
584
- var graphqlTsClientPath = process.env.GQL_CLIENT_DIST_PATH || "@avantstay/graphql-ts-client/dist";
594
+ var graphqlTsClientPath = process.env.GQL_CLIENT_DIST_PATH || "@avantstay/graphql-ts-client";
585
595
  function gqlScalarToTypescript(gqlType) {
586
596
  if (/(int|long|double|decimal|float)/i.test(gqlType)) return "number";
587
597
  if (/boolean/i.test(gqlType)) return "boolean";
@@ -810,7 +820,7 @@ function generateClientCode(types, options) {
810
820
  selection: false,
811
821
  outputType: "js"
812
822
  });
813
- }).join("\n"), "\n\n // Schema Resolution Tree\n ").concat(getTypesTreeCode(forInputExtraction), "\n\n let verbose = ").concat(Boolean(options.verbose), "\n let headers = {}\n let url = '").concat(options.endpoint, "'\n let retryConfig = {\n max: 0,\n before: undefined,\n waitBeforeRetry: 0\n }\n let requestListeners = []\n let responseListeners = []\n let errorsParser = ").concat(options.errorsParser, "\n // noinspection JSUnusedLocalSymbols\n let apiEndpoint = getApiEndpointCreator({\n getClient: () => ({ url, headers, retryConfig }),\n requestListeners,\n responseListeners,\n maxAge: 30000,\n verbose,\n typesTree,\n formatGraphQL,\n errorsParser\n })\n\n export const ").concat(clientName, " = {\n addRequestListener: (listener) => requestListeners.push(listener),\n addResponseListener: (listener) => responseListeners.push(\n listener),\n setHeader: (key, value) => {\n headers[key] = value\n },\n setHeaders: (newHeaders) => {\n headers = newHeaders\n },\n setRetryConfig: (options) => {\n if (!Number.isInteger(options.max) || options.max < 0) {\n throw new Error('retryOptions.max should be a non-negative integer')\n }\n \n retryConfig = { \n max: options.max,\n waitBeforeRetry: options.waitBeforeRetry,\n before: options.before \n }\n },\n setUrl: (_url) => url = _url,\n queries: {\n ").concat(queries.map(function(query) {
823
+ }).join("\n"), "\n\n // Schema Resolution Tree\n ").concat(getTypesTreeCode(forInputExtraction), "\n\n let verbose = ").concat(Boolean(options.verbose), "\n let headers = {}\n let url = '").concat(options.endpoint, "'\n let retryConfig = {\n max: 0,\n before: undefined,\n waitBeforeRetry: 0\n }\n let requestListeners = []\n let responseListeners = []\n let errorsParser = ").concat(options.errorsParser, "\n // noinspection JSUnusedLocalSymbols\n let apiEndpoint = getApiEndpointCreator({\n getClient: () => ({ url, headers, retryConfig }),\n requestListeners,\n responseListeners,\n maxAge: 30000,\n verbose,\n typesTree,\n formatGraphQL,\n errorsParser\n })\n\n export const ").concat(clientName, " = {\n addRequestListener: (listener) => {\n requestListeners.push(listener)\n return () => {\n const index = requestListeners.indexOf(listener)\n if (index > -1) requestListeners.splice(index, 1)\n }\n },\n removeRequestListener: (listener) => {\n const index = requestListeners.indexOf(listener)\n if (index > -1) requestListeners.splice(index, 1)\n },\n addResponseListener: (listener) => {\n responseListeners.push(listener)\n return () => {\n const index = responseListeners.indexOf(listener)\n if (index > -1) responseListeners.splice(index, 1)\n }\n },\n removeResponseListener: (listener) => {\n const index = responseListeners.indexOf(listener)\n if (index > -1) responseListeners.splice(index, 1)\n },\n setHeader: (key, value) => {\n headers[key] = value\n },\n setHeaders: (newHeaders) => {\n headers = newHeaders\n },\n setRetryConfig: (options) => {\n if (!Number.isInteger(options.max) || options.max < 0) {\n throw new Error('retryOptions.max should be a non-negative integer')\n }\n \n retryConfig = { \n max: options.max,\n waitBeforeRetry: options.waitBeforeRetry,\n before: options.before \n }\n },\n setUrl: (_url) => url = _url,\n queries: {\n ").concat(queries.map(function(query) {
814
824
  return gqlEndpointToCode("query", query, "js");
815
825
  }).join(",\n"), "\n },\n mutations: {\n ").concat(mutations.map(function(mutation) {
816
826
  return gqlEndpointToCode("mutation", mutation, "js");
@@ -842,7 +852,7 @@ function generateClientCode(types, options) {
842
852
  selection: true,
843
853
  outputType: "ts"
844
854
  });
845
- }).join("\n"), "\n \n export declare const ").concat(clientName, ": {\n addRequestListener: (listener: IRequestListener) => void\n addResponseListener: (listener: IResponseListener) => void\n setHeader: (key: string, value: string) => void\n setHeaders: (newHeaders: { [k: string]: string }) => void,\n setUrl: (url: string) => void,\n setRetryConfig: (options: { max: number, waitBeforeRetry?: number, before?: IResponseListener }) => void\n queries: {\n ").concat(queries.map(function(q) {
855
+ }).join("\n"), "\n \n export declare const ").concat(clientName, ": {\n addRequestListener: (listener: IRequestListener) => () => void\n removeRequestListener: (listener: IRequestListener) => void\n addResponseListener: (listener: IResponseListener) => () => void\n removeResponseListener: (listener: IResponseListener) => void\n setHeader: (key: string, value: string) => void\n setHeaders: (newHeaders: { [k: string]: string }) => void,\n setUrl: (url: string) => void,\n setRetryConfig: (options: { max: number, waitBeforeRetry?: number, before?: IResponseListener }) => void\n queries: {\n ").concat(queries.map(function(q) {
846
856
  return gqlEndpointToCode("query", q, "ts");
847
857
  }).join(",\n"), "\n },\n mutations: {\n ").concat(mutations.map(function(q) {
848
858
  return gqlEndpointToCode("mutation", q, "ts");
package/dist/index.mjs CHANGED
@@ -24,7 +24,7 @@ import * as prettier from "prettier";
24
24
  // package.json
25
25
  var package_default = {
26
26
  name: "@avantstay/graphql-ts-client",
27
- version: "12.1.0",
27
+ version: "12.3.0",
28
28
  description: "GraphQL Typescript Client Generator",
29
29
  homepage: "https://github.com/avantstay/graphql-ts-client",
30
30
  bugs: {
@@ -45,6 +45,16 @@ var package_default = {
45
45
  require: "./dist/index.js",
46
46
  types: "./dist/index.d.ts"
47
47
  },
48
+ "./endpoint": {
49
+ import: "./dist/endpoint.mjs",
50
+ require: "./dist/endpoint.js",
51
+ types: "./dist/endpoint.d.ts"
52
+ },
53
+ "./dist": {
54
+ import: "./dist/index.mjs",
55
+ require: "./dist/index.js",
56
+ types: "./dist/index.d.ts"
57
+ },
48
58
  "./dist/endpoint": {
49
59
  import: "./dist/endpoint.mjs",
50
60
  require: "./dist/endpoint.js",
@@ -119,7 +129,7 @@ var package_default = {
119
129
 
120
130
  // src/generateTypescriptClient.ts
121
131
  var tempDir = fs.realpathSync(os.tmpdir());
122
- var graphqlTsClientPath = process.env.GQL_CLIENT_DIST_PATH || "@avantstay/graphql-ts-client/dist";
132
+ var graphqlTsClientPath = process.env.GQL_CLIENT_DIST_PATH || "@avantstay/graphql-ts-client";
123
133
  function gqlScalarToTypescript(gqlType) {
124
134
  if (/(int|long|double|decimal|float)/i.test(gqlType))
125
135
  return "number";
@@ -371,9 +381,28 @@ function generateClientCode(types, options) {
371
381
  })
372
382
 
373
383
  export const ${clientName} = {
374
- addRequestListener: (listener) => requestListeners.push(listener),
375
- addResponseListener: (listener) => responseListeners.push(
376
- listener),
384
+ addRequestListener: (listener) => {
385
+ requestListeners.push(listener)
386
+ return () => {
387
+ const index = requestListeners.indexOf(listener)
388
+ if (index > -1) requestListeners.splice(index, 1)
389
+ }
390
+ },
391
+ removeRequestListener: (listener) => {
392
+ const index = requestListeners.indexOf(listener)
393
+ if (index > -1) requestListeners.splice(index, 1)
394
+ },
395
+ addResponseListener: (listener) => {
396
+ responseListeners.push(listener)
397
+ return () => {
398
+ const index = responseListeners.indexOf(listener)
399
+ if (index > -1) responseListeners.splice(index, 1)
400
+ }
401
+ },
402
+ removeResponseListener: (listener) => {
403
+ const index = responseListeners.indexOf(listener)
404
+ if (index > -1) responseListeners.splice(index, 1)
405
+ },
377
406
  setHeader: (key, value) => {
378
407
  headers[key] = value
379
408
  },
@@ -434,8 +463,10 @@ function generateClientCode(types, options) {
434
463
  ${objectTypes.filter((it) => it.name !== "Query").map((it) => gqlSchemaToCode(it, { selection: true, outputType: "ts" })).join("\n")}
435
464
 
436
465
  export declare const ${clientName}: {
437
- addRequestListener: (listener: IRequestListener) => void
438
- addResponseListener: (listener: IResponseListener) => void
466
+ addRequestListener: (listener: IRequestListener) => () => void
467
+ removeRequestListener: (listener: IRequestListener) => void
468
+ addResponseListener: (listener: IResponseListener) => () => void
469
+ removeResponseListener: (listener: IResponseListener) => void
439
470
  setHeader: (key: string, value: string) => void
440
471
  setHeaders: (newHeaders: { [k: string]: string }) => void,
441
472
  setUrl: (url: string) => void,
@@ -9,12 +9,6 @@ type ResponseData = {
9
9
  message: string;
10
10
  }[];
11
11
  };
12
- type RequestListenerInfo = {
13
- queryName: string;
14
- query: string;
15
- variables: any;
16
- };
17
- type IRequestListener = (info: RequestListenerInfo) => void | Promise<void>;
18
12
  type ResponseListenerInfo = {
19
13
  queryName: string;
20
14
  query: string;
@@ -23,8 +17,7 @@ type ResponseListenerInfo = {
23
17
  };
24
18
  type IResponseListener = (info: ResponseListenerInfo) => void | Promise<void>;
25
19
  type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
26
- type Primitive = Date | string | number | boolean | null | undefined;
27
- type Projection<Selection, Base, E = never> = Base extends Array<any> ? ArrayElement<Base> extends Primitive | E ? ArrayElement<Base>[] : Projection<Defined<Selection>, ArrayElement<Base>, E>[] : Base extends Primitive | E ? Selection extends undefined ? Base | undefined : Base : {
20
+ type Projection<Selection, Base, E = never> = Base extends Array<any> ? ArrayElement<Base> extends Date | string | number | boolean | null | undefined | E ? ArrayElement<Base>[] : Projection<Defined<Selection>, ArrayElement<Base>, E>[] : Base extends Date | string | number | boolean | null | E ? Selection extends undefined ? Base | undefined : Base : {
28
21
  [k in keyof Selection & keyof Base]: Selection[k] extends boolean ? Base[k] : Base[k] extends Array<infer A> ? Projection<Defined<Selection[k]>, A, E>[] : Projection<Defined<Selection[k]>, Base[k], E>;
29
22
  };
30
23
  type Unpacked<T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise<infer U> ? U : T;
@@ -66,11 +59,6 @@ type LogInfo = {
66
59
  error?: Error;
67
60
  duration: number;
68
61
  };
69
- type TypescriptClientOutput = {
70
- js: string;
71
- mjs: string;
72
- typings: string;
73
- };
74
62
  declare class GraphQLClientError extends Error {
75
63
  responseData: ResponseData;
76
64
  constructor(responseData: ResponseData);
@@ -78,4 +66,4 @@ declare class GraphQLClientError extends Error {
78
66
  get response(): ResponseData;
79
67
  }
80
68
 
81
- export { ClientConfig as C, Defined as D, Endpoint as E, GraphQLClientError as G, IRequestListener as I, JsonOutput as J, LogInfo as L, Maybe as M, Projection as P, ResponseData as R, TypescriptClientOutput as T, Unpacked as U, RequestListenerInfo as a, ResponseListenerInfo as b, IResponseListener as c, Replacement as d, DeepReplace as e, RawEndpoint as f };
69
+ export { ClientConfig as C, Defined as D, Endpoint as E, GraphQLClientError as G, IResponseListener as I, JsonOutput as J, LogInfo as L, Maybe as M, Projection as P, ResponseData as R, Unpacked as U, ResponseListenerInfo as a, Replacement as b, DeepReplace as c, RawEndpoint as d };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avantstay/graphql-ts-client",
3
- "version": "12.1.0",
3
+ "version": "12.3.0",
4
4
  "description": "GraphQL Typescript Client Generator",
5
5
  "homepage": "https://github.com/avantstay/graphql-ts-client",
6
6
  "bugs": {
@@ -21,6 +21,16 @@
21
21
  "require": "./dist/index.js",
22
22
  "types": "./dist/index.d.ts"
23
23
  },
24
+ "./endpoint": {
25
+ "import": "./dist/endpoint.mjs",
26
+ "require": "./dist/endpoint.js",
27
+ "types": "./dist/endpoint.d.ts"
28
+ },
29
+ "./dist": {
30
+ "import": "./dist/index.mjs",
31
+ "require": "./dist/index.js",
32
+ "types": "./dist/index.d.ts"
33
+ },
24
34
  "./dist/endpoint": {
25
35
  "import": "./dist/endpoint.mjs",
26
36
  "require": "./dist/endpoint.js",
@@ -54,8 +54,32 @@ let apiEndpoint = (0, import_endpoint.getApiEndpointCreator)({
54
54
  errorsParser
55
55
  });
56
56
  const client = {
57
- addRequestListener: (listener) => requestListeners.push(listener),
58
- addResponseListener: (listener) => responseListeners.push(listener),
57
+ addRequestListener: (listener) => {
58
+ requestListeners.push(listener);
59
+ return () => {
60
+ const index = requestListeners.indexOf(listener);
61
+ if (index > -1)
62
+ requestListeners.splice(index, 1);
63
+ };
64
+ },
65
+ removeRequestListener: (listener) => {
66
+ const index = requestListeners.indexOf(listener);
67
+ if (index > -1)
68
+ requestListeners.splice(index, 1);
69
+ },
70
+ addResponseListener: (listener) => {
71
+ responseListeners.push(listener);
72
+ return () => {
73
+ const index = responseListeners.indexOf(listener);
74
+ if (index > -1)
75
+ responseListeners.splice(index, 1);
76
+ };
77
+ },
78
+ removeResponseListener: (listener) => {
79
+ const index = responseListeners.indexOf(listener);
80
+ if (index > -1)
81
+ responseListeners.splice(index, 1);
82
+ },
59
83
  setHeader: (key, value) => {
60
84
  headers[key] = value;
61
85
  },
@@ -105,8 +129,32 @@ let apiEndpoint = getApiEndpointCreator({
105
129
  errorsParser
106
130
  });
107
131
  const client = {
108
- addRequestListener: (listener) => requestListeners.push(listener),
109
- addResponseListener: (listener) => responseListeners.push(listener),
132
+ addRequestListener: (listener) => {
133
+ requestListeners.push(listener);
134
+ return () => {
135
+ const index = requestListeners.indexOf(listener);
136
+ if (index > -1)
137
+ requestListeners.splice(index, 1);
138
+ };
139
+ },
140
+ removeRequestListener: (listener) => {
141
+ const index = requestListeners.indexOf(listener);
142
+ if (index > -1)
143
+ requestListeners.splice(index, 1);
144
+ },
145
+ addResponseListener: (listener) => {
146
+ responseListeners.push(listener);
147
+ return () => {
148
+ const index = responseListeners.indexOf(listener);
149
+ if (index > -1)
150
+ responseListeners.splice(index, 1);
151
+ };
152
+ },
153
+ removeResponseListener: (listener) => {
154
+ const index = responseListeners.indexOf(listener);
155
+ if (index > -1)
156
+ responseListeners.splice(index, 1);
157
+ },
110
158
  setHeader: (key, value) => {
111
159
  headers[key] = value;
112
160
  },
@@ -167,8 +215,10 @@ export interface Query {
167
215
  // Selection Types
168
216
 
169
217
  export declare const client: {
170
- addRequestListener: (listener: IRequestListener) => void
171
- addResponseListener: (listener: IResponseListener) => void
218
+ addRequestListener: (listener: IRequestListener) => () => void
219
+ removeRequestListener: (listener: IRequestListener) => void
220
+ addResponseListener: (listener: IResponseListener) => () => void
221
+ removeResponseListener: (listener: IResponseListener) => void
172
222
  setHeader: (key: string, value: string) => void
173
223
  setHeaders: (newHeaders: { [k: string]: string }) => void
174
224
  setUrl: (url: string) => void
@@ -1,11 +1,6 @@
1
1
  // noinspection TypeScriptUnresolvedVariable, ES6UnusedImports, JSUnusedLocalSymbols, TypeScriptCheckImport
2
2
  import { DeepRequired } from "ts-essentials"
3
- import {
4
- Maybe,
5
- IRequestListener,
6
- IResponseListener,
7
- Endpoint,
8
- } from "@avantstay/graphql-ts-client/dist"
3
+ import { Maybe, IResponseListener, Endpoint } from "."
9
4
 
10
5
  // Scalars
11
6
  export type IDate = string | Date
@@ -97,7 +92,6 @@ export interface BookSearchParamsSomeRequiredSelection {
97
92
  }
98
93
 
99
94
  export declare const myApiClient: {
100
- addRequestListener: (listener: IRequestListener) => void
101
95
  addResponseListener: (listener: IResponseListener) => void
102
96
  setHeader: (key: string, value: string) => void
103
97
  setHeaders: (newHeaders: { [k: string]: string }) => void
@@ -26,7 +26,7 @@ __export(exports, {
26
26
  default: () => stdin_default,
27
27
  myApiClient: () => myApiClient
28
28
  });
29
- var import_endpoint = __toModule(require("@avantstay/graphql-ts-client/dist/endpoint"));
29
+ var import_endpoint = __toModule(require("./endpoint"));
30
30
  var import_standalone = __toModule(require("prettier/standalone"));
31
31
  var import_parser_graphql = __toModule(require("prettier/parser-graphql"));
32
32
  const formatGraphQL = (query) => (0, import_standalone.format)(query, { parser: "graphql", plugins: [import_parser_graphql.default] });
@@ -69,12 +69,10 @@ let retryConfig = {
69
69
  before: void 0,
70
70
  waitBeforeRetry: 0
71
71
  };
72
- let requestListeners = [];
73
72
  let responseListeners = [];
74
73
  let errorsParser = void 0;
75
74
  let apiEndpoint = (0, import_endpoint.getApiEndpointCreator)({
76
75
  getClient: () => ({ url, headers, retryConfig }),
77
- requestListeners,
78
76
  responseListeners,
79
77
  maxAge: 3e4,
80
78
  verbose,
@@ -83,7 +81,6 @@ let apiEndpoint = (0, import_endpoint.getApiEndpointCreator)({
83
81
  errorsParser
84
82
  });
85
83
  const myApiClient = {
86
- addRequestListener: (listener) => requestListeners.push(listener),
87
84
  addResponseListener: (listener) => responseListeners.push(listener),
88
85
  setHeader: (key, value) => {
89
86
  headers[key] = value;
@@ -55,8 +55,32 @@ let apiEndpoint = getApiEndpointCreator({
55
55
  errorsParser
56
56
  });
57
57
  const myApiClient = {
58
- addRequestListener: (listener) => requestListeners.push(listener),
59
- addResponseListener: (listener) => responseListeners.push(listener),
58
+ addRequestListener: (listener) => {
59
+ requestListeners.push(listener);
60
+ return () => {
61
+ const index = requestListeners.indexOf(listener);
62
+ if (index > -1)
63
+ requestListeners.splice(index, 1);
64
+ };
65
+ },
66
+ removeRequestListener: (listener) => {
67
+ const index = requestListeners.indexOf(listener);
68
+ if (index > -1)
69
+ requestListeners.splice(index, 1);
70
+ },
71
+ addResponseListener: (listener) => {
72
+ responseListeners.push(listener);
73
+ return () => {
74
+ const index = responseListeners.indexOf(listener);
75
+ if (index > -1)
76
+ responseListeners.splice(index, 1);
77
+ };
78
+ },
79
+ removeResponseListener: (listener) => {
80
+ const index = responseListeners.indexOf(listener);
81
+ if (index > -1)
82
+ responseListeners.splice(index, 1);
83
+ },
60
84
  setHeader: (key, value) => {
61
85
  headers[key] = value;
62
86
  },
@@ -172,6 +172,56 @@ describe('Generated Client', () => {
172
172
  expect(responseData?.response.errors.length).toBeGreaterThan(0)
173
173
  })
174
174
 
175
+ it('removeRequestListener removes a previously added request listener', async () => {
176
+ let callCount = 0
177
+ const listener = () => { callCount++ }
178
+
179
+ client.addRequestListener(listener)
180
+ await client.queries.booksWithoutParams({ title: true })
181
+ expect(callCount).toBe(1)
182
+
183
+ client.removeRequestListener(listener)
184
+ await client.queries.booksWithoutParams({ title: true })
185
+ expect(callCount).toBe(1)
186
+ })
187
+
188
+ it('removeResponseListener removes a previously added response listener', async () => {
189
+ let callCount = 0
190
+ const listener = () => { callCount++ }
191
+
192
+ client.addResponseListener(listener)
193
+ await client.queries.booksWithoutParams({ title: true })
194
+ expect(callCount).toBe(1)
195
+
196
+ client.removeResponseListener(listener)
197
+ await client.queries.booksWithoutParams({ title: true })
198
+ expect(callCount).toBe(1)
199
+ })
200
+
201
+ it('addRequestListener returns an unsubscribe function', async () => {
202
+ let callCount = 0
203
+ const unsubscribe = client.addRequestListener(() => { callCount++ })
204
+
205
+ await client.queries.booksWithoutParams({ title: true })
206
+ expect(callCount).toBe(1)
207
+
208
+ unsubscribe()
209
+ await client.queries.booksWithoutParams({ title: true })
210
+ expect(callCount).toBe(1)
211
+ })
212
+
213
+ it('addResponseListener returns an unsubscribe function', async () => {
214
+ let callCount = 0
215
+ const unsubscribe = client.addResponseListener(() => { callCount++ })
216
+
217
+ await client.queries.booksWithoutParams({ title: true })
218
+ expect(callCount).toBe(1)
219
+
220
+ unsubscribe()
221
+ await client.queries.booksWithoutParams({ title: true })
222
+ expect(callCount).toBe(1)
223
+ })
224
+
175
225
  it('should generate proper code from SDL', () => {
176
226
  const sdlString = `
177
227
  type Query {
@@ -28,7 +28,7 @@ import { TypescriptClientOutput } from './types'
28
28
 
29
29
  const tempDir = fs.realpathSync(os.tmpdir())
30
30
 
31
- const graphqlTsClientPath = process.env.GQL_CLIENT_DIST_PATH || '@avantstay/graphql-ts-client/dist'
31
+ const graphqlTsClientPath = process.env.GQL_CLIENT_DIST_PATH || '@avantstay/graphql-ts-client'
32
32
 
33
33
  function gqlScalarToTypescript(gqlType: string) {
34
34
  if (/(int|long|double|decimal|float)/i.test(gqlType)) return 'number'
@@ -392,9 +392,28 @@ function generateClientCode(types: ReadonlyArray<IntrospectionType>, options: Om
392
392
  })
393
393
 
394
394
  export const ${clientName} = {
395
- addRequestListener: (listener) => requestListeners.push(listener),
396
- addResponseListener: (listener) => responseListeners.push(
397
- listener),
395
+ addRequestListener: (listener) => {
396
+ requestListeners.push(listener)
397
+ return () => {
398
+ const index = requestListeners.indexOf(listener)
399
+ if (index > -1) requestListeners.splice(index, 1)
400
+ }
401
+ },
402
+ removeRequestListener: (listener) => {
403
+ const index = requestListeners.indexOf(listener)
404
+ if (index > -1) requestListeners.splice(index, 1)
405
+ },
406
+ addResponseListener: (listener) => {
407
+ responseListeners.push(listener)
408
+ return () => {
409
+ const index = responseListeners.indexOf(listener)
410
+ if (index > -1) responseListeners.splice(index, 1)
411
+ }
412
+ },
413
+ removeResponseListener: (listener) => {
414
+ const index = responseListeners.indexOf(listener)
415
+ if (index > -1) responseListeners.splice(index, 1)
416
+ },
398
417
  setHeader: (key, value) => {
399
418
  headers[key] = value
400
419
  },
@@ -464,8 +483,10 @@ function generateClientCode(types: ReadonlyArray<IntrospectionType>, options: Om
464
483
  .join('\n')}
465
484
 
466
485
  export declare const ${clientName}: {
467
- addRequestListener: (listener: IRequestListener) => void
468
- addResponseListener: (listener: IResponseListener) => void
486
+ addRequestListener: (listener: IRequestListener) => () => void
487
+ removeRequestListener: (listener: IRequestListener) => void
488
+ addResponseListener: (listener: IResponseListener) => () => void
489
+ removeResponseListener: (listener: IResponseListener) => void
469
490
  setHeader: (key: string, value: string) => void
470
491
  setHeaders: (newHeaders: { [k: string]: string }) => void,
471
492
  setUrl: (url: string) => void,
@@ -1,85 +0,0 @@
1
- type Maybe<T> = null | undefined | T;
2
- type Defined<T> = Exclude<T, undefined>;
3
- type ResponseData = {
4
- data: any;
5
- warnings: any;
6
- headers: any;
7
- status?: number;
8
- errors: {
9
- message: string;
10
- }[];
11
- };
12
- type RequestListenerInfo = {
13
- url: string;
14
- queryName: string;
15
- query: string;
16
- variables: any;
17
- headers: {
18
- [key: string]: string;
19
- };
20
- };
21
- type IRequestListener = (info: RequestListenerInfo) => void | Promise<void>;
22
- type ResponseListenerInfo = {
23
- queryName: string;
24
- query: string;
25
- variables: any;
26
- response: ResponseData;
27
- };
28
- type IResponseListener = (info: ResponseListenerInfo) => void | Promise<void>;
29
- type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
30
- type Primitive = Date | string | number | boolean | null | undefined;
31
- type Projection<Selection, Base, E = never> = Base extends Array<any> ? ArrayElement<Base> extends Primitive | E ? ArrayElement<Base>[] : Projection<Defined<Selection>, ArrayElement<Base>, E>[] : Base extends Primitive | E ? Selection extends undefined ? Base | undefined : Base : {
32
- [k in keyof Selection & keyof Base]: Selection[k] extends boolean ? Base[k] : Base[k] extends Array<infer A> ? Projection<Defined<Selection[k]>, A, E>[] : Projection<Defined<Selection[k]>, Base[k], E>;
33
- };
34
- type Unpacked<T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise<infer U> ? U : T;
35
- type Replacement<M extends [any, any], T> = M extends any ? ([T] extends [M[0]] ? M[1] : never) : never;
36
- type DeepReplace<T, Ignore, M extends [any, any]> = {
37
- [P in keyof T]: T[P] extends M[0] ? T[P] extends Ignore ? T[P] extends object ? DeepReplace<T[P], Ignore, M> : T[P] : Replacement<M, T[P]> : T[P] extends object ? DeepReplace<T[P], Ignore, M> : T[P];
38
- };
39
- type RawEndpoint<I, O, E> = <S extends I>(jsonQuery?: S) => Promise<{
40
- data: Projection<S, O, E>;
41
- errors: any[];
42
- warnings: any[];
43
- headers: any;
44
- status: any;
45
- }>;
46
- type JsonOutput<O, ToBeIgnored> = DeepReplace<O, ToBeIgnored, [string | Date, string]>;
47
- type Endpoint<I, O, E> = (<S extends I>(jsonQuery?: S) => Promise<Projection<S, JsonOutput<O, E>, E>>) & {
48
- memo: <S extends I>(jsonQuery?: S) => Promise<Projection<S, JsonOutput<O, E>, E>>;
49
- memoRaw: RawEndpoint<I, JsonOutput<O, E>, E>;
50
- raw: RawEndpoint<I, JsonOutput<O, E>, E>;
51
- };
52
- type ClientConfig = {
53
- url: string;
54
- headers: {
55
- [key: string]: string;
56
- };
57
- retryConfig: {
58
- max: number;
59
- waitBeforeRetry?: number;
60
- before: IResponseListener;
61
- };
62
- };
63
- type LogInfo = {
64
- query: string;
65
- variables: any;
66
- formatGraphQL: any;
67
- kind: string;
68
- queryName: string;
69
- response?: any;
70
- error?: Error;
71
- duration: number;
72
- };
73
- type TypescriptClientOutput = {
74
- js: string;
75
- mjs: string;
76
- typings: string;
77
- };
78
- declare class GraphQLClientError extends Error {
79
- responseData: ResponseData;
80
- constructor(responseData: ResponseData);
81
- get message(): string;
82
- get response(): ResponseData;
83
- }
84
-
85
- export { ClientConfig as C, Defined as D, Endpoint as E, GraphQLClientError as G, IRequestListener as I, JsonOutput as J, LogInfo as L, Maybe as M, Projection as P, ResponseData as R, TypescriptClientOutput as T, Unpacked as U, RequestListenerInfo as a, ResponseListenerInfo as b, IResponseListener as c, Replacement as d, DeepReplace as e, RawEndpoint as f };