@naturalcycles/js-lib 14.266.0 → 14.267.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.
@@ -118,10 +118,21 @@ class Fetcher {
118
118
  * @experimental
119
119
  */
120
120
  async queryGraphQL(opt) {
121
- opt.json = {
121
+ opt.method ||= this.cfg.init.method; // defaults to GET
122
+ const payload = (0, object_util_1._filterFalsyValues)({
122
123
  query: opt.query,
123
124
  variables: opt.variables,
124
- };
125
+ });
126
+ // Checking the query length, and not allowing to use GET if above 1900
127
+ if (opt.method === 'GET' && opt.query.length < 1900) {
128
+ opt.searchParams = {
129
+ ...opt.searchParams,
130
+ ...payload,
131
+ };
132
+ }
133
+ else {
134
+ opt.json = payload;
135
+ }
125
136
  const res = await this.doFetch(opt);
126
137
  if (res.err) {
127
138
  throw res.err;
@@ -131,6 +142,7 @@ class Fetcher {
131
142
  const err = res.body.errors[0];
132
143
  // todo: consider creating a new GraphQLError class for this
133
144
  throw new error_util_1.HttpRequestError(err.message, {
145
+ ...payload, // query and variables
134
146
  errors: res.body.errors, // full errors payload returned
135
147
  response: res.fetchResponse,
136
148
  responseStatusCode: res.statusCode,
@@ -141,7 +153,11 @@ class Fetcher {
141
153
  requestDuration: Date.now() - res.req.started,
142
154
  });
143
155
  }
144
- return res.body.data;
156
+ const { data } = res.body;
157
+ if (opt.unwrapObject) {
158
+ return data[opt.unwrapObject];
159
+ }
160
+ return data;
145
161
  }
146
162
  // responseType=readableStream
147
163
  /**
@@ -119,6 +119,18 @@ export interface FetcherRequest extends Omit<FetcherOptions, 'method' | 'headers
119
119
  export interface FetcherGraphQLOptions extends FetcherOptions {
120
120
  query: string;
121
121
  variables?: AnyObject;
122
+ /**
123
+ * When querying singular entities, it may be convenient to specify 1st level object to unwrap.
124
+ * Example:
125
+ * {
126
+ * homePage: { ... }
127
+ * }
128
+ *
129
+ * unwrapObject: 'homePage'
130
+ *
131
+ * would return the contents of `{ ... }`
132
+ */
133
+ unwrapObject?: string;
122
134
  }
123
135
  export interface FetcherOptions {
124
136
  method?: HttpMethod;
@@ -6,7 +6,7 @@ import { isServerSide } from '../env';
6
6
  import { _assertErrorClassOrRethrow, _assertIsError } from '../error/assert';
7
7
  import { _anyToError, _anyToErrorObject, _errorDataAppend, _errorLikeToErrorObject, HttpRequestError, TimeoutError, UnexpectedPassError, } from '../error/error.util';
8
8
  import { _clamp } from '../number/number.util';
9
- import { _filterNullishValues, _filterUndefinedValues, _mapKeys, _merge, _omit, _pick, } from '../object/object.util';
9
+ import { _filterFalsyValues, _filterNullishValues, _filterUndefinedValues, _mapKeys, _merge, _omit, _pick, } from '../object/object.util';
10
10
  import { pDelay } from '../promise/pDelay';
11
11
  import { pTimeout } from '../promise/pTimeout';
12
12
  import { _jsonParse, _jsonParseIfPossible } from '../string/json.util';
@@ -111,10 +111,21 @@ export class Fetcher {
111
111
  * @experimental
112
112
  */
113
113
  async queryGraphQL(opt) {
114
- opt.json = {
114
+ opt.method || (opt.method = this.cfg.init.method); // defaults to GET
115
+ const payload = _filterFalsyValues({
115
116
  query: opt.query,
116
117
  variables: opt.variables,
117
- };
118
+ });
119
+ // Checking the query length, and not allowing to use GET if above 1900
120
+ if (opt.method === 'GET' && opt.query.length < 1900) {
121
+ opt.searchParams = {
122
+ ...opt.searchParams,
123
+ ...payload,
124
+ };
125
+ }
126
+ else {
127
+ opt.json = payload;
128
+ }
118
129
  const res = await this.doFetch(opt);
119
130
  if (res.err) {
120
131
  throw res.err;
@@ -124,6 +135,7 @@ export class Fetcher {
124
135
  const err = res.body.errors[0];
125
136
  // todo: consider creating a new GraphQLError class for this
126
137
  throw new HttpRequestError(err.message, {
138
+ ...payload, // query and variables
127
139
  errors: res.body.errors, // full errors payload returned
128
140
  response: res.fetchResponse,
129
141
  responseStatusCode: res.statusCode,
@@ -134,7 +146,11 @@ export class Fetcher {
134
146
  requestDuration: Date.now() - res.req.started,
135
147
  });
136
148
  }
137
- return res.body.data;
149
+ const { data } = res.body;
150
+ if (opt.unwrapObject) {
151
+ return data[opt.unwrapObject];
152
+ }
153
+ return data;
138
154
  }
139
155
  // responseType=readableStream
140
156
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.266.0",
3
+ "version": "14.267.0",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "build": "dev-lib build-esm-cjs",
@@ -155,6 +155,18 @@ export interface FetcherRequest
155
155
  export interface FetcherGraphQLOptions extends FetcherOptions {
156
156
  query: string
157
157
  variables?: AnyObject
158
+ /**
159
+ * When querying singular entities, it may be convenient to specify 1st level object to unwrap.
160
+ * Example:
161
+ * {
162
+ * homePage: { ... }
163
+ * }
164
+ *
165
+ * unwrapObject: 'homePage'
166
+ *
167
+ * would return the contents of `{ ... }`
168
+ */
169
+ unwrapObject?: string
158
170
  }
159
171
 
160
172
  export interface FetcherOptions {
@@ -16,6 +16,7 @@ import {
16
16
  } from '../error/error.util'
17
17
  import { _clamp } from '../number/number.util'
18
18
  import {
19
+ _filterFalsyValues,
19
20
  _filterNullishValues,
20
21
  _filterUndefinedValues,
21
22
  _mapKeys,
@@ -28,7 +29,7 @@ import { pTimeout } from '../promise/pTimeout'
28
29
  import { _jsonParse, _jsonParseIfPossible } from '../string/json.util'
29
30
  import { _stringify } from '../string/stringify'
30
31
  import { _ms, _since } from '../time/time.util'
31
- import { ErrorDataTuple, NumberOfMilliseconds, UnixTimestampMillis } from '../types'
32
+ import { AnyObject, ErrorDataTuple, NumberOfMilliseconds, UnixTimestampMillis } from '../types'
32
33
  import {
33
34
  FetcherAfterResponseHook,
34
35
  FetcherBeforeRequestHook,
@@ -185,9 +186,21 @@ export class Fetcher {
185
186
  * @experimental
186
187
  */
187
188
  async queryGraphQL<T = unknown>(opt: FetcherGraphQLOptions): Promise<T> {
188
- opt.json = {
189
+ opt.method ||= this.cfg.init.method // defaults to GET
190
+
191
+ const payload: AnyObject = _filterFalsyValues({
189
192
  query: opt.query,
190
193
  variables: opt.variables,
194
+ })
195
+
196
+ // Checking the query length, and not allowing to use GET if above 1900
197
+ if (opt.method === 'GET' && opt.query.length < 1900) {
198
+ opt.searchParams = {
199
+ ...opt.searchParams,
200
+ ...payload,
201
+ }
202
+ } else {
203
+ opt.json = payload
191
204
  }
192
205
 
193
206
  const res = await this.doFetch<GraphQLResponse<T>>(opt)
@@ -201,6 +214,7 @@ export class Fetcher {
201
214
 
202
215
  // todo: consider creating a new GraphQLError class for this
203
216
  throw new HttpRequestError(err.message, {
217
+ ...payload, // query and variables
204
218
  errors: res.body.errors, // full errors payload returned
205
219
  response: res.fetchResponse,
206
220
  responseStatusCode: res.statusCode,
@@ -212,7 +226,12 @@ export class Fetcher {
212
226
  })
213
227
  }
214
228
 
215
- return res.body.data
229
+ const { data } = res.body
230
+ if (opt.unwrapObject) {
231
+ return (data as any)[opt.unwrapObject]
232
+ }
233
+
234
+ return data
216
235
  }
217
236
 
218
237
  // responseType=readableStream