@crawlee/core 4.0.0-beta.99 → 4.0.0-rc.1

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 (133) hide show
  1. package/README.md +1 -1
  2. package/configuration.d.ts +16 -47
  3. package/configuration.js +13 -25
  4. package/debug.js +4 -4
  5. package/errors.d.ts +28 -38
  6. package/errors.js +33 -47
  7. package/events/event_manager.d.ts +2 -2
  8. package/events/event_manager.js +7 -6
  9. package/events/index.d.ts +1 -0
  10. package/events/local_event_manager.d.ts +1 -8
  11. package/events/local_event_manager.js +13 -13
  12. package/events/system_info.d.ts +38 -0
  13. package/index.d.ts +2 -8
  14. package/index.js +4 -8
  15. package/internal.d.ts +8 -0
  16. package/internal.js +9 -0
  17. package/log.d.ts +10 -11
  18. package/log.js +52 -20
  19. package/memory-storage/memory-storage.d.ts +15 -18
  20. package/memory-storage/memory-storage.js +80 -58
  21. package/memory-storage/resource-clients/dataset.d.ts +1 -6
  22. package/memory-storage/resource-clients/dataset.js +23 -31
  23. package/memory-storage/resource-clients/key-value-store.d.ts +1 -10
  24. package/memory-storage/resource-clients/key-value-store.js +43 -67
  25. package/memory-storage/resource-clients/request-queue.d.ts +1 -42
  26. package/memory-storage/resource-clients/request-queue.js +109 -117
  27. package/owned_or_injected.d.ts +1 -3
  28. package/owned_or_injected.js +17 -17
  29. package/package.json +17 -20
  30. package/proxy_configuration.d.ts +21 -26
  31. package/proxy_configuration.js +35 -25
  32. package/recoverable_state.d.ts +104 -47
  33. package/recoverable_state.js +199 -74
  34. package/request.d.ts +20 -107
  35. package/request.js +78 -244
  36. package/serialization.js +17 -16
  37. package/service_locator.d.ts +22 -10
  38. package/service_locator.js +59 -48
  39. package/storages/batched_adds.d.ts +37 -0
  40. package/storages/batched_adds.js +73 -0
  41. package/storages/dataset.d.ts +13 -8
  42. package/storages/dataset.js +149 -40
  43. package/storages/index.d.ts +4 -4
  44. package/storages/index.js +2 -4
  45. package/storages/key_value_store.d.ts +16 -35
  46. package/storages/key_value_store.js +223 -110
  47. package/storages/key_value_store_codec.js +6 -11
  48. package/storages/request_dedup_cache.d.ts +1 -4
  49. package/storages/request_dedup_cache.js +15 -15
  50. package/storages/request_list.d.ts +9 -104
  51. package/storages/request_list.js +236 -233
  52. package/storages/request_loader.d.ts +49 -18
  53. package/storages/request_loader.js +36 -1
  54. package/storages/request_manager.d.ts +86 -0
  55. package/storages/request_manager_tandem.d.ts +14 -38
  56. package/storages/request_manager_tandem.js +67 -64
  57. package/storages/request_queue.d.ts +23 -50
  58. package/storages/request_queue.js +371 -226
  59. package/storages/storage_instance_manager.d.ts +2 -4
  60. package/storages/storage_instance_manager.js +21 -21
  61. package/storages/storage_stats.d.ts +1 -1
  62. package/storages/storage_stats.js +4 -4
  63. package/storages/transaction.d.ts +270 -0
  64. package/storages/transaction.js +296 -0
  65. package/storages/utils.d.ts +6 -3
  66. package/storages/utils.js +11 -2
  67. package/system-info/runtime.js +7 -7
  68. package/url.d.ts +9 -0
  69. package/url.js +11 -0
  70. package/validators.d.ts +23 -25
  71. package/validators.js +14 -25
  72. package/autoscaling/autoscaled_pool.d.ts +0 -213
  73. package/autoscaling/autoscaled_pool.js +0 -378
  74. package/autoscaling/client_load_signal.d.ts +0 -59
  75. package/autoscaling/client_load_signal.js +0 -73
  76. package/autoscaling/concurrency_system.d.ts +0 -283
  77. package/autoscaling/concurrency_system.js +0 -350
  78. package/autoscaling/cpu_load_signal.d.ts +0 -44
  79. package/autoscaling/cpu_load_signal.js +0 -46
  80. package/autoscaling/event_loop_load_signal.d.ts +0 -54
  81. package/autoscaling/event_loop_load_signal.js +0 -60
  82. package/autoscaling/index.d.ts +0 -9
  83. package/autoscaling/index.js +0 -9
  84. package/autoscaling/load_signal.d.ts +0 -99
  85. package/autoscaling/load_signal.js +0 -103
  86. package/autoscaling/memory_load_signal.d.ts +0 -56
  87. package/autoscaling/memory_load_signal.js +0 -106
  88. package/autoscaling/snapshotter.d.ts +0 -87
  89. package/autoscaling/snapshotter.js +0 -67
  90. package/autoscaling/system_status.d.ts +0 -161
  91. package/autoscaling/system_status.js +0 -139
  92. package/autoscaling/weighted_avg.d.ts +0 -5
  93. package/autoscaling/weighted_avg.js +0 -14
  94. package/cookie_utils.d.ts +0 -44
  95. package/cookie_utils.js +0 -122
  96. package/crawlers/context_pipeline.d.ts +0 -70
  97. package/crawlers/context_pipeline.js +0 -122
  98. package/crawlers/crawler_commons.d.ts +0 -257
  99. package/crawlers/crawler_commons.js +0 -107
  100. package/crawlers/error_snapshotter.d.ts +0 -59
  101. package/crawlers/error_snapshotter.js +0 -117
  102. package/crawlers/error_tracker.d.ts +0 -54
  103. package/crawlers/error_tracker.js +0 -308
  104. package/crawlers/index.d.ts +0 -5
  105. package/crawlers/index.js +0 -5
  106. package/crawlers/internals/types.d.ts +0 -7
  107. package/crawlers/statistics.d.ts +0 -209
  108. package/crawlers/statistics.js +0 -350
  109. package/enqueue_links/enqueue_links.d.ts +0 -264
  110. package/enqueue_links/enqueue_links.js +0 -271
  111. package/enqueue_links/index.d.ts +0 -2
  112. package/enqueue_links/index.js +0 -2
  113. package/enqueue_links/shared.d.ts +0 -83
  114. package/enqueue_links/shared.js +0 -221
  115. package/router.d.ts +0 -309
  116. package/router.js +0 -309
  117. package/session_pool/consts.d.ts +0 -3
  118. package/session_pool/consts.js +0 -3
  119. package/session_pool/errors.d.ts +0 -7
  120. package/session_pool/errors.js +0 -11
  121. package/session_pool/fingerprint.d.ts +0 -9
  122. package/session_pool/fingerprint.js +0 -30
  123. package/session_pool/index.d.ts +0 -4
  124. package/session_pool/index.js +0 -4
  125. package/session_pool/session.d.ts +0 -161
  126. package/session_pool/session.js +0 -218
  127. package/session_pool/session_pool.d.ts +0 -246
  128. package/session_pool/session_pool.js +0 -386
  129. package/storages/access_checking.d.ts +0 -12
  130. package/storages/access_checking.js +0 -17
  131. package/storages/sitemap_request_loader.d.ts +0 -249
  132. package/storages/sitemap_request_loader.js +0 -432
  133. /package/{crawlers/internals/types.js → events/system_info.js} +0 -0
@@ -1,12 +1,17 @@
1
- import { stringify } from 'csv-stringify/sync';
2
- import ow from 'ow';
1
+ import { z } from 'zod';
2
+ import { tryCancel } from '@apify/timeout';
3
3
  import { Configuration } from '../configuration.js';
4
4
  import { serviceLocator } from '../service_locator.js';
5
- import { checkStorageAccess } from './access_checking.js';
5
+ import { parseArgument, schemas, validators } from '../validators.js';
6
+ import { activeStorageTransaction, rejectOperationInTransaction, snapshotValue } from './transaction.js';
6
7
  import { KeyValueStore } from './key_value_store.js';
7
8
  import { StorageStatsTracker } from './storage_stats.js';
8
9
  import { resolveStorageIdentifier } from './storage_instance_manager.js';
9
10
  import { createDualIterable, purgeDefaultStorages } from './utils.js';
11
+ const openOptionsSchema = z.strictObject({
12
+ configuration: z.instanceof(Configuration).optional(),
13
+ storageBackend: validators.storageBackend.optional(),
14
+ });
10
15
  /** @internal */
11
16
  export const DATASET_ITERATORS_DEFAULT_LIMIT = 10000;
12
17
  /**
@@ -86,9 +91,9 @@ export class Dataset {
86
91
  configuration;
87
92
  id;
88
93
  name;
94
+ // oxlint-disable-next-line crawlee/prefer-private-fields -- tests spy on the backend directly
89
95
  backend;
90
- log;
91
- statsTracker = new StorageStatsTracker({
96
+ #statsTracker = new StorageStatsTracker({
92
97
  readCount: 0,
93
98
  writeCount: 0,
94
99
  });
@@ -100,14 +105,13 @@ export class Dataset {
100
105
  this.id = options.metadata.id;
101
106
  this.name = options.metadata.name;
102
107
  this.backend = options.backend;
103
- this.log = serviceLocator.getLogger().child({ prefix: 'Dataset' });
104
108
  }
105
109
  /**
106
110
  * Backend-independent usage counters tracked for this dataset (read / write operations issued to
107
111
  * the underlying storage backend). Counted per backend call.
108
112
  */
109
113
  get stats() {
110
- return this.statsTracker.current;
114
+ return this.#statsTracker.current;
111
115
  }
112
116
  /**
113
117
  * Stores an object or an array of objects to the dataset.
@@ -121,24 +125,34 @@ export class Dataset {
121
125
  * The objects must be serializable to JSON.
122
126
  */
123
127
  async pushData(data) {
124
- checkStorageAccess();
125
- ow(data, 'data', ow.object);
128
+ tryCancel();
129
+ const transaction = activeStorageTransaction();
130
+ parseArgument(data, schemas.anyObject);
126
131
  // Normalize to array and validate each item
127
132
  const items = Array.isArray(data) ? data : [data];
128
133
  for (let i = 0; i < items.length; i++) {
129
134
  assertJsonSerializable(items[i], i);
130
135
  }
131
- this.statsTracker.add('writeCount');
136
+ if (transaction) {
137
+ // One snapshot serves both the reads and the commit replay, so the two cannot disagree.
138
+ transaction.recordJournalEntry({
139
+ type: 'dataset',
140
+ participant: this,
141
+ storageId: this.id,
142
+ items: snapshotValue(items),
143
+ recordedAt: new Date(),
144
+ });
145
+ return;
146
+ }
147
+ this.#statsTracker.add('writeCount');
132
148
  await this.backend.pushData(items);
133
149
  }
134
150
  /**
135
151
  * Returns {@link DatasetContent} object holding the items in the dataset based on the provided parameters.
136
152
  */
137
153
  async getData(options = {}) {
138
- checkStorageAccess();
139
154
  try {
140
- this.statsTracker.add('readCount');
141
- return await this.backend.getData(options);
155
+ return await this.#readPage(options);
142
156
  }
143
157
  catch (e) {
144
158
  const error = e;
@@ -148,14 +162,95 @@ export class Dataset {
148
162
  throw e;
149
163
  }
150
164
  }
165
+ /**
166
+ * The single transaction-aware page read all dataset read paths go through — both `getData()` and
167
+ * the private `fetchPages()`. Returns the real page concatenated with the current transaction's
168
+ * buffered items, with `offset` / `limit` / `desc` windowing applied across the concatenation.
169
+ */
170
+ async #readPage(options) {
171
+ const buffered = this.#bufferedJournalEntries()?.flatMap((entry) => entry.items);
172
+ // Every branch below hits the backend exactly once.
173
+ this.#statsTracker.add('readCount');
174
+ if (!buffered?.length) {
175
+ return this.backend.getData(options);
176
+ }
177
+ const { offset = 0, limit, desc = false } = options;
178
+ if (!desc) {
179
+ const realPage = await this.backend.getData(options);
180
+ // Buffered items sit past `realPage.total`, so the window bounds must come from that - not
181
+ // from the page's shortfall, which `skipEmpty` produces without exhausting the real items.
182
+ const bufferedStart = Math.max(0, offset - realPage.total);
183
+ const bufferedEnd = limit === undefined ? buffered.length : Math.max(0, offset + limit - realPage.total);
184
+ const items = [...realPage.items, ...buffered.slice(bufferedStart, bufferedEnd)];
185
+ return {
186
+ items,
187
+ total: realPage.total + buffered.length,
188
+ offset,
189
+ // A caller that passed no limit wants everything, so the backend-reported `limit` is
190
+ // passed through - backends are free to report a page size or a sentinel there.
191
+ limit: limit ?? realPage.limit,
192
+ count: items.length,
193
+ desc,
194
+ };
195
+ }
196
+ // Descending order: the buffered items are the newest, so they come first, reversed.
197
+ const reversedBuffer = [...buffered].reverse();
198
+ const fromBuffer = limit === undefined ? reversedBuffer.slice(offset) : reversedBuffer.slice(offset, offset + limit);
199
+ const needed = limit === undefined ? Infinity : limit - fromBuffer.length;
200
+ if (needed <= 0) {
201
+ // The whole window is served from the buffer; only the real total is missing.
202
+ const { itemCount } = await this.backend.getMetadata();
203
+ return {
204
+ items: fromBuffer,
205
+ total: itemCount + buffered.length,
206
+ offset,
207
+ limit: limit,
208
+ count: fromBuffer.length,
209
+ desc,
210
+ };
211
+ }
212
+ const realPage = await this.backend.getData({
213
+ ...options,
214
+ offset: Math.max(0, offset - buffered.length),
215
+ ...(limit === undefined ? {} : { limit: needed }),
216
+ });
217
+ return {
218
+ items: [...fromBuffer, ...realPage.items],
219
+ total: realPage.total + buffered.length,
220
+ offset,
221
+ limit: limit ?? realPage.limit,
222
+ count: fromBuffer.length + realPage.items.length,
223
+ desc,
224
+ };
225
+ }
226
+ /** The active transaction's buffered writes to this dataset, derived from its journal. */
227
+ #bufferedJournalEntries() {
228
+ const transaction = activeStorageTransaction();
229
+ return transaction?.journal.filter((entry) => entry.type === 'dataset' && entry.participant === this);
230
+ }
231
+ /** @internal */
232
+ async commitJournalEntries(entries) {
233
+ const items = [];
234
+ for (const entry of entries) {
235
+ if (entry.type === 'dataset') {
236
+ items.push(...entry.items);
237
+ }
238
+ }
239
+ // One backend call with all journaled items, in order - as close to atomic as the backend allows.
240
+ // Straight to the backend: the items were validated and snapshotted at write time.
241
+ if (items.length > 0) {
242
+ this.#statsTracker.add('writeCount');
243
+ await this.backend.pushData(items);
244
+ }
245
+ }
151
246
  /**
152
247
  * Returns all the data from the dataset. This will iterate through the whole dataset
153
248
  * via the `listItems()` client method, which gives you only paginated results.
154
249
  */
155
250
  async export(options = {}) {
156
- checkStorageAccess();
251
+ tryCancel();
157
252
  const items = [];
158
- for await (const page of this.fetchPages(options)) {
253
+ for await (const page of this.#fetchPages(options)) {
159
254
  items.push(...page.items);
160
255
  }
161
256
  return items;
@@ -179,6 +274,7 @@ export class Dataset {
179
274
  const keys = options?.collectAllKeys
180
275
  ? Array.from(new Set(items.flatMap(Object.keys)))
181
276
  : Object.keys(items[0]);
277
+ const { stringify } = await import('csv-stringify/sync');
182
278
  const value = stringify([
183
279
  keys,
184
280
  ...items.map((item) => {
@@ -219,7 +315,7 @@ export class Dataset {
219
315
  * @param [options] An optional options object where you can provide the dataset and target KVS name.
220
316
  */
221
317
  static async exportToJSON(key, options) {
222
- checkStorageAccess();
318
+ tryCancel();
223
319
  const dataset = await this.open(options?.fromDataset);
224
320
  await dataset.exportToJSON(key, options);
225
321
  }
@@ -230,7 +326,7 @@ export class Dataset {
230
326
  * @param [options] An optional options object where you can provide the dataset and target KVS name.
231
327
  */
232
328
  static async exportToCSV(key, options) {
233
- checkStorageAccess();
329
+ tryCancel();
234
330
  const dataset = await this.open(options?.fromDataset);
235
331
  await dataset.exportToCSV(key, options);
236
332
  }
@@ -252,8 +348,17 @@ export class Dataset {
252
348
  * @throws If the underlying storage no longer exists (e.g. it was deleted externally).
253
349
  */
254
350
  async getInfo() {
255
- checkStorageAccess();
256
- return this.backend.getMetadata();
351
+ const buffered = this.#bufferedJournalEntries();
352
+ const metadata = await this.backend.getMetadata();
353
+ if (buffered?.length) {
354
+ const lastWriteAt = buffered[buffered.length - 1].recordedAt;
355
+ return {
356
+ ...metadata,
357
+ itemCount: metadata.itemCount + buffered.reduce((sum, entry) => sum + entry.items.length, 0),
358
+ modifiedAt: metadata.modifiedAt > lastWriteAt ? metadata.modifiedAt : lastWriteAt,
359
+ };
360
+ }
361
+ return metadata;
257
362
  }
258
363
  /**
259
364
  * Iterates over dataset items, yielding each in turn to an `iteratee` function.
@@ -276,7 +381,7 @@ export class Dataset {
276
381
  * @default 0
277
382
  */
278
383
  async forEach(iteratee, options = {}, index = 0) {
279
- checkStorageAccess();
384
+ tryCancel();
280
385
  if (!options.offset)
281
386
  options.offset = 0;
282
387
  if (options.format && options.format !== 'json')
@@ -303,7 +408,7 @@ export class Dataset {
303
408
  * @param [options] All `map()` parameters.
304
409
  */
305
410
  async map(iteratee, options = {}) {
306
- checkStorageAccess();
411
+ tryCancel();
307
412
  const result = [];
308
413
  await this.forEach(async (item, index) => {
309
414
  const res = await iteratee(item, index);
@@ -312,7 +417,7 @@ export class Dataset {
312
417
  return result;
313
418
  }
314
419
  async reduce(iteratee, memo, options = {}) {
315
- checkStorageAccess();
420
+ tryCancel();
316
421
  let currentMemo = memo;
317
422
  const wrappedFunc = async (item, index) => {
318
423
  if (index === 0 && currentMemo === undefined) {
@@ -327,16 +432,16 @@ export class Dataset {
327
432
  await this.forEach(wrappedFunc, options);
328
433
  return currentMemo;
329
434
  }
330
- async *fetchEntryPages(options) {
435
+ async *#fetchEntryPages(options) {
331
436
  let index = options.offset ?? 0;
332
- for await (const page of this.fetchPages(options)) {
437
+ for await (const page of this.#fetchPages(options)) {
333
438
  yield {
334
439
  ...page,
335
440
  items: page.items.map((item) => [index++, item]),
336
441
  };
337
442
  }
338
443
  }
339
- async *fetchPages(options, pageSize = DATASET_ITERATORS_DEFAULT_LIMIT) {
444
+ async *#fetchPages(options, pageSize = DATASET_ITERATORS_DEFAULT_LIMIT) {
340
445
  let offset = options.offset ?? 0;
341
446
  const totalLimit = options.limit;
342
447
  let yielded = 0;
@@ -344,8 +449,7 @@ export class Dataset {
344
449
  const fetchLimit = totalLimit !== undefined ? Math.min(pageSize, totalLimit - yielded) : pageSize;
345
450
  if (fetchLimit <= 0)
346
451
  break;
347
- this.statsTracker.add('readCount');
348
- const page = await this.backend.getData({ ...options, offset, limit: fetchLimit });
452
+ const page = await this.#readPage({ ...options, offset, limit: fetchLimit });
349
453
  yield page;
350
454
  yielded += page.items.length;
351
455
  if (page.items.length < fetchLimit || offset + page.items.length >= page.total)
@@ -377,9 +481,9 @@ export class Dataset {
377
481
  * @param options Options for the iteration.
378
482
  */
379
483
  values(options = {}) {
380
- checkStorageAccess();
484
+ tryCancel();
381
485
  return createDualIterable({
382
- createPages: () => this.fetchPages(options),
486
+ createPages: () => this.#fetchPages(options),
383
487
  extractItems: (page) => page.items,
384
488
  });
385
489
  }
@@ -407,9 +511,9 @@ export class Dataset {
407
511
  * @param options Options for the iteration.
408
512
  */
409
513
  entries(options = {}) {
410
- checkStorageAccess();
514
+ tryCancel();
411
515
  return createDualIterable({
412
- createPages: () => this.fetchEntryPages(options),
516
+ createPages: () => this.#fetchEntryPages(options),
413
517
  extractItems: (page) => page.items,
414
518
  });
415
519
  }
@@ -433,10 +537,18 @@ export class Dataset {
433
537
  * depending on the mode of operation.
434
538
  */
435
539
  async drop() {
436
- checkStorageAccess();
540
+ rejectOperationInTransaction('Dataset.drop()');
437
541
  await this.backend.drop();
438
542
  serviceLocator.getStorageInstanceManager().removeFromCache(this);
439
543
  }
544
+ /**
545
+ * Removes all items from the dataset but keeps the dataset itself, along with its
546
+ * {@link Dataset.id|`id`} and {@link Dataset.name|`name`}.
547
+ */
548
+ async purge() {
549
+ rejectOperationInTransaction('Dataset.purge()');
550
+ await this.backend.purge();
551
+ }
440
552
  /**
441
553
  * Opens a dataset and returns a promise resolving to an instance of the {@link Dataset} class.
442
554
  *
@@ -453,14 +565,11 @@ export class Dataset {
453
565
  * @param [options] Storage manager options.
454
566
  */
455
567
  static async open(identifier, options = {}) {
456
- checkStorageAccess();
457
- ow(options, ow.object.exactShape({
458
- configuration: ow.optional.object.instanceOf(Configuration),
459
- storageBackend: ow.optional.object,
460
- }));
461
- options.configuration ??= Configuration.getGlobalConfiguration();
462
- const storageBackend = options.storageBackend ?? serviceLocator.getStorageBackend();
463
- await purgeDefaultStorages({ onlyPurgeOnce: true, storageBackend, configuration: options.configuration });
568
+ tryCancel();
569
+ const parsedOptions = parseArgument(options, openOptionsSchema);
570
+ const configuration = parsedOptions.configuration ?? Configuration.getGlobalConfiguration();
571
+ const storageBackend = parsedOptions.storageBackend ?? serviceLocator.getStorageBackend();
572
+ await purgeDefaultStorages({ onlyPurgeOnce: true, storageBackend, configuration });
464
573
  const resolved = await resolveStorageIdentifier(identifier, storageBackend, 'Dataset');
465
574
  return serviceLocator.getStorageInstanceManager().openStorage(this, {
466
575
  ...resolved,
@@ -5,9 +5,9 @@ export * from './request_list.js';
5
5
  export type * from './request_loader.js';
6
6
  export type * from './request_manager.js';
7
7
  export * from './request_queue.js';
8
- export * from './storage_instance_manager.js';
9
- export * from './storage_stats.js';
8
+ export type { DefaultStorageIdentifier, ExplicitStorageIdentifier, IStorage, StorageIdentifier, } from './storage_instance_manager.js';
9
+ export { StorageInstanceManager } from './storage_instance_manager.js';
10
+ export type { DatasetStats, KeyValueStoreStats, RequestQueueStats } from './storage_stats.js';
10
11
  export * from './utils.js';
11
- export * from './access_checking.js';
12
- export * from './sitemap_request_loader.js';
12
+ export * from './transaction.js';
13
13
  export * from './request_manager_tandem.js';
package/storages/index.js CHANGED
@@ -3,9 +3,7 @@ export * from './key_value_store.js';
3
3
  export * from './key_value_store_codec.js';
4
4
  export * from './request_list.js';
5
5
  export * from './request_queue.js';
6
- export * from './storage_instance_manager.js';
7
- export * from './storage_stats.js';
6
+ export { StorageInstanceManager } from './storage_instance_manager.js';
8
7
  export * from './utils.js';
9
- export * from './access_checking.js';
10
- export * from './sitemap_request_loader.js';
8
+ export * from './transaction.js';
11
9
  export * from './request_manager_tandem.js';
@@ -1,5 +1,6 @@
1
1
  import type { Awaitable, Dictionary, KeyValueStoreBackend, KeyValueStoreInfo } from '@crawlee/types';
2
2
  import { Configuration } from '../configuration.js';
3
+ import type { JournalEntry } from './transaction.js';
3
4
  import type { KeyValueStoreStats } from './storage_stats.js';
4
5
  import type { StorageOpenOptions } from './utils.js';
5
6
  import type { StorageIdentifier } from './storage_instance_manager.js';
@@ -19,8 +20,6 @@ import type { StorageIdentifier } from './storage_instance_manager.js';
19
20
  * To access the default key-value store directly, you can use the
20
21
  * {@link KeyValueStore.getValue} and {@link KeyValueStore.setValue} convenience functions.
21
22
  *
22
- * To access the input, you can also use the {@link KeyValueStore.getInput} convenience function.
23
- *
24
23
  * `KeyValueStore` stores its data on a local disk.
25
24
  *
26
25
  * If the `CRAWLEE_STORAGE_DIR` environment variable is set, the data is stored in
@@ -28,15 +27,14 @@ import type { StorageIdentifier } from './storage_instance_manager.js';
28
27
  * ```
29
28
  * {CRAWLEE_STORAGE_DIR}/key_value_stores/{STORE_ID}/{INDEX}.{EXT}
30
29
  * ```
31
- * Note that `{STORE_ID}` is the name or ID of the key-value store. The default key-value store has ID: `default`,
32
- * unless you override it by setting the `CRAWLEE_DEFAULT_KEY_VALUE_STORE_ID` environment variable.
30
+ * Note that `{STORE_ID}` is the name or ID of the key-value store. The default key-value store has ID: `default`.
33
31
  * The `{KEY}` is the key of the record and `{EXT}` corresponds to the MIME content type of the data value.
34
32
  *
35
33
  * **Example usage:**
36
34
  *
37
35
  * ```javascript
38
36
  * // Get crawler input from the default key-value store.
39
- * const input = await KeyValueStore.getInput();
37
+ * const input = await KeyValueStore.getValue('INPUT');
40
38
  * // Get some value from the default key-value store.
41
39
  * const otherValue = await KeyValueStore.getValue('my-key');
42
40
  *
@@ -60,14 +58,11 @@ import type { StorageIdentifier } from './storage_instance_manager.js';
60
58
  * @category Result Stores
61
59
  */
62
60
  export declare class KeyValueStore {
61
+ #private;
63
62
  readonly configuration: Configuration;
64
63
  readonly id: string;
65
64
  readonly name?: string;
66
- private readonly backend;
67
- private persistStateEventStarted;
68
- /** Cache for persistent (auto-saved) values. When we try to set such value, the cache will be updated automatically. */
69
- private readonly cache;
70
- private readonly statsTracker;
65
+ readonly backend: KeyValueStoreBackend;
71
66
  /**
72
67
  * @internal
73
68
  */
@@ -176,9 +171,6 @@ export declare class KeyValueStore {
176
171
  */
177
172
  recordExists(key: string): Promise<boolean>;
178
173
  getAutoSavedValue<T extends Dictionary = Dictionary>(key: string, defaultValue?: T): Promise<T>;
179
- private ensurePersistStateEvent;
180
- private fetchKeyValuePages;
181
- private fetchKeyPages;
182
174
  /**
183
175
  * Saves or deletes a record in the key-value store.
184
176
  * The function returns a promise that resolves once the record has been saved or deleted.
@@ -223,11 +215,18 @@ export declare class KeyValueStore {
223
215
  * @param [options] Record options.
224
216
  */
225
217
  setValue<T>(key: string, value: T | null, options?: RecordOptions): Promise<void>;
218
+ /** @internal */
219
+ commitJournalEntries(entries: JournalEntry[]): Promise<void>;
226
220
  /**
227
221
  * Removes the key-value store either from the Apify cloud storage or from the local directory,
228
222
  * depending on the mode of operation.
229
223
  */
230
224
  drop(): Promise<void>;
225
+ /**
226
+ * Removes all records from the store but keeps the store itself, along with its
227
+ * {@link KeyValueStore.id|`id`} and {@link KeyValueStore.name|`name`}.
228
+ */
229
+ purge(): Promise<void>;
231
230
  /** @internal */
232
231
  clearCache(): void;
233
232
  /**
@@ -340,7 +339,9 @@ export declare class KeyValueStore {
340
339
  /**
341
340
  * Returns a file URL for the given key.
342
341
  *
343
- * If the record does not exist or has no associated file path (i.e., it is not stored as a file), returns `undefined`.
342
+ * The URL is derived from the key, so it is also returned for a record that does not exist (yet) —
343
+ * including one written earlier in an uncommitted storage transaction. Returns `undefined` only when
344
+ * the storage has no file URLs at all (e.g. the in-memory storage).
344
345
  *
345
346
  * @param key The key of the record to generate the public URL for.
346
347
  */
@@ -471,27 +472,6 @@ export declare class KeyValueStore {
471
472
  * @ignore
472
473
  */
473
474
  static setValue<T>(key: string, value: T | null, options?: RecordOptions): Promise<void>;
474
- /**
475
- * Gets the crawler input value from the default {@link KeyValueStore} associated with the current crawler run.
476
- *
477
- * The input is read from the default {@link KeyValueStore} under the configured input key
478
- * (`CRAWLEE_INPUT_KEY`, default `INPUT`).
479
- *
480
- * Note that the `getInput()` function does not cache the value read from the key-value store.
481
- * If you need to use the input multiple times in your crawler,
482
- * it is far more efficient to read it once and store it locally.
483
- *
484
- * For more information, see {@link KeyValueStore.open}
485
- * and {@link KeyValueStore.getValue}.
486
- *
487
- * @returns
488
- * Returns a promise that resolves to an object, string
489
- * or [`Buffer`](https://nodejs.org/api/buffer.html), depending
490
- * on the MIME content type of the record, or `null`
491
- * if the record is missing.
492
- * @ignore
493
- */
494
- static getInput<T = Dictionary | string | Buffer>(): Promise<T | null>;
495
475
  }
496
476
  /**
497
477
  * User-function used in the {@link KeyValueStore.forEachKey} method.
@@ -507,6 +487,7 @@ export interface KeyConsumer {
507
487
  size: number;
508
488
  }): Awaitable<void>;
509
489
  }
490
+ /** @internal */
510
491
  export interface KeyValueStoreOptions {
511
492
  /** Resolved metadata for the key-value store, as returned by the backend's `getMetadata()`. */
512
493
  metadata: KeyValueStoreInfo;