@naturalcycles/js-lib 14.265.0 → 14.266.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/dist/bot.js +1 -1
- package/dist/http/fetcher.d.ts +13 -1
- package/dist/http/fetcher.js +37 -0
- package/dist/http/fetcher.model.d.ts +20 -0
- package/dist-esm/bot.js +1 -1
- package/dist-esm/http/fetcher.js +37 -0
- package/package.json +1 -1
- package/src/bot.ts +1 -1
- package/src/http/fetcher.model.ts +25 -0
- package/src/http/fetcher.ts +45 -1
package/dist/bot.js
CHANGED
|
@@ -64,7 +64,7 @@ class BotDetectionService {
|
|
|
64
64
|
// if (userAgent.includes('Chrome') && !(globalThis as any).chrome) {
|
|
65
65
|
// return BotReason.ChromeWithoutChrome // Headless Chrome
|
|
66
66
|
// }
|
|
67
|
-
if (this.cfg.treatCDPAsBotReason && this.
|
|
67
|
+
if (this.cfg.treatCDPAsBotReason && this.isCDP()) {
|
|
68
68
|
return BotReason.CDP;
|
|
69
69
|
}
|
|
70
70
|
return null;
|
package/dist/http/fetcher.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/// <reference lib="dom.iterable" preserve="true" />
|
|
4
4
|
import { HttpRequestError } from '../error/error.util';
|
|
5
5
|
import { ErrorDataTuple } from '../types';
|
|
6
|
-
import
|
|
6
|
+
import { FetcherAfterResponseHook, FetcherBeforeRequestHook, FetcherBeforeRetryHook, FetcherCfg, FetcherGraphQLOptions, FetcherNormalizedCfg, FetcherOnErrorHook, FetcherOptions, FetcherResponse, RequestInitNormalized } from './fetcher.model';
|
|
7
7
|
/**
|
|
8
8
|
* Experimental wrapper around Fetch.
|
|
9
9
|
* Works in both Browser and Node, using `globalThis.fetch`.
|
|
@@ -43,6 +43,18 @@ export declare class Fetcher {
|
|
|
43
43
|
patchVoid: (url: string, opt?: FetcherOptions) => Promise<void>;
|
|
44
44
|
deleteVoid: (url: string, opt?: FetcherOptions) => Promise<void>;
|
|
45
45
|
headVoid: (url: string, opt?: FetcherOptions) => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Small convenience wrapper that allows to issue GraphQL queries.
|
|
48
|
+
* In practice, all it does is:
|
|
49
|
+
* - Defines convenience `query` input option
|
|
50
|
+
* - Unwraps `response.data`
|
|
51
|
+
* - Unwraps `response.errors` and throws, if it's defined (as GQL famously returns http 200 even for errors)
|
|
52
|
+
*
|
|
53
|
+
* Currently it only unwraps and uses the first error from the `errors` array, for simplicity.
|
|
54
|
+
*
|
|
55
|
+
* @experimental
|
|
56
|
+
*/
|
|
57
|
+
queryGraphQL<T = unknown>(opt: FetcherGraphQLOptions): Promise<T>;
|
|
46
58
|
/**
|
|
47
59
|
* Returns raw fetchResponse.body, which is a ReadableStream<Uint8Array>
|
|
48
60
|
*
|
package/dist/http/fetcher.js
CHANGED
|
@@ -106,6 +106,43 @@ class Fetcher {
|
|
|
106
106
|
static create(cfg = {}) {
|
|
107
107
|
return new Fetcher(cfg);
|
|
108
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Small convenience wrapper that allows to issue GraphQL queries.
|
|
111
|
+
* In practice, all it does is:
|
|
112
|
+
* - Defines convenience `query` input option
|
|
113
|
+
* - Unwraps `response.data`
|
|
114
|
+
* - Unwraps `response.errors` and throws, if it's defined (as GQL famously returns http 200 even for errors)
|
|
115
|
+
*
|
|
116
|
+
* Currently it only unwraps and uses the first error from the `errors` array, for simplicity.
|
|
117
|
+
*
|
|
118
|
+
* @experimental
|
|
119
|
+
*/
|
|
120
|
+
async queryGraphQL(opt) {
|
|
121
|
+
opt.json = {
|
|
122
|
+
query: opt.query,
|
|
123
|
+
variables: opt.variables,
|
|
124
|
+
};
|
|
125
|
+
const res = await this.doFetch(opt);
|
|
126
|
+
if (res.err) {
|
|
127
|
+
throw res.err;
|
|
128
|
+
}
|
|
129
|
+
if (res.body.errors) {
|
|
130
|
+
// unwrap errors and throw
|
|
131
|
+
const err = res.body.errors[0];
|
|
132
|
+
// todo: consider creating a new GraphQLError class for this
|
|
133
|
+
throw new error_util_1.HttpRequestError(err.message, {
|
|
134
|
+
errors: res.body.errors, // full errors payload returned
|
|
135
|
+
response: res.fetchResponse,
|
|
136
|
+
responseStatusCode: res.statusCode,
|
|
137
|
+
requestUrl: res.req.fullUrl,
|
|
138
|
+
requestBaseUrl: this.cfg.baseUrl,
|
|
139
|
+
requestMethod: res.req.init.method,
|
|
140
|
+
requestSignature: res.signature,
|
|
141
|
+
requestDuration: Date.now() - res.req.started,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return res.body.data;
|
|
145
|
+
}
|
|
109
146
|
// responseType=readableStream
|
|
110
147
|
/**
|
|
111
148
|
* Returns raw fetchResponse.body, which is a ReadableStream<Uint8Array>
|
|
@@ -116,6 +116,10 @@ export interface FetcherRequest extends Omit<FetcherOptions, 'method' | 'headers
|
|
|
116
116
|
retry5xx: boolean;
|
|
117
117
|
started: UnixTimestampMillis;
|
|
118
118
|
}
|
|
119
|
+
export interface FetcherGraphQLOptions extends FetcherOptions {
|
|
120
|
+
query: string;
|
|
121
|
+
variables?: AnyObject;
|
|
122
|
+
}
|
|
119
123
|
export interface FetcherOptions {
|
|
120
124
|
method?: HttpMethod;
|
|
121
125
|
/**
|
|
@@ -253,3 +257,19 @@ export type FetcherResponseType = 'json' | 'text' | 'void' | 'arrayBuffer' | 'bl
|
|
|
253
257
|
* e.g when mocking.
|
|
254
258
|
*/
|
|
255
259
|
export type FetchFunction = (url: string, init: RequestInitNormalized) => Promise<Response>;
|
|
260
|
+
export type GraphQLResponse<DATA> = GraphQLSuccessResponse<DATA> | GraphQLErrorResponse;
|
|
261
|
+
export interface GraphQLSuccessResponse<DATA> {
|
|
262
|
+
data: DATA;
|
|
263
|
+
errors: never;
|
|
264
|
+
}
|
|
265
|
+
export interface GraphQLErrorResponse {
|
|
266
|
+
data: never;
|
|
267
|
+
errors: GraphQLFormattedError[];
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Copy-pasted from `graphql` package, slimmed down.
|
|
271
|
+
* See: https://spec.graphql.org/draft/#sec-Errors
|
|
272
|
+
*/
|
|
273
|
+
export interface GraphQLFormattedError {
|
|
274
|
+
message: string;
|
|
275
|
+
}
|
package/dist-esm/bot.js
CHANGED
|
@@ -61,7 +61,7 @@ export class BotDetectionService {
|
|
|
61
61
|
// if (userAgent.includes('Chrome') && !(globalThis as any).chrome) {
|
|
62
62
|
// return BotReason.ChromeWithoutChrome // Headless Chrome
|
|
63
63
|
// }
|
|
64
|
-
if (this.cfg.treatCDPAsBotReason && this.
|
|
64
|
+
if (this.cfg.treatCDPAsBotReason && this.isCDP()) {
|
|
65
65
|
return BotReason.CDP;
|
|
66
66
|
}
|
|
67
67
|
return null;
|
package/dist-esm/http/fetcher.js
CHANGED
|
@@ -99,6 +99,43 @@ export class Fetcher {
|
|
|
99
99
|
static create(cfg = {}) {
|
|
100
100
|
return new _a(cfg);
|
|
101
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Small convenience wrapper that allows to issue GraphQL queries.
|
|
104
|
+
* In practice, all it does is:
|
|
105
|
+
* - Defines convenience `query` input option
|
|
106
|
+
* - Unwraps `response.data`
|
|
107
|
+
* - Unwraps `response.errors` and throws, if it's defined (as GQL famously returns http 200 even for errors)
|
|
108
|
+
*
|
|
109
|
+
* Currently it only unwraps and uses the first error from the `errors` array, for simplicity.
|
|
110
|
+
*
|
|
111
|
+
* @experimental
|
|
112
|
+
*/
|
|
113
|
+
async queryGraphQL(opt) {
|
|
114
|
+
opt.json = {
|
|
115
|
+
query: opt.query,
|
|
116
|
+
variables: opt.variables,
|
|
117
|
+
};
|
|
118
|
+
const res = await this.doFetch(opt);
|
|
119
|
+
if (res.err) {
|
|
120
|
+
throw res.err;
|
|
121
|
+
}
|
|
122
|
+
if (res.body.errors) {
|
|
123
|
+
// unwrap errors and throw
|
|
124
|
+
const err = res.body.errors[0];
|
|
125
|
+
// todo: consider creating a new GraphQLError class for this
|
|
126
|
+
throw new HttpRequestError(err.message, {
|
|
127
|
+
errors: res.body.errors, // full errors payload returned
|
|
128
|
+
response: res.fetchResponse,
|
|
129
|
+
responseStatusCode: res.statusCode,
|
|
130
|
+
requestUrl: res.req.fullUrl,
|
|
131
|
+
requestBaseUrl: this.cfg.baseUrl,
|
|
132
|
+
requestMethod: res.req.init.method,
|
|
133
|
+
requestSignature: res.signature,
|
|
134
|
+
requestDuration: Date.now() - res.req.started,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return res.body.data;
|
|
138
|
+
}
|
|
102
139
|
// responseType=readableStream
|
|
103
140
|
/**
|
|
104
141
|
* Returns raw fetchResponse.body, which is a ReadableStream<Uint8Array>
|
package/package.json
CHANGED
package/src/bot.ts
CHANGED
|
@@ -152,6 +152,11 @@ export interface FetcherRequest
|
|
|
152
152
|
started: UnixTimestampMillis
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
export interface FetcherGraphQLOptions extends FetcherOptions {
|
|
156
|
+
query: string
|
|
157
|
+
variables?: AnyObject
|
|
158
|
+
}
|
|
159
|
+
|
|
155
160
|
export interface FetcherOptions {
|
|
156
161
|
method?: HttpMethod
|
|
157
162
|
|
|
@@ -325,3 +330,23 @@ export type FetcherResponseType =
|
|
|
325
330
|
* e.g when mocking.
|
|
326
331
|
*/
|
|
327
332
|
export type FetchFunction = (url: string, init: RequestInitNormalized) => Promise<Response>
|
|
333
|
+
|
|
334
|
+
export type GraphQLResponse<DATA> = GraphQLSuccessResponse<DATA> | GraphQLErrorResponse
|
|
335
|
+
|
|
336
|
+
export interface GraphQLSuccessResponse<DATA> {
|
|
337
|
+
data: DATA
|
|
338
|
+
errors: never
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export interface GraphQLErrorResponse {
|
|
342
|
+
data: never
|
|
343
|
+
errors: GraphQLFormattedError[]
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Copy-pasted from `graphql` package, slimmed down.
|
|
348
|
+
* See: https://spec.graphql.org/draft/#sec-Errors
|
|
349
|
+
*/
|
|
350
|
+
export interface GraphQLFormattedError {
|
|
351
|
+
message: string
|
|
352
|
+
}
|
package/src/http/fetcher.ts
CHANGED
|
@@ -29,11 +29,12 @@ import { _jsonParse, _jsonParseIfPossible } from '../string/json.util'
|
|
|
29
29
|
import { _stringify } from '../string/stringify'
|
|
30
30
|
import { _ms, _since } from '../time/time.util'
|
|
31
31
|
import { ErrorDataTuple, NumberOfMilliseconds, UnixTimestampMillis } from '../types'
|
|
32
|
-
import
|
|
32
|
+
import {
|
|
33
33
|
FetcherAfterResponseHook,
|
|
34
34
|
FetcherBeforeRequestHook,
|
|
35
35
|
FetcherBeforeRetryHook,
|
|
36
36
|
FetcherCfg,
|
|
37
|
+
FetcherGraphQLOptions,
|
|
37
38
|
FetcherNormalizedCfg,
|
|
38
39
|
FetcherOnErrorHook,
|
|
39
40
|
FetcherOptions,
|
|
@@ -41,6 +42,7 @@ import type {
|
|
|
41
42
|
FetcherResponse,
|
|
42
43
|
FetcherResponseType,
|
|
43
44
|
FetcherRetryOptions,
|
|
45
|
+
GraphQLResponse,
|
|
44
46
|
RequestInitNormalized,
|
|
45
47
|
} from './fetcher.model'
|
|
46
48
|
import type { HttpStatusFamily } from './http.model'
|
|
@@ -171,6 +173,48 @@ export class Fetcher {
|
|
|
171
173
|
deleteVoid!: (url: string, opt?: FetcherOptions) => Promise<void>
|
|
172
174
|
headVoid!: (url: string, opt?: FetcherOptions) => Promise<void>
|
|
173
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Small convenience wrapper that allows to issue GraphQL queries.
|
|
178
|
+
* In practice, all it does is:
|
|
179
|
+
* - Defines convenience `query` input option
|
|
180
|
+
* - Unwraps `response.data`
|
|
181
|
+
* - Unwraps `response.errors` and throws, if it's defined (as GQL famously returns http 200 even for errors)
|
|
182
|
+
*
|
|
183
|
+
* Currently it only unwraps and uses the first error from the `errors` array, for simplicity.
|
|
184
|
+
*
|
|
185
|
+
* @experimental
|
|
186
|
+
*/
|
|
187
|
+
async queryGraphQL<T = unknown>(opt: FetcherGraphQLOptions): Promise<T> {
|
|
188
|
+
opt.json = {
|
|
189
|
+
query: opt.query,
|
|
190
|
+
variables: opt.variables,
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const res = await this.doFetch<GraphQLResponse<T>>(opt)
|
|
194
|
+
if (res.err) {
|
|
195
|
+
throw res.err
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (res.body.errors) {
|
|
199
|
+
// unwrap errors and throw
|
|
200
|
+
const err = res.body.errors[0]!
|
|
201
|
+
|
|
202
|
+
// todo: consider creating a new GraphQLError class for this
|
|
203
|
+
throw new HttpRequestError(err.message, {
|
|
204
|
+
errors: res.body.errors, // full errors payload returned
|
|
205
|
+
response: res.fetchResponse,
|
|
206
|
+
responseStatusCode: res.statusCode,
|
|
207
|
+
requestUrl: res.req.fullUrl,
|
|
208
|
+
requestBaseUrl: this.cfg.baseUrl,
|
|
209
|
+
requestMethod: res.req.init.method,
|
|
210
|
+
requestSignature: res.signature,
|
|
211
|
+
requestDuration: Date.now() - res.req.started,
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return res.body.data
|
|
216
|
+
}
|
|
217
|
+
|
|
174
218
|
// responseType=readableStream
|
|
175
219
|
/**
|
|
176
220
|
* Returns raw fetchResponse.body, which is a ReadableStream<Uint8Array>
|