@crawlee/fs-storage 4.0.0-beta.105 → 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.
- package/package.json +3 -3
- package/resource-clients/dataset.d.ts +1 -2
- package/resource-clients/dataset.js +11 -11
- package/resource-clients/key-value-store.d.ts +1 -1
- package/resource-clients/key-value-store.js +16 -16
- package/resource-clients/request-queue.d.ts +1 -1
- package/resource-clients/request-queue.js +16 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/fs-storage",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.106",
|
|
4
4
|
"description": "A file-system storage implementation of the Apify API",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@crawlee/fs-storage-native": "0.1.5-beta.18",
|
|
46
|
-
"@crawlee/types": "4.0.0-beta.
|
|
46
|
+
"@crawlee/types": "4.0.0-beta.106",
|
|
47
47
|
"@sapphire/shapeshift": "^4.0.0"
|
|
48
48
|
},
|
|
49
49
|
"lerna": {
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "38186ba9ec1ab456b6c71ef9a9d45e675a9cd1e5"
|
|
57
57
|
}
|
|
@@ -21,10 +21,9 @@ export interface DatasetBackendOptions {
|
|
|
21
21
|
* the `@crawlee/types` interfaces.
|
|
22
22
|
*/
|
|
23
23
|
export declare class DatasetBackend<Data extends Dictionary = Dictionary> extends CachedIdClient implements storage.DatasetBackend<Data> {
|
|
24
|
+
#private;
|
|
24
25
|
readonly name?: string;
|
|
25
26
|
readonly cacheKey: string;
|
|
26
|
-
private readonly nativeBackend;
|
|
27
|
-
private readonly logger?;
|
|
28
27
|
constructor(options: DatasetBackendOptions);
|
|
29
28
|
get datasetDirectory(): string;
|
|
30
29
|
static create<Data extends Dictionary = Dictionary>(options: DatasetBackendOptions): Promise<DatasetBackend<Data>>;
|
|
@@ -19,17 +19,17 @@ const UNSUPPORTED_GET_DATA_OPTIONS = ['clean', 'fields', 'omit', 'skipHidden', '
|
|
|
19
19
|
export class DatasetBackend extends CachedIdClient {
|
|
20
20
|
name;
|
|
21
21
|
cacheKey;
|
|
22
|
-
nativeBackend;
|
|
23
|
-
logger;
|
|
22
|
+
#nativeBackend;
|
|
23
|
+
#logger;
|
|
24
24
|
constructor(options) {
|
|
25
25
|
super();
|
|
26
26
|
this.name = options.name;
|
|
27
27
|
this.cacheKey = options.cacheKey;
|
|
28
|
-
this
|
|
29
|
-
this
|
|
28
|
+
this.#nativeBackend = options.nativeBackend;
|
|
29
|
+
this.#logger = options.logger;
|
|
30
30
|
}
|
|
31
31
|
get datasetDirectory() {
|
|
32
|
-
return this
|
|
32
|
+
return this.#nativeBackend.pathToDataset;
|
|
33
33
|
}
|
|
34
34
|
static async create(options) {
|
|
35
35
|
const backend = new DatasetBackend(options);
|
|
@@ -37,22 +37,22 @@ export class DatasetBackend extends CachedIdClient {
|
|
|
37
37
|
return backend;
|
|
38
38
|
}
|
|
39
39
|
async getMetadata() {
|
|
40
|
-
return this
|
|
40
|
+
return this.#nativeBackend.getMetadata();
|
|
41
41
|
}
|
|
42
42
|
async drop() {
|
|
43
|
-
await this
|
|
43
|
+
await this.#nativeBackend.dropStorage();
|
|
44
44
|
}
|
|
45
45
|
async purge() {
|
|
46
|
-
await this
|
|
46
|
+
await this.#nativeBackend.purge();
|
|
47
47
|
}
|
|
48
48
|
async pushData(items) {
|
|
49
|
-
await this
|
|
49
|
+
await this.#nativeBackend.pushData(items);
|
|
50
50
|
}
|
|
51
51
|
async getData(options = {}) {
|
|
52
52
|
const passedOptions = options;
|
|
53
53
|
const ignored = UNSUPPORTED_GET_DATA_OPTIONS.filter((key) => passedOptions[key] !== undefined);
|
|
54
54
|
if (ignored.length > 0) {
|
|
55
|
-
this
|
|
55
|
+
this.#logger?.warning?.(`getData() options [${ignored.join(', ')}] are not supported by the file-system dataset ` +
|
|
56
56
|
`and were ignored. Only "offset", "limit" and "desc" are honored.`);
|
|
57
57
|
}
|
|
58
58
|
const { desc, limit, offset } = s
|
|
@@ -62,7 +62,7 @@ export class DatasetBackend extends CachedIdClient {
|
|
|
62
62
|
offset: s.number().int().optional(),
|
|
63
63
|
})
|
|
64
64
|
.parse(options);
|
|
65
|
-
const page = await this
|
|
65
|
+
const page = await this.#nativeBackend.getData(offset ?? 0, limit, desc ?? false, false);
|
|
66
66
|
return {
|
|
67
67
|
count: page.count,
|
|
68
68
|
desc: page.desc,
|
|
@@ -22,9 +22,9 @@ export interface KeyValueStoreBackendOptions {
|
|
|
22
22
|
* is the {@link KeyValueStore} frontend codec's job, not this backend's.
|
|
23
23
|
*/
|
|
24
24
|
export declare class KeyValueStoreBackend extends CachedIdClient implements storage.KeyValueStoreBackend {
|
|
25
|
+
#private;
|
|
25
26
|
readonly name?: string;
|
|
26
27
|
readonly cacheKey: string;
|
|
27
|
-
private readonly nativeBackend;
|
|
28
28
|
constructor(options: KeyValueStoreBackendOptions);
|
|
29
29
|
get keyValueStoreDirectory(): string;
|
|
30
30
|
static create(options: KeyValueStoreBackendOptions): Promise<KeyValueStoreBackend>;
|
|
@@ -46,15 +46,15 @@ const BARE_FILE_LOGICAL_KEYS = new Map(ALLOWED_BARE_FILES.flatMap((key) => BARE_
|
|
|
46
46
|
export class KeyValueStoreBackend extends CachedIdClient {
|
|
47
47
|
name;
|
|
48
48
|
cacheKey;
|
|
49
|
-
nativeBackend;
|
|
49
|
+
#nativeBackend;
|
|
50
50
|
constructor(options) {
|
|
51
51
|
super();
|
|
52
52
|
this.name = options.name;
|
|
53
53
|
this.cacheKey = options.cacheKey;
|
|
54
|
-
this
|
|
54
|
+
this.#nativeBackend = options.nativeBackend;
|
|
55
55
|
}
|
|
56
56
|
get keyValueStoreDirectory() {
|
|
57
|
-
return this
|
|
57
|
+
return this.#nativeBackend.pathToKvs;
|
|
58
58
|
}
|
|
59
59
|
static async create(options) {
|
|
60
60
|
const backend = new KeyValueStoreBackend(options);
|
|
@@ -62,13 +62,13 @@ export class KeyValueStoreBackend extends CachedIdClient {
|
|
|
62
62
|
return backend;
|
|
63
63
|
}
|
|
64
64
|
async getMetadata() {
|
|
65
|
-
return this
|
|
65
|
+
return this.#nativeBackend.getMetadata();
|
|
66
66
|
}
|
|
67
67
|
async drop() {
|
|
68
|
-
await this
|
|
68
|
+
await this.#nativeBackend.dropStorage();
|
|
69
69
|
}
|
|
70
70
|
async purge() {
|
|
71
|
-
await this
|
|
71
|
+
await this.#nativeBackend.purge();
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* Remove every record from the store except the run input. Used by
|
|
@@ -79,7 +79,7 @@ export class KeyValueStoreBackend extends CachedIdClient {
|
|
|
79
79
|
* filename the input might live under (`INPUT`, `INPUT.json`, `INPUT.txt`, `INPUT.bin`).
|
|
80
80
|
*/
|
|
81
81
|
async purgeExceptInput() {
|
|
82
|
-
await this
|
|
82
|
+
await this.#nativeBackend.purge(BARE_FILE_FALLBACKS.flatMap(({ extension }) => `INPUT${extension}`));
|
|
83
83
|
}
|
|
84
84
|
async listKeys(options = {}) {
|
|
85
85
|
const { prefix, exclusiveStartKey, limit } = s
|
|
@@ -94,7 +94,7 @@ export class KeyValueStoreBackend extends CachedIdClient {
|
|
|
94
94
|
// everything it needs off the filesystem index — no per-file reads — so this stays cheap.
|
|
95
95
|
// The native `listKeys` already returns a self-describing page (items + pagination cursors)
|
|
96
96
|
// matching the `KeyValueStoreListKeysResult` contract, so we only post-process the items.
|
|
97
|
-
const page = await this
|
|
97
|
+
const page = await this.#nativeBackend.listKeys(exclusiveStartKey, limit, prefix, LIST_BARE_FALLBACKS);
|
|
98
98
|
const presentKeys = new Set(page.items.map((record) => record.key));
|
|
99
99
|
// A bare value file is listed under its actual name (`INPUT.json`), which already round-trips
|
|
100
100
|
// through `getValue`/`recordExists`. The only collision is a tracked record occupying the
|
|
@@ -130,7 +130,7 @@ export class KeyValueStoreBackend extends CachedIdClient {
|
|
|
130
130
|
if (resolvedKey === undefined) {
|
|
131
131
|
return undefined;
|
|
132
132
|
}
|
|
133
|
-
return (await this
|
|
133
|
+
return (await this.#nativeBackend.getPublicUrl(resolvedKey)) ?? undefined;
|
|
134
134
|
}
|
|
135
135
|
/**
|
|
136
136
|
* Tests whether a record with the given key exists without retrieving its value.
|
|
@@ -146,8 +146,8 @@ export class KeyValueStoreBackend extends CachedIdClient {
|
|
|
146
146
|
s.string().parse(key);
|
|
147
147
|
const fallbacks = this.bareFallbacksFor(key);
|
|
148
148
|
const record = fallbacks
|
|
149
|
-
? await this
|
|
150
|
-
: await this
|
|
149
|
+
? await this.#nativeBackend.resolveValue(key, fallbacks)
|
|
150
|
+
: await this.#nativeBackend.getValue(key);
|
|
151
151
|
if (record) {
|
|
152
152
|
return {
|
|
153
153
|
key: record.key,
|
|
@@ -183,7 +183,7 @@ export class KeyValueStoreBackend extends CachedIdClient {
|
|
|
183
183
|
// consumes a Web `ReadableStream`, so convert the Node `Readable` we get from the frontend.
|
|
184
184
|
if (isStream(value)) {
|
|
185
185
|
const webStream = Readable.toWeb(value);
|
|
186
|
-
await this
|
|
186
|
+
await this.#nativeBackend.setValueStream(key, webStream, contentType);
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
189
189
|
// Normalize the remaining (already-serialized) value into a Buffer for the native client.
|
|
@@ -194,11 +194,11 @@ export class KeyValueStoreBackend extends CachedIdClient {
|
|
|
194
194
|
: ArrayBuffer.isView(value)
|
|
195
195
|
? Buffer.from(value.buffer, value.byteOffset, value.byteLength)
|
|
196
196
|
: Buffer.from(value);
|
|
197
|
-
await this
|
|
197
|
+
await this.#nativeBackend.setValue(key, buffer, contentType);
|
|
198
198
|
}
|
|
199
199
|
async deleteValue(key) {
|
|
200
200
|
s.string().parse(key);
|
|
201
|
-
await this
|
|
201
|
+
await this.#nativeBackend.deleteValue(key);
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
204
|
* Resolve `key` to the on-disk key that actually exists, or `undefined` if nothing does. Every
|
|
@@ -211,9 +211,9 @@ export class KeyValueStoreBackend extends CachedIdClient {
|
|
|
211
211
|
async resolveExistingKey(key) {
|
|
212
212
|
const fallbacks = this.bareFallbacksFor(key);
|
|
213
213
|
if (fallbacks) {
|
|
214
|
-
return ((await this
|
|
214
|
+
return ((await this.#nativeBackend.resolveExistingKey(key, fallbacks.map(({ extension }) => extension))) ?? undefined);
|
|
215
215
|
}
|
|
216
|
-
return (await this
|
|
216
|
+
return (await this.#nativeBackend.recordExists(key)) ? key : undefined;
|
|
217
217
|
}
|
|
218
218
|
/**
|
|
219
219
|
* The native `resolveValue`/`resolveExistingKey` bare-file fallbacks to use for `key`, or
|
|
@@ -21,9 +21,9 @@ export interface RequestQueueBackendOptions {
|
|
|
21
21
|
* This adapter forwards each operation and converts result shapes to the `@crawlee/types` interfaces.
|
|
22
22
|
*/
|
|
23
23
|
export declare class RequestQueueBackend extends CachedIdClient implements storage.RequestQueueBackend {
|
|
24
|
+
#private;
|
|
24
25
|
readonly name?: string;
|
|
25
26
|
readonly cacheKey: string;
|
|
26
|
-
private readonly nativeBackend;
|
|
27
27
|
constructor(options: RequestQueueBackendOptions);
|
|
28
28
|
get requestQueueDirectory(): string;
|
|
29
29
|
static create(options: RequestQueueBackendOptions): Promise<RequestQueueBackend>;
|
|
@@ -40,15 +40,15 @@ const requestOptionsShape = s.object({
|
|
|
40
40
|
export class RequestQueueBackend extends CachedIdClient {
|
|
41
41
|
name;
|
|
42
42
|
cacheKey;
|
|
43
|
-
nativeBackend;
|
|
43
|
+
#nativeBackend;
|
|
44
44
|
constructor(options) {
|
|
45
45
|
super();
|
|
46
46
|
this.name = options.name;
|
|
47
47
|
this.cacheKey = options.cacheKey;
|
|
48
|
-
this
|
|
48
|
+
this.#nativeBackend = options.nativeBackend;
|
|
49
49
|
}
|
|
50
50
|
get requestQueueDirectory() {
|
|
51
|
-
return this
|
|
51
|
+
return this.#nativeBackend.pathToRq;
|
|
52
52
|
}
|
|
53
53
|
static async create(options) {
|
|
54
54
|
const backend = new RequestQueueBackend(options);
|
|
@@ -60,21 +60,21 @@ export class RequestQueueBackend extends CachedIdClient {
|
|
|
60
60
|
* available again.
|
|
61
61
|
*/
|
|
62
62
|
async setExpectedRequestProcessingTimeSecs(secs) {
|
|
63
|
-
await this
|
|
63
|
+
await this.#nativeBackend.setExpectedRequestProcessingTime(secs);
|
|
64
64
|
}
|
|
65
65
|
async getMetadata() {
|
|
66
|
-
return this
|
|
66
|
+
return this.#nativeBackend.getMetadata();
|
|
67
67
|
}
|
|
68
68
|
async drop() {
|
|
69
|
-
await this
|
|
69
|
+
await this.#nativeBackend.dropStorage();
|
|
70
70
|
}
|
|
71
71
|
async purge() {
|
|
72
|
-
await this
|
|
72
|
+
await this.#nativeBackend.purge();
|
|
73
73
|
}
|
|
74
74
|
async addBatchOfRequests(requests, options = {}) {
|
|
75
75
|
batchRequestShapeWithoutId.parse(requests);
|
|
76
76
|
requestOptionsShape.parse(options);
|
|
77
|
-
const response = await this
|
|
77
|
+
const response = await this.#nativeBackend.addBatchOfRequests(requests.map((request) => plainifyRequest(request)), options.forefront ?? false);
|
|
78
78
|
// `processedRequests` is structurally identical between the native and `storage` types, so it
|
|
79
79
|
// passes through unchanged. `unprocessedRequests` only differs in that the native `method` is
|
|
80
80
|
// a plain `string`, hence the cast to the narrower `AllowedHttpMethods` union.
|
|
@@ -88,25 +88,26 @@ export class RequestQueueBackend extends CachedIdClient {
|
|
|
88
88
|
// The native client tags requests with an internal `orderNo`; it's harmless to leak, so we
|
|
89
89
|
// hand the request back as-is rather than copying it just to drop one undeclared property.
|
|
90
90
|
// The native client already returns `undefined` for a missing request, matching this contract.
|
|
91
|
-
return (await this
|
|
91
|
+
return (await this.#nativeBackend.getRequest(uniqueKey));
|
|
92
92
|
}
|
|
93
93
|
async fetchNextRequest() {
|
|
94
|
-
return (await this
|
|
94
|
+
return (await this.#nativeBackend.fetchNextRequest());
|
|
95
95
|
}
|
|
96
96
|
async markRequestAsHandled(request) {
|
|
97
97
|
requestShape.parse(request);
|
|
98
|
-
return (await this
|
|
98
|
+
return (await this.#nativeBackend.markRequestAsHandled(plainifyRequest(request))) ?? undefined;
|
|
99
99
|
}
|
|
100
100
|
async reclaimRequest(request, options = {}) {
|
|
101
101
|
requestShape.parse(request);
|
|
102
102
|
requestOptionsShape.parse(options);
|
|
103
|
-
return ((await this
|
|
103
|
+
return ((await this.#nativeBackend.reclaimRequest(plainifyRequest(request), options.forefront ?? false)) ??
|
|
104
|
+
undefined);
|
|
104
105
|
}
|
|
105
106
|
async isEmpty() {
|
|
106
|
-
return this
|
|
107
|
+
return this.#nativeBackend.isEmpty();
|
|
107
108
|
}
|
|
108
109
|
async isFinished() {
|
|
109
|
-
return this
|
|
110
|
+
return this.#nativeBackend.isFinished();
|
|
110
111
|
}
|
|
111
112
|
/**
|
|
112
113
|
* Persist the native client's in-memory state to disk. Called by
|
|
@@ -114,6 +115,6 @@ export class RequestQueueBackend extends CachedIdClient {
|
|
|
114
115
|
* for the next consumer of the same on-disk queue.
|
|
115
116
|
*/
|
|
116
117
|
async persistState() {
|
|
117
|
-
await this
|
|
118
|
+
await this.#nativeBackend.persistState();
|
|
118
119
|
}
|
|
119
120
|
}
|