@crawlee/core 4.0.0-beta.104 → 4.0.0-beta.106

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.
Files changed (83) hide show
  1. package/autoscaling/autoscaled_pool.d.ts +3 -21
  2. package/autoscaling/autoscaled_pool.js +85 -85
  3. package/autoscaling/client_load_signal.d.ts +1 -5
  4. package/autoscaling/client_load_signal.js +20 -20
  5. package/autoscaling/concurrency_system.d.ts +5 -20
  6. package/autoscaling/concurrency_system.js +81 -80
  7. package/autoscaling/cpu_load_signal.d.ts +1 -2
  8. package/autoscaling/cpu_load_signal.js +10 -10
  9. package/autoscaling/event_loop_load_signal.d.ts +1 -4
  10. package/autoscaling/event_loop_load_signal.js +18 -18
  11. package/autoscaling/load_signal.d.ts +1 -1
  12. package/autoscaling/load_signal.js +12 -11
  13. package/autoscaling/memory_load_signal.d.ts +3 -12
  14. package/autoscaling/memory_load_signal.js +40 -41
  15. package/autoscaling/snapshotter.d.ts +1 -4
  16. package/autoscaling/snapshotter.js +12 -12
  17. package/autoscaling/system_status.d.ts +1 -3
  18. package/autoscaling/system_status.js +11 -11
  19. package/configuration.d.ts +1 -1
  20. package/configuration.js +3 -3
  21. package/crawlers/context_pipeline.js +6 -6
  22. package/crawlers/crawler_commons.d.ts +6 -56
  23. package/crawlers/crawler_commons.js +1 -107
  24. package/crawlers/index.d.ts +1 -1
  25. package/crawlers/index.js +0 -1
  26. package/crawlers/statistics.d.ts +1 -8
  27. package/crawlers/statistics.js +45 -44
  28. package/events/event_manager.d.ts +1 -1
  29. package/events/event_manager.js +3 -3
  30. package/events/local_event_manager.d.ts +1 -1
  31. package/events/local_event_manager.js +3 -3
  32. package/log.js +5 -1
  33. package/memory-storage/memory-storage.d.ts +1 -5
  34. package/memory-storage/memory-storage.js +2 -2
  35. package/memory-storage/resource-clients/dataset.d.ts +1 -1
  36. package/memory-storage/resource-clients/dataset.js +6 -5
  37. package/memory-storage/resource-clients/key-value-store.d.ts +1 -1
  38. package/memory-storage/resource-clients/key-value-store.js +13 -12
  39. package/memory-storage/resource-clients/request-queue.d.ts +4 -23
  40. package/memory-storage/resource-clients/request-queue.js +59 -58
  41. package/owned_or_injected.d.ts +1 -3
  42. package/owned_or_injected.js +17 -17
  43. package/package.json +5 -5
  44. package/proxy_configuration.d.ts +1 -3
  45. package/proxy_configuration.js +8 -8
  46. package/recoverable_state.d.ts +1 -10
  47. package/recoverable_state.js +41 -41
  48. package/request.d.ts +1 -2
  49. package/request.js +10 -13
  50. package/router.d.ts +1 -4
  51. package/router.js +23 -23
  52. package/serialization.js +8 -9
  53. package/service_locator.d.ts +1 -10
  54. package/service_locator.js +48 -48
  55. package/session_pool/session.d.ts +1 -12
  56. package/session_pool/session.js +50 -50
  57. package/session_pool/session_pool.d.ts +2 -11
  58. package/session_pool/session_pool.js +59 -58
  59. package/storages/dataset.d.ts +12 -1
  60. package/storages/dataset.js +121 -22
  61. package/storages/index.d.ts +1 -1
  62. package/storages/index.js +1 -1
  63. package/storages/key_value_store.d.ts +19 -4
  64. package/storages/key_value_store.js +174 -48
  65. package/storages/request_dedup_cache.d.ts +1 -2
  66. package/storages/request_dedup_cache.js +9 -9
  67. package/storages/request_list.d.ts +2 -22
  68. package/storages/request_list.js +74 -73
  69. package/storages/request_manager_tandem.d.ts +1 -10
  70. package/storages/request_manager_tandem.js +27 -27
  71. package/storages/request_queue.d.ts +21 -18
  72. package/storages/request_queue.js +256 -53
  73. package/storages/sitemap_request_loader.d.ts +1 -44
  74. package/storages/sitemap_request_loader.js +87 -87
  75. package/storages/storage_instance_manager.d.ts +1 -2
  76. package/storages/storage_instance_manager.js +17 -17
  77. package/storages/storage_stats.d.ts +1 -1
  78. package/storages/storage_stats.js +4 -4
  79. package/storages/transaction.d.ts +252 -0
  80. package/storages/transaction.js +251 -0
  81. package/system-info/runtime.js +7 -7
  82. package/storages/access_checking.d.ts +0 -12
  83. package/storages/access_checking.js +0 -17
@@ -38,8 +38,8 @@ export class RequestQueueBackend extends BaseClient {
38
38
  * `addBatchOfRequests` pushes to it). Held by every mutating method as well as by `isEmpty`/
39
39
  * `isFinished`, whose head scan also prunes `forefrontRequestIds`.
40
40
  */
41
- queueStateMutex = new AsyncQueue();
42
- forefrontRequestIds = [];
41
+ #queueStateMutex = new AsyncQueue();
42
+ #forefrontRequestIds = [];
43
43
  /**
44
44
  * IDs of requests currently fetched but not yet handled or reclaimed. A request in this set is
45
45
  * "in progress" and will not be handed out again by {@link fetchNextRequest}.
@@ -48,8 +48,9 @@ export class RequestQueueBackend extends BaseClient {
48
48
  * process and is never shared with another consumer, so there is no need for an expiring,
49
49
  * cross-process-visible lock — tracking in-progress requests in this set is enough.
50
50
  */
51
- inProgressRequestIds = new Set();
52
- requests = new Map();
51
+ #inProgressRequestIds = new Set();
52
+ #requests = new Map();
53
+ // kept as TS-private: storage-backend tests read this field at runtime
53
54
  storageBackend;
54
55
  constructor(options) {
55
56
  super(options.id ?? randomUUID());
@@ -65,7 +66,7 @@ export class RequestQueueBackend extends BaseClient {
65
66
  // Serialize against other mutators (and the head scans in `isEmpty`/`isFinished`) so a concurrent
66
67
  // operation cannot observe half-cleared state — e.g. a forefront id whose request has already been
67
68
  // removed, which `listPendingHead` would then dereference as `undefined`.
68
- await this.queueStateMutex.wait();
69
+ await this.#queueStateMutex.wait();
69
70
  try {
70
71
  const storeIndex = this.storageBackend.requestQueueBackendCache.findIndex((queue) => queue.id === this.id);
71
72
  if (storeIndex !== -1) {
@@ -74,37 +75,37 @@ export class RequestQueueBackend extends BaseClient {
74
75
  // Clear all in-memory state, consistent with `purge`. Clearing `requests` alone would
75
76
  // leave dangling ids in `forefrontRequestIds`/`inProgressRequestIds`, which a later head
76
77
  // scan would resolve to a missing request and dereference.
77
- oldBackend.requests.clear();
78
- oldBackend.forefrontRequestIds = [];
79
- oldBackend.inProgressRequestIds.clear();
78
+ oldBackend.#requests.clear();
79
+ oldBackend.#forefrontRequestIds = [];
80
+ oldBackend.#inProgressRequestIds.clear();
80
81
  }
81
82
  }
82
83
  finally {
83
- this.queueStateMutex.shift();
84
+ this.#queueStateMutex.shift();
84
85
  }
85
86
  }
86
87
  async purge() {
87
88
  // Serialize against other mutators (and the head scans in `isEmpty`/`isFinished`) so a concurrent
88
89
  // operation cannot observe or repopulate half-cleared state across the `await` below.
89
- await this.queueStateMutex.wait();
90
+ await this.#queueStateMutex.wait();
90
91
  try {
91
92
  // Clear all in-memory state
92
- this.requests.clear();
93
- this.forefrontRequestIds = [];
94
- this.inProgressRequestIds.clear();
93
+ this.#requests.clear();
94
+ this.#forefrontRequestIds = [];
95
+ this.#inProgressRequestIds.clear();
95
96
  this.handledRequestCount = 0;
96
97
  this.pendingRequestCount = 0;
97
98
  this.updateTimestamps(true);
98
99
  }
99
100
  finally {
100
- this.queueStateMutex.shift();
101
+ this.#queueStateMutex.shift();
101
102
  }
102
103
  }
103
104
  *requestKeyIterator() {
104
- for (let i = this.forefrontRequestIds.length - 1; i >= 0; i--) {
105
- yield this.forefrontRequestIds[i];
105
+ for (let i = this.#forefrontRequestIds.length - 1; i >= 0; i--) {
106
+ yield this.#forefrontRequestIds[i];
106
107
  }
107
- for (const key of this.requests.keys()) {
108
+ for (const key of this.#requests.keys()) {
108
109
  yield key;
109
110
  }
110
111
  }
@@ -140,17 +141,17 @@ export class RequestQueueBackend extends BaseClient {
140
141
  continue;
141
142
  }
142
143
  seenRequestIds.add(requestId);
143
- const request = this.requests.get(requestId);
144
+ const request = this.#requests.get(requestId);
144
145
  // Permanently-handled requests (`orderNo === null`) are in a terminal state and can be skipped.
145
146
  if (request.orderNo === null) {
146
- if (this.forefrontRequestIds.includes(requestId)) {
147
+ if (this.#forefrontRequestIds.includes(requestId)) {
147
148
  handledForefrontIds.add(requestId);
148
149
  }
149
150
  continue;
150
151
  }
151
152
  // In progress (fetched but not yet handled or reclaimed) — skip it, but remember that the
152
153
  // queue is not truly empty.
153
- if (this.inProgressRequestIds.has(requestId)) {
154
+ if (this.#inProgressRequestIds.has(requestId)) {
154
155
  hasInProgressRequests = true;
155
156
  continue;
156
157
  }
@@ -158,7 +159,7 @@ export class RequestQueueBackend extends BaseClient {
158
159
  items.push(request);
159
160
  }
160
161
  }
161
- this.forefrontRequestIds = this.forefrontRequestIds.filter((id) => !handledForefrontIds.has(id));
162
+ this.#forefrontRequestIds = this.#forefrontRequestIds.filter((id) => !handledForefrontIds.has(id));
162
163
  return {
163
164
  items: items.sort((a, b) => a.orderNo - b.orderNo),
164
165
  hasInProgressRequests: detectInProgressRequests ? hasInProgressRequests : undefined,
@@ -166,7 +167,7 @@ export class RequestQueueBackend extends BaseClient {
166
167
  }
167
168
  async fetchNextRequest() {
168
169
  this.updateTimestamps(false);
169
- await this.queueStateMutex.wait();
170
+ await this.#queueStateMutex.wait();
170
171
  try {
171
172
  const { items: [head], } = await this.listPendingHead(1);
172
173
  if (!head) {
@@ -174,11 +175,11 @@ export class RequestQueueBackend extends BaseClient {
174
175
  }
175
176
  // Mark the request as in progress so it is not handed out again until it is handled or
176
177
  // reclaimed. The request keeps its `orderNo` (and thus its forefront / normal ordering).
177
- this.inProgressRequestIds.add(head.id);
178
- return this._jsonToRequest(head.json) ?? undefined;
178
+ this.#inProgressRequestIds.add(head.id);
179
+ return this.jsonToRequest(head.json) ?? undefined;
179
180
  }
180
181
  finally {
181
- this.queueStateMutex.shift();
182
+ this.#queueStateMutex.shift();
182
183
  }
183
184
  }
184
185
  async addBatchOfRequests(requests, options = {}) {
@@ -187,15 +188,15 @@ export class RequestQueueBackend extends BaseClient {
187
188
  // Serialize against other mutators (and the head scans in `isEmpty`/`isFinished`) so that the
188
189
  // shared `requests` map, `forefrontRequestIds` array and request counts are not corrupted by a
189
190
  // concurrent operation interleaving at one of the `await` points below.
190
- await this.queueStateMutex.wait();
191
+ await this.#queueStateMutex.wait();
191
192
  try {
192
193
  const result = {
193
194
  processedRequests: [],
194
195
  unprocessedRequests: [],
195
196
  };
196
197
  for (const model of requests) {
197
- const requestModel = this._createInternalRequest(model, options.forefront);
198
- const existingRequestWithId = this.requests.get(requestModel.id);
198
+ const requestModel = this.createInternalRequest(model, options.forefront);
199
+ const existingRequestWithId = this.#requests.get(requestModel.id);
199
200
  if (existingRequestWithId) {
200
201
  result.processedRequests.push({
201
202
  requestId: existingRequestWithId.id,
@@ -205,7 +206,7 @@ export class RequestQueueBackend extends BaseClient {
205
206
  });
206
207
  continue;
207
208
  }
208
- this.requests.set(requestModel.id, requestModel);
209
+ this.#requests.set(requestModel.id, requestModel);
209
210
  if (requestModel.orderNo) {
210
211
  this.pendingRequestCount += 1;
211
212
  }
@@ -213,7 +214,7 @@ export class RequestQueueBackend extends BaseClient {
213
214
  this.handledRequestCount += 1;
214
215
  }
215
216
  if (options.forefront) {
216
- this.forefrontRequestIds.push(requestModel.id);
217
+ this.#forefrontRequestIds.push(requestModel.id);
217
218
  }
218
219
  result.processedRequests.push({
219
220
  requestId: requestModel.id,
@@ -228,15 +229,15 @@ export class RequestQueueBackend extends BaseClient {
228
229
  return result;
229
230
  }
230
231
  finally {
231
- this.queueStateMutex.shift();
232
+ this.#queueStateMutex.shift();
232
233
  }
233
234
  }
234
235
  async getRequest(uniqueKey) {
235
236
  s.string().parse(uniqueKey);
236
237
  this.updateTimestamps(false);
237
238
  const id = uniqueKeyToRequestId(uniqueKey);
238
- const json = this.requests.get(id)?.json;
239
- return this._jsonToRequest(json);
239
+ const json = this.#requests.get(id)?.json;
240
+ return this.jsonToRequest(json);
240
241
  }
241
242
  async markRequestAsHandled(request) {
242
243
  requestShape.parse(request);
@@ -244,10 +245,10 @@ export class RequestQueueBackend extends BaseClient {
244
245
  // Serialize against other mutators (and the head scans in `isEmpty`/`isFinished`) so the shared
245
246
  // `requests` map, `inProgressRequestIds` set and request counts stay consistent across the
246
247
  // `await` points below.
247
- await this.queueStateMutex.wait();
248
+ await this.#queueStateMutex.wait();
248
249
  try {
249
250
  const id = uniqueKeyToRequestId(request.uniqueKey);
250
- const existingRequest = this.requests.get(id);
251
+ const existingRequest = this.#requests.get(id);
251
252
  // The request must exist to be marked as handled. We intentionally do NOT require it to still
252
253
  // be in progress: marking an already-released request handled must still succeed, otherwise
253
254
  // the request could be handed out again and the queue would never finish.
@@ -257,10 +258,10 @@ export class RequestQueueBackend extends BaseClient {
257
258
  // A handled request has `orderNo === null`. Marking it again is an idempotent no-op.
258
259
  const wasAlreadyHandled = existingRequest.orderNo === null;
259
260
  const handledAt = request.handledAt ?? new Date().toISOString();
260
- const requestModel = this._createInternalRequest({ ...request, handledAt }, false);
261
- this.requests.set(id, requestModel);
261
+ const requestModel = this.createInternalRequest({ ...request, handledAt }, false);
262
+ this.#requests.set(id, requestModel);
262
263
  // The request is no longer in progress for this client.
263
- this.inProgressRequestIds.delete(id);
264
+ this.#inProgressRequestIds.delete(id);
264
265
  if (!wasAlreadyHandled) {
265
266
  this.pendingRequestCount -= 1;
266
267
  this.handledRequestCount += 1;
@@ -273,7 +274,7 @@ export class RequestQueueBackend extends BaseClient {
273
274
  };
274
275
  }
275
276
  finally {
276
- this.queueStateMutex.shift();
277
+ this.#queueStateMutex.shift();
277
278
  }
278
279
  }
279
280
  async reclaimRequest(request, options = {}) {
@@ -283,10 +284,10 @@ export class RequestQueueBackend extends BaseClient {
283
284
  // Serialize against other mutators (and the head scans in `isEmpty`/`isFinished`) so the shared
284
285
  // `requests` map, `forefrontRequestIds` array and `inProgressRequestIds` set stay consistent
285
286
  // across the `await` points below.
286
- await this.queueStateMutex.wait();
287
+ await this.#queueStateMutex.wait();
287
288
  try {
288
289
  const id = uniqueKeyToRequestId(request.uniqueKey);
289
- const existingRequest = this.requests.get(id);
290
+ const existingRequest = this.#requests.get(id);
290
291
  // The request must exist and not already be handled to be reclaimed. As with
291
292
  // `markRequestAsHandled`, we do NOT require it to still be in progress — returning an
292
293
  // already-released request to the queue (e.g. to honor a `forefront` reorder) must still
@@ -296,12 +297,12 @@ export class RequestQueueBackend extends BaseClient {
296
297
  }
297
298
  // Reclaiming resets the `orderNo` to a fresh timestamp, restoring the request to the queue
298
299
  // (at the front if `forefront`).
299
- const requestModel = this._createInternalRequest(request, options.forefront);
300
- this.requests.set(id, requestModel);
300
+ const requestModel = this.createInternalRequest(request, options.forefront);
301
+ this.#requests.set(id, requestModel);
301
302
  // The request is no longer in progress for this client.
302
- this.inProgressRequestIds.delete(id);
303
+ this.#inProgressRequestIds.delete(id);
303
304
  if (options.forefront) {
304
- this.forefrontRequestIds.push(id);
305
+ this.#forefrontRequestIds.push(id);
305
306
  }
306
307
  this.updateTimestamps(true);
307
308
  return {
@@ -311,7 +312,7 @@ export class RequestQueueBackend extends BaseClient {
311
312
  };
312
313
  }
313
314
  finally {
314
- this.queueStateMutex.shift();
315
+ this.#queueStateMutex.shift();
315
316
  }
316
317
  }
317
318
  async isEmpty() {
@@ -324,13 +325,13 @@ export class RequestQueueBackend extends BaseClient {
324
325
  //
325
326
  // `listPendingHead` prunes `forefrontRequestIds` as it scans, so we must hold the queue-state mutex to avoid
326
327
  // racing a concurrent mutator (e.g. `addBatchOfRequests`) at its `await` points.
327
- await this.queueStateMutex.wait();
328
+ await this.#queueStateMutex.wait();
328
329
  try {
329
330
  const { items } = await this.listPendingHead(1);
330
331
  return items.length === 0;
331
332
  }
332
333
  finally {
333
- this.queueStateMutex.shift();
334
+ this.#queueStateMutex.shift();
334
335
  }
335
336
  }
336
337
  async isFinished() {
@@ -344,13 +345,13 @@ export class RequestQueueBackend extends BaseClient {
344
345
  //
345
346
  // `listPendingHead` prunes `forefrontRequestIds` as it scans, so we must hold the queue-state mutex to avoid
346
347
  // racing a concurrent mutator (e.g. `addBatchOfRequests`) at its `await` points.
347
- await this.queueStateMutex.wait();
348
+ await this.#queueStateMutex.wait();
348
349
  try {
349
350
  const { items, hasInProgressRequests } = await this.listPendingHead(1, true);
350
351
  return items.length === 0 && !hasInProgressRequests;
351
352
  }
352
353
  finally {
353
- this.queueStateMutex.shift();
354
+ this.#queueStateMutex.shift();
354
355
  }
355
356
  }
356
357
  /**
@@ -362,13 +363,13 @@ export class RequestQueueBackend extends BaseClient {
362
363
  this.updateTimestamps(false);
363
364
  // `listPendingHead` prunes `forefrontRequestIds` as it scans, so we must hold the queue-state
364
365
  // mutex to avoid racing a concurrent mutator at its `await` points.
365
- await this.queueStateMutex.wait();
366
+ await this.#queueStateMutex.wait();
366
367
  try {
367
368
  const { items } = await this.listPendingHead(Number.POSITIVE_INFINITY);
368
- return items.map((request) => this._jsonToRequest(request.json));
369
+ return items.map((request) => this.jsonToRequest(request.json));
369
370
  }
370
371
  finally {
371
- this.queueStateMutex.shift();
372
+ this.#queueStateMutex.shift();
372
373
  }
373
374
  }
374
375
  toRequestQueueInfo() {
@@ -380,7 +381,7 @@ export class RequestQueueBackend extends BaseClient {
380
381
  modifiedAt: this.modifiedAt,
381
382
  name: this.name,
382
383
  pendingRequestCount: this.pendingRequestCount,
383
- totalRequestCount: this.requests.size,
384
+ totalRequestCount: this.#requests.size,
384
385
  };
385
386
  }
386
387
  updateTimestamps(hasBeenModified) {
@@ -389,14 +390,14 @@ export class RequestQueueBackend extends BaseClient {
389
390
  this.modifiedAt = new Date();
390
391
  }
391
392
  }
392
- _jsonToRequest(requestJson) {
393
+ jsonToRequest(requestJson) {
393
394
  if (!requestJson)
394
395
  return undefined;
395
396
  const request = JSON.parse(requestJson);
396
397
  return purgeNullsFromObject(request);
397
398
  }
398
- _createInternalRequest(request, forefront) {
399
- const orderNo = this._calculateOrderNo(request, forefront);
399
+ createInternalRequest(request, forefront) {
400
+ const orderNo = this.calculateOrderNo(request, forefront);
400
401
  const id = uniqueKeyToRequestId(request.uniqueKey);
401
402
  if (request.id && request.id !== id) {
402
403
  throw new Error('Request ID does not match its uniqueKey.');
@@ -412,7 +413,7 @@ export class RequestQueueBackend extends BaseClient {
412
413
  url: request.url,
413
414
  };
414
415
  }
415
- _calculateOrderNo(request, forefront) {
416
+ calculateOrderNo(request, forefront) {
416
417
  if (request.handledAt)
417
418
  return null;
418
419
  const timestamp = Date.now();
@@ -10,9 +10,7 @@
10
10
  * @internal
11
11
  */
12
12
  export declare class OwnedOrInjected<Injected, Owned extends Injected = Injected> {
13
- private _value;
14
- private readonly _owned;
15
- private _present;
13
+ #private;
16
14
  private constructor();
17
15
  /**
18
16
  * Resolves a collaborator from an optionally-injected instance. `Injected` is the public/borrowed type exposed via
@@ -10,13 +10,13 @@
10
10
  * @internal
11
11
  */
12
12
  export class OwnedOrInjected {
13
- _value;
14
- _owned;
15
- _present;
13
+ #value;
14
+ #owned;
15
+ #present;
16
16
  constructor(value, owned, present) {
17
- this._value = value;
18
- this._owned = owned;
19
- this._present = present;
17
+ this.#value = value;
18
+ this.#owned = owned;
19
+ this.#present = present;
20
20
  }
21
21
  /**
22
22
  * Resolves a collaborator from an optionally-injected instance. `Injected` is the public/borrowed type exposed via
@@ -42,24 +42,24 @@ export class OwnedOrInjected {
42
42
  * crawler-built defaults, `false` for user-injected instances.
43
43
  */
44
44
  get isOwned() {
45
- return this._owned;
45
+ return this.#owned;
46
46
  }
47
47
  /**
48
48
  * Whether a value is currently available. `false` for an owned slot whose default hasn't been built yet
49
49
  * (e.g. a lazily-opened request queue before its first use).
50
50
  */
51
51
  get isPresent() {
52
- return this._present;
52
+ return this.#present;
53
53
  }
54
54
  /**
55
55
  * The resolved instance, typed as the public `Injected` type. Throws if the value is not present yet — callers that
56
56
  * expect a lazily-filled owned slot should read {@link OwnedOrInjected.maybeValue|`maybeValue`} instead.
57
57
  */
58
58
  get value() {
59
- if (!this._present) {
59
+ if (!this.#present) {
60
60
  throw new Error('OwnedOrInjected value is not initialized yet');
61
61
  }
62
- return this._value;
62
+ return this.#value;
63
63
  }
64
64
  /**
65
65
  * The resolved instance, or `undefined` when a lazily-filled owned slot hasn't been built yet. The non-throwing
@@ -67,7 +67,7 @@ export class OwnedOrInjected {
67
67
  * a possibly-empty slot without the `isPresent ? value : …` dance.
68
68
  */
69
69
  get maybeValue() {
70
- return this._present ? this._value : undefined;
70
+ return this.#present ? this.#value : undefined;
71
71
  }
72
72
  /**
73
73
  * Fills the (owned) slot with the crawler-built default, returning it for convenience. Only valid on an owned,
@@ -75,14 +75,14 @@ export class OwnedOrInjected {
75
75
  * would silently orphan the previous instance's lifecycle).
76
76
  */
77
77
  set(value) {
78
- if (!this._owned) {
78
+ if (!this.#owned) {
79
79
  throw new Error('Cannot set() a borrowed OwnedOrInjected value');
80
80
  }
81
- if (this._present) {
81
+ if (this.#present) {
82
82
  throw new Error('OwnedOrInjected value is already initialized');
83
83
  }
84
- this._value = value;
85
- this._present = true;
84
+ this.#value = value;
85
+ this.#present = true;
86
86
  return value;
87
87
  }
88
88
  /**
@@ -90,9 +90,9 @@ export class OwnedOrInjected {
90
90
  * owns a present instance — a no-op for a borrowed instance or an owned-but-not-yet-built slot.
91
91
  */
92
92
  async ifOwned(fn) {
93
- if (!this._owned || !this._present) {
93
+ if (!this.#owned || !this.#present) {
94
94
  return undefined;
95
95
  }
96
- return fn(this._value);
96
+ return fn(this.#value);
97
97
  }
98
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/core",
3
- "version": "4.0.0-beta.104",
3
+ "version": "4.0.0-beta.106",
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"
@@ -52,9 +52,9 @@
52
52
  "@apify/log": "^2.5.18",
53
53
  "@apify/timeout": "^0.4.4",
54
54
  "@apify/utilities": "^2.15.5",
55
- "@crawlee/fs-storage": "4.0.0-beta.104",
56
- "@crawlee/types": "4.0.0-beta.104",
57
- "@crawlee/utils": "4.0.0-beta.104",
55
+ "@crawlee/fs-storage": "4.0.0-beta.106",
56
+ "@crawlee/types": "4.0.0-beta.106",
57
+ "@crawlee/utils": "4.0.0-beta.106",
58
58
  "@sapphire/async-queue": "^1.5.5",
59
59
  "@sapphire/shapeshift": "^4.0.0",
60
60
  "@vladfrangu/async_event_emitter": "^2.4.6",
@@ -78,5 +78,5 @@
78
78
  }
79
79
  }
80
80
  },
81
- "gitHead": "1c761e689e56ac06b67fc4f1dc091f693e024d12"
81
+ "gitHead": "c622f1fc65e65221ea245817c58ecc0ffb4a5cb0"
82
82
  }
@@ -70,10 +70,8 @@ export interface IProxyConfiguration {
70
70
  * @category Scaling
71
71
  */
72
72
  export declare class ProxyConfiguration implements IProxyConfiguration {
73
+ #private;
73
74
  readonly isManInTheMiddle = false;
74
- private nextCustomUrlIndex;
75
- private proxyUrls?;
76
- private newUrlFunction?;
77
75
  /**
78
76
  * Creates a {@link ProxyConfiguration} instance based on the provided options. Proxy servers are used to prevent target websites from
79
77
  * blocking your crawlers based on IP address rate limits or blacklists. Setting proxy configuration in your crawlers automatically configures
@@ -29,9 +29,9 @@ import ow from 'ow';
29
29
  */
30
30
  export class ProxyConfiguration {
31
31
  isManInTheMiddle = false;
32
- nextCustomUrlIndex = 0;
33
- proxyUrls;
34
- newUrlFunction;
32
+ #nextCustomUrlIndex = 0;
33
+ #proxyUrls;
34
+ #newUrlFunction;
35
35
  /**
36
36
  * Creates a {@link ProxyConfiguration} instance based on the provided options. Proxy servers are used to prevent target websites from
37
37
  * blocking your crawlers based on IP address rate limits or blacklists. Setting proxy configuration in your crawlers automatically configures
@@ -67,8 +67,8 @@ export class ProxyConfiguration {
67
67
  this.throwCannotCombineCustomMethods();
68
68
  if (!proxyUrls && !newUrlFunction && validateRequired)
69
69
  this.throwNoOptionsProvided();
70
- this.proxyUrls = proxyUrls;
71
- this.newUrlFunction = newUrlFunction;
70
+ this.#proxyUrls = proxyUrls;
71
+ this.#newUrlFunction = newUrlFunction;
72
72
  }
73
73
  /**
74
74
  * This function creates a new {@link ProxyInfo} info object.
@@ -99,19 +99,19 @@ export class ProxyConfiguration {
99
99
  * For example, `http://bob:password123@proxy.example.com:8000`
100
100
  */
101
101
  async newUrl(options) {
102
- if (this.newUrlFunction) {
102
+ if (this.#newUrlFunction) {
103
103
  return (await this.callNewUrlFunction({ request: options?.request })) ?? undefined;
104
104
  }
105
105
  return this.handleProxyUrlsList() ?? undefined;
106
106
  }
107
107
  handleProxyUrlsList() {
108
- return this.proxyUrls[this.nextCustomUrlIndex++ % this.proxyUrls.length];
108
+ return this.#proxyUrls[this.#nextCustomUrlIndex++ % this.#proxyUrls.length];
109
109
  }
110
110
  /**
111
111
  * Calls the custom newUrlFunction and checks format of its return value
112
112
  */
113
113
  async callNewUrlFunction(options) {
114
- const proxyUrl = await this.newUrlFunction(options);
114
+ const proxyUrl = await this.#newUrlFunction(options);
115
115
  try {
116
116
  if (proxyUrl) {
117
117
  new URL(proxyUrl); // eslint-disable-line no-new
@@ -59,16 +59,7 @@ export interface RecoverableStateOptions<TStateModel = Record<string, unknown>>
59
59
  * The class automatically hooks into the event system to persist state when needed.
60
60
  */
61
61
  export declare class RecoverableState<TStateModel = Record<string, unknown>> {
62
- private readonly defaultState;
63
- private state;
64
- private readonly persistenceEnabled;
65
- private readonly persistStateKey;
66
- private readonly persistStateKvsName?;
67
- private readonly persistStateKvsId?;
68
- private keyValueStore;
69
- private readonly log;
70
- private readonly serialize;
71
- private readonly deserialize;
62
+ #private;
72
63
  /**
73
64
  * Initialize a new recoverable state object.
74
65
  *