@crawlee/core 4.0.0-beta.183 → 4.0.0-beta.185

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/core",
3
- "version": "4.0.0-beta.183",
3
+ "version": "4.0.0-beta.185",
4
4
  "description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
5
5
  "engines": {
6
6
  "node": ">=22.0.0"
@@ -53,10 +53,10 @@
53
53
  "@apify/log": "^3.0.1",
54
54
  "@apify/timeout": "^1.0.1",
55
55
  "@apify/utilities": "^3.0.1",
56
- "@crawlee/fs-storage": "4.0.0-beta.183",
57
- "@crawlee/http-client": "4.0.0-beta.183",
58
- "@crawlee/types": "4.0.0-beta.183",
59
- "@crawlee/utils": "4.0.0-beta.183",
56
+ "@crawlee/fs-storage": "4.0.0-beta.185",
57
+ "@crawlee/http-client": "4.0.0-beta.185",
58
+ "@crawlee/types": "4.0.0-beta.185",
59
+ "@crawlee/utils": "4.0.0-beta.185",
60
60
  "@sapphire/async-queue": "^1.5.5",
61
61
  "@standard-schema/spec": "^1.0.0",
62
62
  "@vladfrangu/async_event_emitter": "^2.4.6",
@@ -76,5 +76,5 @@
76
76
  }
77
77
  }
78
78
  },
79
- "gitHead": "3832a8d3392bba9e3e7cc6d06b9be0be4ee1ab98"
79
+ "gitHead": "642c670956a5a60384d5ed5e67ee809927cc419b"
80
80
  }
package/request.d.ts CHANGED
@@ -1,22 +1,12 @@
1
1
  import type { BinaryLike } from 'node:crypto';
2
- import type { AllowedHttpMethods, Dictionary } from '@crawlee/types';
2
+ import type { AllowedHttpMethods, Dictionary, RequestSchema } from '@crawlee/types';
3
3
  import type { EnqueueStrategy } from '@crawlee/utils';
4
4
  /** The `strategy` option accepted by {@link ExtractLinksOptions} and {@link EnqueueUrlsOptions}. */
5
5
  export type EnqueueStrategyOption = EnqueueStrategy | 'all' | 'same-domain' | 'same-hostname' | 'same-origin';
6
- export type SkippedRequestReason = 'robotsTxt' | 'limit' | 'enqueueLimit' | 'filters' | 'transform' | 'redirect' | 'depth';
7
- export declare enum RequestState {
8
- UNPROCESSED = 0,
9
- BEFORE_NAV = 1,
10
- AFTER_NAV = 2,
11
- REQUEST_HANDLER = 3,
12
- DONE = 4,
13
- ERROR_HANDLER = 5,
14
- ERROR = 6,
15
- SKIPPED = 7
16
- }
17
6
  /**
18
- * Represents a URL to be crawled, optionally including HTTP method, headers, payload and other metadata.
19
- * The `Request` object also stores information about errors that occurred during processing of the request.
7
+ * Represents a URL to be crawled, optionally including HTTP method, headers, payload and other metadata, together
8
+ * with the processing state a request queue keeps about it (`retryCount`, `errorMessages`, `handledAt`, ...).
9
+ * Inside a crawler, requests are {@link CrawlingRequest}s, which add the crawler's own per-request settings.
20
10
  *
21
11
  * Each `Request` instance has the `uniqueKey` property, which can be either specified
22
12
  * manually in the constructor or generated automatically from the URL. Two requests with the same `uniqueKey`
@@ -32,22 +22,16 @@ export declare enum RequestState {
32
22
  * const request = new Request({
33
23
  * url: 'http://www.example.com',
34
24
  * headers: { Accept: 'application/json' },
25
+ * userData: { foo: 'bar' },
35
26
  * });
36
27
  *
37
- * ...
38
- *
39
- * request.userData.foo = 'bar';
40
- * request.pushErrorMessage(new Error('Request failed!'));
41
- *
42
- * ...
43
- *
44
- * const foo = request.userData.foo;
28
+ * await requestQueue.addRequest(request);
45
29
  * ```
46
30
  * @category Sources
47
31
  */
48
32
  declare class CrawleeRequest<UserData extends Dictionary = Dictionary> {
49
33
  #private;
50
- /** Request ID */
34
+ /** Storage-assigned request ID. Only present on requests that went through a {@link RequestQueue}. */
51
35
  id?: string;
52
36
  /** URL of the web page to crawl. */
53
37
  url: string;
@@ -91,78 +75,25 @@ declare class CrawleeRequest<UserData extends Dictionary = Dictionary> {
91
75
  handledAt?: string;
92
76
  /**
93
77
  * `Request` parameters including the URL, HTTP method and headers, and others.
78
+ *
79
+ * Processing state (`retryCount`, `errorMessages`, `handledAt`, `loadedUrl`, `id`) is not an option;
80
+ * requests coming back from a storage are rebuilt with {@link Request.fromSchema}.
94
81
  */
95
82
  constructor(options: RequestOptions<UserData>);
83
+ /**
84
+ * Rebuilds a request from its stored form, including the processing state a
85
+ * {@link RequestOptions} object cannot carry. Subclasses get instances of themselves.
86
+ */
87
+ static fromSchema<UserData extends Dictionary = Dictionary>(schema: RequestSchema): CrawleeRequest<UserData>;
96
88
  /**
97
89
  * Converts the Crawlee Request object to a `fetch` API Request object.
98
90
  * @returns The native `fetch` API Request object.
99
91
  */
100
92
  intoFetchAPIRequest(): Request;
101
- /**
102
- * Tells the crawler processing this request to skip the navigation and process the request directly.
103
- *
104
- * When this is set to `true`, the crawling context will not contain the results of the navigation
105
- * (e.g. `response`, `body`, `contentType`, `$` or `request.loadedUrl`).
106
- * Accessing these properties will throw a {@link NavigationSkippedError} at runtime.
107
- */
108
- get skipNavigation(): boolean;
109
- /**
110
- * Tells the crawler processing this request to skip the navigation and process the request directly.
111
- *
112
- * When this is set to `true`, the crawling context will not contain the results of the navigation
113
- * (e.g. `response`, `body`, `contentType`, `$` or `request.loadedUrl`).
114
- * Accessing these properties will throw a {@link NavigationSkippedError} at runtime.
115
- */
116
- set skipNavigation(value: boolean);
117
- /**
118
- * Depth of the request in the current crawl tree.
119
- * Note that this is dependent on the crawler setup and might produce unexpected results when used with multiple crawlers.
120
- */
121
- get crawlDepth(): number;
122
- /**
123
- * Depth of the request in the current crawl tree.
124
- * Note that this is dependent on the crawler setup and might produce unexpected results when used with multiple crawlers.
125
- */
126
- set crawlDepth(value: number);
127
- /** ID of a session to use for this request. When set, the crawler will fetch this session from the session pool instead of creating a new one. */
128
- get sessionId(): string | undefined;
129
- set sessionId(value: string | undefined);
130
93
  /** shortcut for getting `request.userData.label` */
131
94
  get label(): string | undefined;
132
95
  /** shortcut for setting `request.userData.label` */
133
96
  set label(value: string | undefined);
134
- /** Maximum number of retries for this request. Allows to override the global `maxRequestRetries` option of `BasicCrawler`. */
135
- get maxRetries(): number | undefined;
136
- /** Maximum number of retries for this request. Allows to override the global `maxRequestRetries` option of `BasicCrawler`. */
137
- set maxRetries(value: number | undefined);
138
- /** Describes the request's current lifecycle state. */
139
- get state(): RequestState;
140
- /** Describes the request's current lifecycle state. */
141
- set state(value: RequestState);
142
- /**
143
- * Reason for skipping this request.
144
- */
145
- get skippedReason(): SkippedRequestReason | undefined;
146
- /**
147
- * Reason for skipping this request.
148
- */
149
- set skippedReason(value: SkippedRequestReason | undefined);
150
- private get enqueueStrategy();
151
- private set enqueueStrategy(value);
152
- /**
153
- * Stores information about an error that occurred during processing of this request.
154
- *
155
- * You should always use Error instances when throwing errors in JavaScript.
156
- *
157
- * Nevertheless, to improve the debugging experience when using third party libraries
158
- * that may not always throw an Error instance, the function performs a type
159
- * inspection of the passed argument and attempts to extract as much information
160
- * as possible, since just throwing a bad type error makes any debugging rather difficult.
161
- *
162
- * @param errorOrMessage Error object or error message to be stored in the request.
163
- * @param [options]
164
- */
165
- pushErrorMessage(errorOrMessage: unknown, options?: PushErrorMessageOptions): void;
166
97
  /** @internal */
167
98
  static computeUniqueKey({ url, method, payload, keepUrlFragment, useExtendedUniqueKey, alwaysEnqueue, }: ComputeUniqueKeyOptions): string;
168
99
  /** @internal */
@@ -266,32 +197,13 @@ export interface RequestOptions<UserData extends Dictionary = Dictionary> {
266
197
  * @default 0
267
198
  */
268
199
  crawlDepth?: number;
269
- /**
270
- * Reason for skipping this request.
271
- * This is used to provide more information about why the request was skipped.
272
- * @internal
273
- */
274
- skippedReason?: SkippedRequestReason;
275
200
  /**
276
201
  * Maximum number of retries for this request. Allows to override the global `maxRequestRetries` option of `BasicCrawler`.
277
202
  */
278
203
  maxRetries?: number;
279
204
  /** @internal */
280
- id?: string;
281
- /** @internal */
282
- handledAt?: string;
283
- /** @internal */
284
- lockExpiresAt?: Date;
285
- /** @internal */
286
205
  enqueueStrategy?: EnqueueStrategyOption;
287
206
  }
288
- export interface PushErrorMessageOptions {
289
- /**
290
- * Only push the error message without stack trace when true.
291
- * @default false
292
- */
293
- omitStack?: boolean;
294
- }
295
207
  interface ComputeUniqueKeyOptions {
296
208
  url: string;
297
209
  method: AllowedHttpMethods;
package/request.js CHANGED
@@ -1,41 +1,21 @@
1
1
  import crypto from 'node:crypto';
2
- import util from 'node:util';
3
2
  import { z } from 'zod';
4
3
  import { cryptoRandomObjectId, normalizeUrl } from '@apify/utilities';
5
4
  import { serviceLocator } from './service_locator.js';
6
5
  import { keys } from './typedefs.js';
7
6
  import { parseArgument, schemas } from './validators.js';
8
- const dateString = z.string().refine((value) => !Number.isNaN(Date.parse(value)), {
9
- message: 'Invalid input: expected a date string',
10
- });
11
- export var RequestState;
12
- (function (RequestState) {
13
- RequestState[RequestState["UNPROCESSED"] = 0] = "UNPROCESSED";
14
- RequestState[RequestState["BEFORE_NAV"] = 1] = "BEFORE_NAV";
15
- RequestState[RequestState["AFTER_NAV"] = 2] = "AFTER_NAV";
16
- RequestState[RequestState["REQUEST_HANDLER"] = 3] = "REQUEST_HANDLER";
17
- RequestState[RequestState["DONE"] = 4] = "DONE";
18
- RequestState[RequestState["ERROR_HANDLER"] = 5] = "ERROR_HANDLER";
19
- RequestState[RequestState["ERROR"] = 6] = "ERROR";
20
- RequestState[RequestState["SKIPPED"] = 7] = "SKIPPED";
21
- })(RequestState || (RequestState = {}));
22
7
  const requestUrlSchema = z.object({ url: z.string() });
23
8
  // new properties on the Request object breaks serialization
24
9
  const requestOptionalSchemaShapes = {
25
- id: z.string().optional(),
26
- loadedUrl: z.url().optional(),
27
10
  uniqueKey: z.string().optional(),
28
11
  method: z.string().optional(),
29
12
  payload: z.union([z.string(), z.instanceof(Uint8Array)]).optional(),
30
13
  noRetry: z.boolean().optional(),
31
- retryCount: schemas.anyNumber.optional(),
32
14
  sessionId: z.string().optional(),
33
15
  maxRetries: schemas.anyNumber.optional(),
34
- errorMessages: schemas.arrayOf(z.string(), 'strings').optional(),
35
16
  headers: z.looseObject({}).optional(),
36
17
  userData: z.looseObject({}).optional(),
37
18
  label: z.string().optional(),
38
- handledAt: z.union([dateString, z.date()]).optional(),
39
19
  keepUrlFragment: z.boolean().optional(),
40
20
  useExtendedUniqueKey: z.boolean().optional(),
41
21
  alwaysEnqueue: z.boolean().optional(),
@@ -43,13 +23,13 @@ const requestOptionalSchemaShapes = {
43
23
  crawlDepth: schemas.anyNumber
44
24
  .refine((value) => value >= 0, 'Expected a number greater than or equal to 0')
45
25
  .optional(),
46
- state: z.enum(RequestState).optional(),
47
26
  };
48
27
  // Each schema is wrapped in a single-key object so validation errors carry the property name.
49
28
  const requestOptionalSchemas = Object.fromEntries(Object.entries(requestOptionalSchemaShapes).map(([key, schema]) => [key, z.object({ [key]: schema })]));
50
29
  /**
51
- * Represents a URL to be crawled, optionally including HTTP method, headers, payload and other metadata.
52
- * The `Request` object also stores information about errors that occurred during processing of the request.
30
+ * Represents a URL to be crawled, optionally including HTTP method, headers, payload and other metadata, together
31
+ * with the processing state a request queue keeps about it (`retryCount`, `errorMessages`, `handledAt`, ...).
32
+ * Inside a crawler, requests are {@link CrawlingRequest}s, which add the crawler's own per-request settings.
53
33
  *
54
34
  * Each `Request` instance has the `uniqueKey` property, which can be either specified
55
35
  * manually in the constructor or generated automatically from the URL. Two requests with the same `uniqueKey`
@@ -65,21 +45,15 @@ const requestOptionalSchemas = Object.fromEntries(Object.entries(requestOptional
65
45
  * const request = new Request({
66
46
  * url: 'http://www.example.com',
67
47
  * headers: { Accept: 'application/json' },
48
+ * userData: { foo: 'bar' },
68
49
  * });
69
50
  *
70
- * ...
71
- *
72
- * request.userData.foo = 'bar';
73
- * request.pushErrorMessage(new Error('Request failed!'));
74
- *
75
- * ...
76
- *
77
- * const foo = request.userData.foo;
51
+ * await requestQueue.addRequest(request);
78
52
  * ```
79
53
  * @category Sources
80
54
  */
81
55
  class CrawleeRequest {
82
- /** Request ID */
56
+ /** Storage-assigned request ID. Only present on requests that went through a {@link RequestQueue}. */
83
57
  id;
84
58
  /** URL of the web page to crawl. */
85
59
  url;
@@ -125,6 +99,9 @@ class CrawleeRequest {
125
99
  handledAt;
126
100
  /**
127
101
  * `Request` parameters including the URL, HTTP method and headers, and others.
102
+ *
103
+ * Processing state (`retryCount`, `errorMessages`, `handledAt`, `loadedUrl`, `id`) is not an option;
104
+ * requests coming back from a storage are rebuilt with {@link Request.fromSchema}.
128
105
  */
129
106
  constructor(options) {
130
107
  // A bare URL is a common slip — point at the object form instead of a generic type error.
@@ -149,7 +126,7 @@ class CrawleeRequest {
149
126
  parseArgument({ [prop]: value }, schema, 'RequestOptions');
150
127
  }
151
128
  });
152
- const { id, url, loadedUrl, uniqueKey, payload, noRetry = false, retryCount = 0, sessionId, maxRetries, errorMessages = [], headers = {}, userData = {}, label, handledAt, keepUrlFragment = false, useExtendedUniqueKey = false, alwaysEnqueue = false, skipNavigation, enqueueStrategy, crawlDepth, } = options;
129
+ const { url, uniqueKey, payload, noRetry = false, sessionId, maxRetries, headers = {}, userData = {}, label, keepUrlFragment = false, useExtendedUniqueKey = false, alwaysEnqueue = false, skipNavigation, enqueueStrategy, crawlDepth, } = options;
153
130
  let { method = 'GET' } = options;
154
131
  method = method.toUpperCase();
155
132
  if (method === 'GET' && payload)
@@ -157,9 +134,7 @@ class CrawleeRequest {
157
134
  if (uniqueKey && alwaysEnqueue) {
158
135
  throw new Error('`alwaysEnqueue` cannot be used together with a custom `uniqueKey`.');
159
136
  }
160
- this.id = id;
161
137
  this.url = url;
162
- this.loadedUrl = loadedUrl;
163
138
  this.uniqueKey =
164
139
  uniqueKey ||
165
140
  CrawleeRequest.computeUniqueKey({
@@ -173,10 +148,9 @@ class CrawleeRequest {
173
148
  this.method = method;
174
149
  this.payload = payload;
175
150
  this.noRetry = noRetry;
176
- this.retryCount = retryCount;
177
- this.errorMessages = [...errorMessages];
151
+ this.retryCount = 0;
152
+ this.errorMessages = [];
178
153
  this.headers = { ...headers };
179
- this.handledAt = handledAt instanceof Date ? handledAt.toISOString() : handledAt;
180
154
  if (label) {
181
155
  userData.label = label;
182
156
  }
@@ -216,18 +190,34 @@ class CrawleeRequest {
216
190
  });
217
191
  // reassign userData to ensure internal `__crawlee` object is non-enumerable
218
192
  this.userData = userData;
193
+ const crawlee = (this.userData.__crawlee ??= {});
219
194
  if (skipNavigation != null)
220
- this.skipNavigation = skipNavigation;
195
+ crawlee.skipNavigation = skipNavigation;
221
196
  if (maxRetries != null)
222
- this.maxRetries = maxRetries;
197
+ crawlee.maxRetries = maxRetries;
223
198
  if (crawlDepth != null)
224
- this.userData.__crawlee.crawlDepth ??= crawlDepth;
199
+ crawlee.crawlDepth ??= crawlDepth;
225
200
  if (sessionId)
226
- this.sessionId = sessionId;
227
- // If it's already set, don't override it (for instance when fetching from storage)
228
- if (enqueueStrategy) {
229
- this.enqueueStrategy ??= enqueueStrategy;
230
- }
201
+ crawlee.sessionId = sessionId;
202
+ // A stored request keeps the strategy it was enqueued under.
203
+ if (enqueueStrategy)
204
+ crawlee.enqueueStrategy ??= enqueueStrategy;
205
+ }
206
+ /**
207
+ * Rebuilds a request from its stored form, including the processing state a
208
+ * {@link RequestOptions} object cannot carry. Subclasses get instances of themselves.
209
+ */
210
+ static fromSchema(schema) {
211
+ const { id, retryCount = 0, errorMessages = [], handledAt, loadedUrl, ...options } = schema;
212
+ const request = new this(options);
213
+ request.id = id;
214
+ request.retryCount = retryCount;
215
+ request.errorMessages = [...errorMessages];
216
+ request.loadedUrl = loadedUrl;
217
+ // `apify-client` parses `*At` fields into `Date`s, whatever the schema says.
218
+ request.handledAt =
219
+ handledAt instanceof Date ? handledAt.toISOString() : handledAt;
220
+ return request;
231
221
  }
232
222
  /**
233
223
  * Converts the Crawlee Request object to a `fetch` API Request object.
@@ -240,54 +230,6 @@ class CrawleeRequest {
240
230
  body: this.payload,
241
231
  });
242
232
  }
243
- /**
244
- * Tells the crawler processing this request to skip the navigation and process the request directly.
245
- *
246
- * When this is set to `true`, the crawling context will not contain the results of the navigation
247
- * (e.g. `response`, `body`, `contentType`, `$` or `request.loadedUrl`).
248
- * Accessing these properties will throw a {@link NavigationSkippedError} at runtime.
249
- */
250
- get skipNavigation() {
251
- return this.userData.__crawlee?.skipNavigation ?? false;
252
- }
253
- /**
254
- * Tells the crawler processing this request to skip the navigation and process the request directly.
255
- *
256
- * When this is set to `true`, the crawling context will not contain the results of the navigation
257
- * (e.g. `response`, `body`, `contentType`, `$` or `request.loadedUrl`).
258
- * Accessing these properties will throw a {@link NavigationSkippedError} at runtime.
259
- */
260
- set skipNavigation(value) {
261
- if (!this.userData.__crawlee) {
262
- this.userData.__crawlee = { skipNavigation: value };
263
- }
264
- else {
265
- this.userData.__crawlee.skipNavigation = value;
266
- }
267
- }
268
- /**
269
- * Depth of the request in the current crawl tree.
270
- * Note that this is dependent on the crawler setup and might produce unexpected results when used with multiple crawlers.
271
- */
272
- get crawlDepth() {
273
- return this.userData.__crawlee?.crawlDepth ?? 0;
274
- }
275
- /**
276
- * Depth of the request in the current crawl tree.
277
- * Note that this is dependent on the crawler setup and might produce unexpected results when used with multiple crawlers.
278
- */
279
- set crawlDepth(value) {
280
- this.userData.__crawlee ??= {};
281
- this.userData.__crawlee.crawlDepth = value;
282
- }
283
- /** ID of a session to use for this request. When set, the crawler will fetch this session from the session pool instead of creating a new one. */
284
- get sessionId() {
285
- return this.userData.__crawlee?.sessionId;
286
- }
287
- set sessionId(value) {
288
- this.userData.__crawlee ??= {};
289
- this.userData.__crawlee.sessionId = value;
290
- }
291
233
  /** shortcut for getting `request.userData.label` */
292
234
  get label() {
293
235
  return this.userData.label;
@@ -296,110 +238,6 @@ class CrawleeRequest {
296
238
  set label(value) {
297
239
  this.userData.label = value;
298
240
  }
299
- /** Maximum number of retries for this request. Allows to override the global `maxRequestRetries` option of `BasicCrawler`. */
300
- get maxRetries() {
301
- return this.userData.__crawlee?.maxRetries;
302
- }
303
- /** Maximum number of retries for this request. Allows to override the global `maxRequestRetries` option of `BasicCrawler`. */
304
- set maxRetries(value) {
305
- if (!this.userData.__crawlee) {
306
- this.userData.__crawlee = { maxRetries: value };
307
- }
308
- else {
309
- this.userData.__crawlee.maxRetries = value;
310
- }
311
- }
312
- /** Describes the request's current lifecycle state. */
313
- get state() {
314
- return this.userData.__crawlee?.state ?? RequestState.UNPROCESSED;
315
- }
316
- /** Describes the request's current lifecycle state. */
317
- set state(value) {
318
- if (!this.userData.__crawlee) {
319
- this.userData.__crawlee = { state: value };
320
- }
321
- else {
322
- this.userData.__crawlee.state = value;
323
- }
324
- }
325
- /**
326
- * Reason for skipping this request.
327
- */
328
- get skippedReason() {
329
- return this.userData.__crawlee?.skippedReason;
330
- }
331
- /**
332
- * Reason for skipping this request.
333
- */
334
- set skippedReason(value) {
335
- if (!this.userData.__crawlee) {
336
- this.userData.__crawlee = { skippedReason: value };
337
- }
338
- else {
339
- this.userData.__crawlee.skippedReason = value;
340
- }
341
- }
342
- get enqueueStrategy() {
343
- return this.userData.__crawlee?.enqueueStrategy;
344
- }
345
- set enqueueStrategy(value) {
346
- if (!this.userData.__crawlee) {
347
- this.userData.__crawlee = { enqueueStrategy: value };
348
- }
349
- else {
350
- this.userData.__crawlee.enqueueStrategy = value;
351
- }
352
- }
353
- /**
354
- * Stores information about an error that occurred during processing of this request.
355
- *
356
- * You should always use Error instances when throwing errors in JavaScript.
357
- *
358
- * Nevertheless, to improve the debugging experience when using third party libraries
359
- * that may not always throw an Error instance, the function performs a type
360
- * inspection of the passed argument and attempts to extract as much information
361
- * as possible, since just throwing a bad type error makes any debugging rather difficult.
362
- *
363
- * @param errorOrMessage Error object or error message to be stored in the request.
364
- * @param [options]
365
- */
366
- pushErrorMessage(errorOrMessage, options = {}) {
367
- const { omitStack } = options;
368
- let message;
369
- const type = typeof errorOrMessage;
370
- if (type === 'object') {
371
- if (!errorOrMessage) {
372
- message = 'null';
373
- }
374
- else if (errorOrMessage instanceof Error) {
375
- message = omitStack
376
- ? errorOrMessage.message
377
- : // .stack includes the message
378
- errorOrMessage.stack;
379
- }
380
- else if (Reflect.has(Object(errorOrMessage), 'message')) {
381
- message = Reflect.get(Object(errorOrMessage), 'message');
382
- }
383
- else if (errorOrMessage.toString() !== '[object Object]') {
384
- message = errorOrMessage.toString();
385
- }
386
- else {
387
- try {
388
- message = util.inspect(errorOrMessage);
389
- }
390
- catch (err) {
391
- message = 'Unable to extract any message from the received object.';
392
- }
393
- }
394
- }
395
- else if (type === 'undefined') {
396
- message = 'undefined';
397
- }
398
- else {
399
- message = errorOrMessage.toString();
400
- }
401
- this.errorMessages.push(message);
402
- }
403
241
  /** @internal */
404
242
  static computeUniqueKey({ url, method = 'GET', payload, keepUrlFragment = false, useExtendedUniqueKey = false, alwaysEnqueue = false, }) {
405
243
  const normalizedMethod = method.toUpperCase();
@@ -336,7 +336,7 @@ export class RequestQueue {
336
336
  ? // Requests without a snapshot were deduplicated or written through; nothing to replay.
337
337
  entry.requests
338
338
  .filter((journaled) => journaled.snapshot !== undefined)
339
- .map((journaled) => new Request(journaled.snapshot))
339
+ .map((journaled) => Request.fromSchema(journaled.snapshot))
340
340
  : []);
341
341
  if (requests.length === 0)
342
342
  continue;
@@ -473,7 +473,7 @@ export class RequestQueue {
473
473
  if (opts.url !== undefined && typeof opts.url !== 'string') {
474
474
  throw new Error(`Request options are not valid, the 'url' property is not a string. Input: ${inspect(opts)}`);
475
475
  }
476
- if (opts.id !== undefined) {
476
+ if ('id' in opts && opts.id !== undefined) {
477
477
  throw new Error(`Request options are not valid, the 'id' property must not be present. Input: ${inspect(opts)}`);
478
478
  }
479
479
  if (opts.requestsFromUrl !== undefined &&
@@ -534,12 +534,12 @@ export class RequestQueue {
534
534
  // Requests buffered by the active transaction (under the `deferred` write policy) are visible to it.
535
535
  const buffered = transaction && this.bufferedRequests(transaction).get(uniqueKey);
536
536
  if (buffered) {
537
- return new Request(buffered);
537
+ return Request.fromSchema(buffered);
538
538
  }
539
- const requestOptions = await this.backend.getRequest(uniqueKey);
540
- if (!requestOptions)
539
+ const schema = await this.backend.getRequest(uniqueKey);
540
+ if (!schema)
541
541
  return null;
542
- return new Request(requestOptions);
542
+ return Request.fromSchema(schema);
543
543
  }
544
544
  /**
545
545
  * Returns a next request in the queue to be processed, or `null` if there are no more pending requests.
@@ -564,10 +564,10 @@ export class RequestQueue {
564
564
  return null;
565
565
  }
566
566
  this.#statsTracker.add('headItemReadCount');
567
- const requestOptions = await this.backend.fetchNextRequest();
568
- if (!requestOptions)
567
+ const schema = await this.backend.fetchNextRequest();
568
+ if (!schema)
569
569
  return null;
570
- return new Request(requestOptions);
570
+ return Request.fromSchema(schema);
571
571
  }
572
572
  /**
573
573
  * Marks a request that was previously returned by the
@@ -685,7 +685,6 @@ export class RequestQueue {
685
685
  isHandled: queueOperationInfo.wasAlreadyHandled,
686
686
  uniqueKey: queueOperationInfo.uniqueKey,
687
687
  hydrated: null,
688
- lockExpiresAt: null,
689
688
  forefront: queueOperationInfo.forefront,
690
689
  });
691
690
  }
@@ -1,4 +1,4 @@
1
- import type { Awaitable, Dictionary } from '@crawlee/types';
1
+ import type { Awaitable, Dictionary, RequestSchema } from '@crawlee/types';
2
2
  import type { RecordOptions } from './key_value_store.js';
3
3
  /**
4
4
  * Governs whether writes of a given storage type performed inside a {@link StorageTransaction} are
@@ -72,7 +72,7 @@ export interface JournaledRequest {
72
72
  * A full JSON snapshot of the request for the commit replay. Only present for buffered additions —
73
73
  * deduplicated and write-through ones are journaled for introspection only.
74
74
  */
75
- snapshot?: Dictionary;
75
+ snapshot?: RequestSchema;
76
76
  }
77
77
  /**
78
78
  * A batch of request queue additions recorded in a transaction journal.