Skip to content

Commit eb67655

Browse files
committed
Merge remote-tracking branch 'origin/master' into issue-17837
2 parents 231486c + 1693c83 commit eb67655

File tree

59 files changed

+1807
-345
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1807
-345
lines changed

components/apify/actions/get-dataset-items/get-dataset-items.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export default {
55
key: "apify-get-dataset-items",
66
name: "Get Dataset Items",
77
description: "Returns data stored in a dataset. [See the documentation](https://docs.apify.com/api/v2/dataset-items-get)",
8-
version: "0.0.5",
8+
version: "0.0.6",
99
annotations: {
1010
destructiveHint: false,
1111
openWorldHint: true,
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import axios from "axios";
2+
import apify from "../../apify.app.mjs";
3+
4+
export default {
5+
key: "apify-get-kvs-record",
6+
name: "Get Key-Value Store Record",
7+
description: "Gets a record from a key-value store. [See the documentation](https://docs.apify.com/api/v2/key-value-store-record-get)",
8+
version: "0.0.1",
9+
type: "action",
10+
annotations: {
11+
destructiveHint: false,
12+
openWorldHint: true,
13+
readOnlyHint: true,
14+
},
15+
props: {
16+
apify,
17+
keyValueStoreId: {
18+
propDefinition: [
19+
apify,
20+
"keyValueStoreId",
21+
() => ({
22+
unnamed: false,
23+
}),
24+
],
25+
},
26+
key: {
27+
type: "string",
28+
label: "Record Key",
29+
description: "If the record is a valid JSON object, the output will include all parsed attributes as individual fields. If the record is any other file type (such as PDFs, images, or plain text), the output will instead be a file reference.",
30+
},
31+
},
32+
async run({ $ }) {
33+
const token = this.apify.getAuthToken();
34+
35+
// HEAD request to get size and content-type
36+
const recordUrl = `https://api.apify.com/v2/key-value-stores/${this.keyValueStoreId}/records/${encodeURIComponent(this.key)}`;
37+
const headResp = await axios({
38+
url: recordUrl,
39+
method: "HEAD",
40+
headers: {
41+
Authorization: `Bearer ${token}`,
42+
},
43+
validateStatus: () => true,
44+
});
45+
46+
if (headResp.status === 404) {
47+
$.export("$summary", "Record not found");
48+
return {};
49+
}
50+
if (headResp.status >= 400) {
51+
throw new Error(`Error retrieving record: ${headResp.statusText}`);
52+
}
53+
54+
const contentType = headResp.headers["content-type"];
55+
const contentLength = parseInt(headResp.headers["content-length"] || "0");
56+
57+
const PARSEABLE_MIMES = [
58+
"application/json",
59+
"text/plain",
60+
];
61+
const MAX_INLINE_SIZE = 10 * 1000 * 1000;
62+
63+
// If parseable and small enough, get data via Apify client
64+
if (PARSEABLE_MIMES.some((pattern) => contentType.includes(pattern))
65+
&& contentLength < MAX_INLINE_SIZE) {
66+
const record = await this.apify.getKVSRecord(this.keyValueStoreId, this.key);
67+
const data = record?.value;
68+
69+
if (typeof data === "object" && !Array.isArray(data) && data !== null) {
70+
$.export("$summary", "Retrieved JSON record");
71+
return data;
72+
} else {
73+
$.export("$summary", "Retrieved text record");
74+
return {
75+
value: data ?? null,
76+
};
77+
}
78+
} else {
79+
// For large/binary files, return signed URL via Apify client
80+
const signedUrl = await this.apify.getKVSRecordUrl(this.keyValueStoreId, this.key);
81+
82+
$.export("$summary", "Retrieved file pointer");
83+
return {
84+
contentType,
85+
value: signedUrl,
86+
};
87+
}
88+
},
89+
};

components/apify/actions/run-actor/run-actor.mjs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default {
77
key: "apify-run-actor",
88
name: "Run Actor",
99
description: "Performs an execution of a selected Actor in Apify. [See the documentation](https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor)",
10-
version: "0.0.6",
10+
version: "0.0.7",
1111
annotations: {
1212
destructiveHint: false,
1313
openWorldHint: true,
@@ -137,14 +137,18 @@ export default {
137137
const newData = {};
138138
const { properties } = await this.getSchema(this.actorId, this.buildTag);
139139

140+
// Iterate over properties from the schema because newData might contain additional fields
140141
for (const [
141142
key,
142143
value,
143-
] of Object.entries(data)) {
144-
const editor = properties[key]?.editor || "hidden";
145-
newData[key] = Array.isArray(value)
146-
? value.map((item) => this.setValue(editor, item))
147-
: value;
144+
] of Object.entries(properties)) {
145+
const propValue = data[key];
146+
if (propValue === undefined) continue;
147+
148+
const editor = value.editor || "hidden";
149+
newData[key] = Array.isArray(propValue)
150+
? propValue.map((item) => this.setValue(editor, item))
151+
: this.setValue(editor, propValue);
148152
}
149153
return newData;
150154
},
@@ -170,6 +174,10 @@ export default {
170174
return {
171175
glob: item,
172176
};
177+
case "json":
178+
case "schemaBased":
179+
if (typeof item === "string") return JSON.parse(item);
180+
return item;
173181
default:
174182
return item;
175183
}
@@ -204,23 +212,27 @@ export default {
204212
if (value.unit) {
205213
props[key].description += ` Unit: ${value.unit}.`;
206214
}
207-
} else if (props[key].type === "boolean") {
208-
// Default all boolean properties to false
209-
props[key].default = false;
210215
}
211216

212217
const options = this.prepareOptions(value);
213-
if (options) props[key].options = options;
218+
if (options) props[key].options = options.filter((option) => option.value !== "" && option.label !== "");
214219

215-
const defaultValue = value.prefill ?? value.default;
220+
// We're using prefill here as a suggestion for the user. Using default value would be
221+
// redundant as the default value is inserted by the Apify platform.
222+
// More info: https://docs.apify.com/platform/actors/development/actor-definition/input-schema/specification/v1#prefill-vs-default-vs-required
223+
const defaultValue = value.prefill;
216224

217225
if (defaultValue !== undefined) {
218-
if (props[key].type !== "object") {
219-
props[key].default = defaultValue;
226+
props[key].default = defaultValue;
220227

221-
if (props[key].type === "string[]" && value.editor === "requestListSources") {
228+
if (props[key].type === "string[]") {
229+
if (value.editor === "requestListSources") {
222230
props[key].default = defaultValue.map((request) => request.url);
223231
}
232+
233+
if (value.editor === "json" || value.editor === "schemaBased") {
234+
props[key].default = defaultValue.map((item) => JSON.stringify(item));
235+
}
224236
}
225237

226238
props[key].description += ` Default: \`${JSON.stringify(defaultValue)}\``;
@@ -297,9 +309,13 @@ export default {
297309
}
298310

299311
// Prepare input
300-
const rawInput = this.properties
301-
? parseObject(this.properties)
302-
: data;
312+
// Use data (dynamic props from schema) if it has any keys,
313+
// otherwise fall back to this.properties (fallback object prop)
314+
const rawInput = Object.keys(data).length > 0
315+
? data
316+
: (this.properties
317+
? parseObject(this.properties)
318+
: {});
303319
const input = await this.prepareData(rawInput);
304320

305321
// Build params safely

components/apify/actions/run-task-synchronously/run-task-synchronously.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export default {
55
key: "apify-run-task-synchronously",
66
name: "Run Task Synchronously",
77
description: "Run a specific task and return its dataset items. [See the documentation](https://docs.apify.com/api/v2/actor-task-run-sync-get-dataset-items-get)",
8-
version: "0.0.5",
8+
version: "0.0.6",
99
annotations: {
1010
destructiveHint: true,
1111
openWorldHint: true,

0 commit comments

Comments
 (0)