Skip to content

Improve Apify actions #16384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 28, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ export default {
key: "apify-get-dataset-items",
name: "Get Dataset Items",
description: "Returns data stored in a dataset. [See the documentation](https://docs.apify.com/api/v2/dataset-items-get)",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
apify,
167 changes: 143 additions & 24 deletions components/apify/actions/run-actor/run-actor.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/* eslint-disable no-unused-vars */
import apify from "../../apify.app.mjs";
import { parseObject } from "../../common/utils.mjs";
import { EVENT_TYPES } from "../../common/constants.mjs";

export default {
key: "apify-run-actor",
name: "Run Actor",
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)",
version: "0.0.2",
version: "0.0.3",
type: "action",
props: {
apify,
@@ -14,6 +16,52 @@ export default {
apify,
"actorId",
],
},
buildId: {
propDefinition: [
apify,
"buildId",
(c) => ({
actorId: c.actorId,
}),
],
reloadProps: true,
},
runAsynchronously: {
type: "boolean",
label: "Run Asynchronously",
description: "Set to `true` to run the actor asynchronously",
reloadProps: true,
},
timeout: {
type: "string",
label: "Timeout",
description: "Optional timeout for the run, in seconds. By default, the run uses a timeout specified in the default run configuration for the Actor.",
optional: true,
},
memory: {
type: "string",
label: "Memory",
description: "Memory limit for the run, in megabytes. The amount of memory can be set to a power of 2 with a minimum of 128. By default, the run uses a memory limit specified in the default run configuration for the Actor.",
optional: true,
},
maxItems: {
type: "string",
label: "Max Items",
description: "The maximum number of items that the Actor run should return. This is useful for pay-per-result Actors, as it allows you to limit the number of results that will be charged to your subscription. You can access the maximum number of items in your Actor by using the ACTOR_MAX_PAID_DATASET_ITEMS environment variable.",
optional: true,
},
maxTotalChargeUsd: {
type: "string",
label: "Max Total Charge USD",
description: "Specifies the maximum cost of the Actor run. This parameter is useful for pay-per-event Actors, as it allows you to limit the amount charged to your subscription. You can access the maximum cost in your Actor by using the ACTOR_MAX_TOTAL_CHARGE_USD environment variable.",
optional: true,
},
webhook: {
type: "string",
label: "Webhook",
description: "Specifies optional webhook associated with the Actor run, which can be used to receive a notification e.g. when the Actor finished or failed.",
optional: true,
reloadProps: true,
},
},
@@ -28,16 +76,14 @@ export default {
? type
: "string[]";
},
async getSchema() {
const { data: { items: builds } } = await this.apify.listBuilds(this.actorId);
const buildId = builds.at(-1).id;
async getSchema(buildId) {
const { data: { inputSchema } } = await this.apify.getBuild(buildId);
return JSON.parse(inputSchema);
},
async prepareData(data) {
const newData = {};

const { properties } = await this.getSchema();
const { properties } = await this.getSchema(this.buildId);
for (const [
key,
value,
@@ -85,27 +131,64 @@ export default {
},
async additionalProps() {
const props = {};
if (this.actorId) {
const {
properties, required: requiredProps = [],
} = await this.getSchema();
if (this.buildId) {
try {
const {
properties, required: requiredProps = [],
} = await this.getSchema(this.buildId);

for (const [
key,
value,
] of Object.entries(properties)) {
if (value.editor === "hidden") continue;
for (const [
key,
value,
] of Object.entries(properties)) {
if (value.editor === "hidden") continue;

props[key] = {
type: this.getType(value.type),
label: value.title,
description: value.description,
optional: !requiredProps.includes(key),
props[key] = {
type: this.getType(value.type),
label: value.title,
description: value.description,
optional: !requiredProps.includes(key),
};
const options = this.prepareOptions(value);
if (options) props[key].options = options;
if (value.default) {
props[key].description += ` Default: \`${JSON.stringify(value.default)}\``;
if (props[key].type !== "object") { // default values don't work properly for object props
props[key].default = value.default;
}
}
}
} catch {
props.properties = {
type: "object",
label: "Properties",
description: "Properties to set for this actor",
};
}
if (this.runAsynchronously) {
props.outputRecordKey = {
type: "string",
label: "Output Record Key",
description: "Key of the record from run's default key-value store to be returned in the response. By default, it is OUTPUT.",
optional: true,
};
} else {
props.waitForFinish = {
type: "string",
label: "Wait For Finish",
description: "The maximum number of seconds the server waits for the run to finish. By default, it is 0, the maximum value is 60. If the build finishes in time then the returned run object will have a terminal status (e.g. SUCCEEDED), otherwise it will have a transitional status (e.g. RUNNING).",
optional: true,
};
const options = this.prepareOptions(value);
if (options) props[key].options = options;
}
}
if (this.webhook) {
props.eventTypes = {
type: "string[]",
label: "Event Types",
description: "The types of events to send to the webhook",
options: EVENT_TYPES,
};
}
return props;
},
async run({ $ }) {
@@ -117,14 +200,50 @@ export default {
prepareData,
apify,
actorId,
buildId,
properties,
runAsynchronously,
outputRecordKey,
timeout,
memory,
maxItems,
maxTotalChargeUsd,
waitForFinish,
webhook,
eventTypes,
...data
} = this;

const response = await apify.runActor({
const fn = runAsynchronously
? apify.runActorAsynchronously
: apify.runActor;

const response = await fn({
actorId,
data: await prepareData(data),
data: properties
? parseObject(properties)
: await prepareData(data),
params: {
outputRecordKey,
timeout,
memory,
maxItems,
maxTotalChargeUsd,
waitForFinish,
webhooks: webhook
? btoa(JSON.stringify([
{
eventTypes,
requestUrl: webhook,
},
]))
: undefined,
},
});
$.export("$summary", `Successfully started actor run with ID: ${response.data.id}`);
const summary = this.runAsynchronously
? `Successfully started actor run with ID: ${response.data.id}`
: `Successfully ran actor with ID: ${this.actorId}`;
$.export("$summary", `${summary}`);
return response;
},
};
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ export default {
key: "apify-run-task-synchronously",
name: "Run Task Synchronously",
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)",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
apify,
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ export default {
key: "apify-scrape-single-url",
name: "Scrape Single URL",
description: "Executes a scraper on a specific website and returns its content as text. This action is perfect for extracting content from a single page.",
version: "0.0.2",
version: "0.0.3",
type: "action",
props: {
apify,
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ export default {
key: "apify-set-key-value-store-record",
name: "Set Key-Value Store Record",
description: "Create or update a record in the key-value store of Apify. [See the documentation](https://docs.apify.com/api/v2#/reference/key-value-stores/record-collection/put-record)",
version: "0.0.2",
version: "0.0.3",
type: "action",
props: {
apify,
30 changes: 28 additions & 2 deletions components/apify/apify.app.mjs
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ export default {
actorId: {
type: "string",
label: "Actor ID",
description: "The ID of the actor to run.",
description: "Actor ID or a tilde-separated owner's username and Actor name",
async options({ page }) {
const { data: { items } } = await this.listActors({
params: {
@@ -105,6 +105,23 @@ export default {
})) || [];
},
},
buildId: {
type: "string",
label: "Build",
description: "Specifies the Actor build to run. It can be either a build tag or build number.",
async options({
page, actorId,
}) {
const { data: { items } } = await this.listBuilds({
actorId,
params: {
offset: LIMIT * page,
limit: LIMIT,
},
});
return items?.map(({ id }) => id) || [];
},
},
clean: {
type: "boolean",
label: "Clean",
@@ -171,6 +188,15 @@ export default {
},
runActor({
actorId, ...opts
}) {
return this._makeRequest({
method: "POST",
path: `/acts/${actorId}/run-sync`,
...opts,
});
},
runActorAsynchronously({
actorId, ...opts
}) {
return this._makeRequest({
method: "POST",
@@ -207,7 +233,7 @@ export default {
...opts,
});
},
listBuilds(actorId) {
listBuilds({ actorId }) {
return this._makeRequest({
path: `/acts/${actorId}/builds`,
});
9 changes: 9 additions & 0 deletions components/apify/common/constants.mjs
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
export const ACTOR_ID = "aYG0l9s7dbB7j3gbS";
export const LIMIT = 100;

export const EVENT_TYPES = [
"ACTOR.RUN.CREATED",
"ACTOR.RUN.SUCCEEDED",
"ACTOR.RUN.FAILED",
"ACTOR.RUN.ABORTED",
"ACTOR.RUN.TIMED_OUT",
"ACTOR.RUN.RESURRECTED",
];
2 changes: 1 addition & 1 deletion components/apify/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/apify",
"version": "0.2.0",
"version": "0.2.1",
"description": "Pipedream Apify Components",
"main": "apify.app.mjs",
"keywords": [
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ export default {
key: "apify-new-finished-actor-run-instant",
name: "New Finished Actor Run (Instant)",
description: "Emit new event when a selected actor is run and finishes.",
version: "0.0.2",
version: "0.0.3",
type: "source",
dedupe: "unique",
props: {
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ export default {
key: "apify-new-finished-task-run-instant",
name: "New Finished Task Run (Instant)",
description: "Emit new event when a selected task is run and finishes.",
version: "0.0.2",
version: "0.0.3",
type: "source",
dedupe: "unique",
props: {