@hostwebhook/node-types 1.80.0 → 1.81.0

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.
@@ -0,0 +1,67 @@
1
+ /**
2
+ * El nodo de Apify: correr actores y tareas, y leer lo que dejan.
3
+ *
4
+ * ## Por qué existe
5
+ *
6
+ * [2026-09-13] Él tenía el polling montado a mano: «Start Apify job (HTTP) →
7
+ * Check status (HTTP) → Loop Until Complete (conditional) → else → Check», con
8
+ * el token pegado en cada HTTP. Apify no tiene OAuth para terceros —Zapier,
9
+ * Make y n8n van con token igual— así que la credencial es una API key como
10
+ * la de Firecrawl, y lo demás es un nodo con las llamadas ya escritas.
11
+ *
12
+ * ## La operación que motiva el nodo
13
+ *
14
+ * `runActorAndWait`: `run-sync-get-dataset-items` corre el actor y devuelve
15
+ * los items del dataset en la MISMA respuesta (hasta 300 s; pasado eso, 408).
16
+ * Con eso el flujo de arriba cabe en un nodo. Para actores más lentos siguen
17
+ * estando `startRun` + `getRun` + `getDatasetItems`, que es lo que él hacía a
18
+ * mano, ahora con la key en la credencial.
19
+ *
20
+ * ## Por qué siete
21
+ *
22
+ * Las tres del polling (`startRun`, `getRun`, `getDatasetItems`), la que lo
23
+ * evita (`runActorAndWait`), su gemela para tareas guardadas (`runTask`), el
24
+ * key-value store (`getKeyValueRecord`: `OUTPUT`, un `results-map`, lo que el
25
+ * actor guarde con nombre) y `abortRun`. Lo que queda fuera a propósito:
26
+ * listar actores y datasets del usuario, webhooks de Apify y el request
27
+ * queue — nada de eso hace falta para correr un actor y leer su resultado.
28
+ *
29
+ * ⚠️ El orden de este array es el orden del desplegable.
30
+ */
31
+ export declare const APIFY_OPERATIONS: readonly ["runActorAndWait", "startRun", "getRun", "getDatasetItems", "getKeyValueRecord", "runTask", "abortRun"];
32
+ export type ApifyOperation = (typeof APIFY_OPERATIONS)[number];
33
+ export declare function isApifyOperation(value: unknown): value is ApifyOperation;
34
+ /**
35
+ * Las que devuelven una COLECCIÓN sobre la que el nodo de abajo repite: los
36
+ * items de un dataset. `runActorAndWait` y `runTask` los traen en la misma
37
+ * respuesta; `getDatasetItems` los pide aparte. Las otras devuelven UN objeto
38
+ * (la corrida, el registro).
39
+ *
40
+ * ⚠️ Se itera `items`, y sólo `items`. La salida lleva `_meta.iterable: true`
41
+ * con `iterateField: 'items'`, como el crawl de Firecrawl.
42
+ */
43
+ export declare const APIFY_ITERABLE_OPERATIONS: ReadonlyArray<ApifyOperation>;
44
+ export type ApifyParamType = "template" | "textarea" | "json" | "select" | "number" | "booleanSelect";
45
+ export interface ApifyParamSpec {
46
+ name: string;
47
+ label: string;
48
+ type: ApifyParamType;
49
+ required?: boolean;
50
+ description?: string;
51
+ placeholder?: string;
52
+ default?: string | number;
53
+ options?: ReadonlyArray<{
54
+ value: string;
55
+ label: string;
56
+ }>;
57
+ min?: number;
58
+ max?: number;
59
+ advanced?: boolean;
60
+ }
61
+ export interface ApifyOperationSpec {
62
+ label: string;
63
+ description: string;
64
+ apiRoute: string;
65
+ params: ApifyParamSpec[];
66
+ }
67
+ export declare const APIFY_OPERATION_SPECS: Record<ApifyOperation, ApifyOperationSpec>;
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APIFY_OPERATION_SPECS = exports.APIFY_ITERABLE_OPERATIONS = exports.APIFY_OPERATIONS = void 0;
4
+ exports.isApifyOperation = isApifyOperation;
5
+ /**
6
+ * El nodo de Apify: correr actores y tareas, y leer lo que dejan.
7
+ *
8
+ * ## Por qué existe
9
+ *
10
+ * [2026-09-13] Él tenía el polling montado a mano: «Start Apify job (HTTP) →
11
+ * Check status (HTTP) → Loop Until Complete (conditional) → else → Check», con
12
+ * el token pegado en cada HTTP. Apify no tiene OAuth para terceros —Zapier,
13
+ * Make y n8n van con token igual— así que la credencial es una API key como
14
+ * la de Firecrawl, y lo demás es un nodo con las llamadas ya escritas.
15
+ *
16
+ * ## La operación que motiva el nodo
17
+ *
18
+ * `runActorAndWait`: `run-sync-get-dataset-items` corre el actor y devuelve
19
+ * los items del dataset en la MISMA respuesta (hasta 300 s; pasado eso, 408).
20
+ * Con eso el flujo de arriba cabe en un nodo. Para actores más lentos siguen
21
+ * estando `startRun` + `getRun` + `getDatasetItems`, que es lo que él hacía a
22
+ * mano, ahora con la key en la credencial.
23
+ *
24
+ * ## Por qué siete
25
+ *
26
+ * Las tres del polling (`startRun`, `getRun`, `getDatasetItems`), la que lo
27
+ * evita (`runActorAndWait`), su gemela para tareas guardadas (`runTask`), el
28
+ * key-value store (`getKeyValueRecord`: `OUTPUT`, un `results-map`, lo que el
29
+ * actor guarde con nombre) y `abortRun`. Lo que queda fuera a propósito:
30
+ * listar actores y datasets del usuario, webhooks de Apify y el request
31
+ * queue — nada de eso hace falta para correr un actor y leer su resultado.
32
+ *
33
+ * ⚠️ El orden de este array es el orden del desplegable.
34
+ */
35
+ exports.APIFY_OPERATIONS = [
36
+ "runActorAndWait",
37
+ "startRun",
38
+ "getRun",
39
+ "getDatasetItems",
40
+ "getKeyValueRecord",
41
+ "runTask",
42
+ "abortRun",
43
+ ];
44
+ function isApifyOperation(value) {
45
+ return (typeof value === "string" &&
46
+ exports.APIFY_OPERATIONS.includes(value));
47
+ }
48
+ /**
49
+ * Las que devuelven una COLECCIÓN sobre la que el nodo de abajo repite: los
50
+ * items de un dataset. `runActorAndWait` y `runTask` los traen en la misma
51
+ * respuesta; `getDatasetItems` los pide aparte. Las otras devuelven UN objeto
52
+ * (la corrida, el registro).
53
+ *
54
+ * ⚠️ Se itera `items`, y sólo `items`. La salida lleva `_meta.iterable: true`
55
+ * con `iterateField: 'items'`, como el crawl de Firecrawl.
56
+ */
57
+ exports.APIFY_ITERABLE_OPERATIONS = [
58
+ "runActorAndWait",
59
+ "runTask",
60
+ "getDatasetItems",
61
+ ];
62
+ /* El actor se nombra como lo nombra Apify: `usuario~nombre` o su id. */
63
+ const actorId = () => ({
64
+ name: "actorId",
65
+ label: "Actor",
66
+ type: "template",
67
+ required: true,
68
+ placeholder: "apify~web-scraper or nwua9Gu5YrADL7ZDj",
69
+ description: "The actor to run, as username~actor-name or its ID. Supports {{payload.x}}.",
70
+ });
71
+ /* El input del actor es JSON libre: cada actor define el suyo. `json` se
72
+ escribe en la caja en corto (`clave: valor`) o como JSON de verdad, y las
73
+ cadenas de dentro admiten plantillas. */
74
+ const actorInput = () => ({
75
+ name: "input",
76
+ label: "Actor input",
77
+ type: "json",
78
+ description: "The input the actor expects (each actor documents its own). Strings inside may use {{payload.x}}. Leave it empty to run with the actor's defaults.",
79
+ });
80
+ const runId = () => ({
81
+ name: "runId",
82
+ label: "Run ID",
83
+ type: "template",
84
+ required: true,
85
+ placeholder: "{{payload.data.id}}",
86
+ description: "The run to look at — usually the `data.id` that Start actor run returned.",
87
+ });
88
+ /* Los tres ajustes de una corrida, en todas las que arrancan una. */
89
+ const runSettings = () => [
90
+ {
91
+ name: "timeoutSecs",
92
+ label: "Run timeout (seconds)",
93
+ type: "number",
94
+ min: 0,
95
+ max: 3600,
96
+ advanced: true,
97
+ description: "How long Apify lets the actor run. Empty = the actor's own default.",
98
+ },
99
+ {
100
+ name: "memoryMbytes",
101
+ label: "Memory (MB)",
102
+ type: "number",
103
+ min: 128,
104
+ max: 32768,
105
+ advanced: true,
106
+ description: "Memory for the run, a power of two from 128. Empty = the actor's own default.",
107
+ },
108
+ {
109
+ name: "build",
110
+ label: "Build",
111
+ type: "template",
112
+ placeholder: "latest",
113
+ advanced: true,
114
+ description: "Which build to run — a tag like latest or beta, or a build number. Empty = latest.",
115
+ },
116
+ ];
117
+ /* Cómo se piden los items de un dataset, en las tres que los devuelven. */
118
+ const itemSettings = () => [
119
+ {
120
+ name: "limit",
121
+ label: "Max items",
122
+ type: "number",
123
+ min: 1,
124
+ max: 250000,
125
+ description: "How many items to bring into the flow. Empty = all of them (careful with big datasets).",
126
+ },
127
+ {
128
+ name: "clean",
129
+ label: "Clean items",
130
+ type: "booleanSelect",
131
+ options: [
132
+ { value: "true", label: "Yes — skip empty items and hidden fields" },
133
+ { value: "false", label: "No — everything, as stored" },
134
+ ],
135
+ advanced: true,
136
+ description: 'Apify\'s "clean" flag: drops empty items and fields starting with #. Default is Yes.',
137
+ },
138
+ ];
139
+ exports.APIFY_OPERATION_SPECS = {
140
+ runActorAndWait: {
141
+ label: "Run actor and wait",
142
+ description: "Runs the actor and returns its dataset items in the same step — no polling. Waits up to 5 minutes; for slower actors use Start actor run.",
143
+ apiRoute: "POST /v2/actors/{actorId}/run-sync-get-dataset-items",
144
+ params: [actorId(), actorInput(), ...itemSettings(), ...runSettings()],
145
+ },
146
+ startRun: {
147
+ label: "Start actor run",
148
+ description: "Starts the actor and returns the run right away (its ID, status and dataset ID). Check it later with Get run, or wait a bit with the option below.",
149
+ apiRoute: "POST /v2/actors/{actorId}/runs",
150
+ params: [
151
+ actorId(),
152
+ actorInput(),
153
+ {
154
+ name: "waitForFinishSecs",
155
+ label: "Wait for finish (seconds)",
156
+ type: "number",
157
+ min: 0,
158
+ max: 60,
159
+ description: "Up to 60 s: if the run finishes in time, the returned run already says SUCCEEDED. 0 or empty = come back immediately.",
160
+ },
161
+ ...runSettings(),
162
+ ],
163
+ },
164
+ getRun: {
165
+ label: "Get run",
166
+ description: "The current state of a run: RUNNING, SUCCEEDED, FAILED… plus its dataset and key-value store IDs. This is the check in a polling loop.",
167
+ apiRoute: "GET /v2/actor-runs/{runId}",
168
+ params: [runId()],
169
+ },
170
+ getDatasetItems: {
171
+ label: "Get dataset items",
172
+ description: "Reads the items of a dataset — usually the run's defaultDatasetId. Sent with your token, so it also works once the account is set to Restricted.",
173
+ apiRoute: "GET /v2/datasets/{datasetId}/items",
174
+ params: [
175
+ {
176
+ name: "datasetId",
177
+ label: "Dataset ID",
178
+ type: "template",
179
+ required: true,
180
+ placeholder: "{{payload.data.defaultDatasetId}}",
181
+ description: "The dataset to read, by ID or username~name.",
182
+ },
183
+ ...itemSettings(),
184
+ {
185
+ name: "offset",
186
+ label: "Skip items",
187
+ type: "number",
188
+ min: 0,
189
+ advanced: true,
190
+ description: "How many items to skip from the start. Empty = none.",
191
+ },
192
+ {
193
+ name: "fields",
194
+ label: "Only these fields",
195
+ type: "template",
196
+ placeholder: "title, url, price",
197
+ advanced: true,
198
+ description: "Comma-separated field names to keep in each item. Empty = every field.",
199
+ },
200
+ ],
201
+ },
202
+ getKeyValueRecord: {
203
+ label: "Get key-value record",
204
+ description: "Reads one record from a key-value store — the run's OUTPUT, a results-map, anything the actor stored by name. JSON comes back parsed; anything else as text.",
205
+ apiRoute: "GET /v2/key-value-stores/{storeId}/records/{recordKey}",
206
+ params: [
207
+ {
208
+ name: "storeId",
209
+ label: "Store ID",
210
+ type: "template",
211
+ required: true,
212
+ placeholder: "{{payload.data.defaultKeyValueStoreId}}",
213
+ description: "The key-value store, by ID or username~name.",
214
+ },
215
+ {
216
+ name: "recordKey",
217
+ label: "Record key",
218
+ type: "template",
219
+ required: true,
220
+ placeholder: "OUTPUT",
221
+ description: "The record to read.",
222
+ },
223
+ ],
224
+ },
225
+ runTask: {
226
+ label: "Run task and wait",
227
+ description: "Runs a saved task (an actor with its input already set in Apify) and returns its dataset items. Waits up to 5 minutes.",
228
+ apiRoute: "POST /v2/actor-tasks/{taskId}/run-sync-get-dataset-items",
229
+ params: [
230
+ {
231
+ name: "taskId",
232
+ label: "Task",
233
+ type: "template",
234
+ required: true,
235
+ placeholder: "username~my-task or its ID",
236
+ description: "The task to run, as username~task-name or its ID.",
237
+ },
238
+ {
239
+ name: "input",
240
+ label: "Input overrides",
241
+ type: "json",
242
+ description: "Fields to override on top of the task's saved input. Empty = run the task as saved.",
243
+ },
244
+ ...itemSettings(),
245
+ ...runSettings(),
246
+ ],
247
+ },
248
+ abortRun: {
249
+ label: "Abort run",
250
+ description: "Stops a run that is still going. Returns the run with its final state.",
251
+ apiRoute: "POST /v2/actor-runs/{runId}/abort",
252
+ params: [
253
+ runId(),
254
+ {
255
+ name: "gracefully",
256
+ label: "Gracefully",
257
+ type: "booleanSelect",
258
+ options: [
259
+ { value: "true", label: "Yes — let it finish the current item" },
260
+ { value: "false", label: "No — stop it now" },
261
+ ],
262
+ advanced: true,
263
+ description: "With Yes, Apify sends the actor a signal and waits up to 30 s before killing it.",
264
+ },
265
+ ],
266
+ },
267
+ };
@@ -82,6 +82,7 @@ exports.NODE_CONNECTIONS = {
82
82
  githubAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
83
83
  jiraAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
84
84
  bucketAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
85
+ apifyAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
85
86
  googleContactsAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
86
87
  googleAnalyticsAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
87
88
  notionAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
@@ -70,6 +70,8 @@ export declare const CREDENTIAL_TYPES: readonly [{
70
70
  readonly type: "llm_ollama";
71
71
  }, {
72
72
  readonly type: "firecrawl";
73
+ }, {
74
+ readonly type: "apify";
73
75
  }, {
74
76
  readonly type: "http_auth";
75
77
  }, {
@@ -55,6 +55,9 @@ exports.CREDENTIAL_TYPES = [
55
55
  { type: 'llm_openrouter' },
56
56
  { type: 'llm_ollama' },
57
57
  { type: 'firecrawl' },
58
+ /* [2026-09-13] Apify no tiene OAuth para terceros: es un API token, como
59
+ Firecrawl. Lo lee el nodo `apifyAction`. */
60
+ { type: 'apify' },
58
61
  { type: 'http_auth' },
59
62
  { type: 'aws_s3' },
60
63
  { type: 'memory_contextwindow' },
package/dist/dispatch.js CHANGED
@@ -63,6 +63,7 @@ exports.NODE_DISPATCH = {
63
63
  githubAction: { service: 'githubActionsService', collection: 'githubactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
64
64
  jiraAction: { service: 'jiraActionsService', collection: 'jiraactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
65
65
  bucketAction: { service: 'bucketActionsService', collection: 'bucketactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
66
+ apifyAction: { service: 'apifyActionsService', collection: 'apifyactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
66
67
  slackAction: { service: 'slackActionsService', collection: 'slackactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
67
68
  googleContactsAction: { service: 'googleContactsActionsService', collection: 'googlecontactsactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
68
69
  googleAnalyticsAction: { service: 'googleAnalyticsActionsService', collection: 'googleanalyticsactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
@@ -0,0 +1,67 @@
1
+ /**
2
+ * El nodo de Apify: correr actores y tareas, y leer lo que dejan.
3
+ *
4
+ * ## Por qué existe
5
+ *
6
+ * [2026-09-13] Él tenía el polling montado a mano: «Start Apify job (HTTP) →
7
+ * Check status (HTTP) → Loop Until Complete (conditional) → else → Check», con
8
+ * el token pegado en cada HTTP. Apify no tiene OAuth para terceros —Zapier,
9
+ * Make y n8n van con token igual— así que la credencial es una API key como
10
+ * la de Firecrawl, y lo demás es un nodo con las llamadas ya escritas.
11
+ *
12
+ * ## La operación que motiva el nodo
13
+ *
14
+ * `runActorAndWait`: `run-sync-get-dataset-items` corre el actor y devuelve
15
+ * los items del dataset en la MISMA respuesta (hasta 300 s; pasado eso, 408).
16
+ * Con eso el flujo de arriba cabe en un nodo. Para actores más lentos siguen
17
+ * estando `startRun` + `getRun` + `getDatasetItems`, que es lo que él hacía a
18
+ * mano, ahora con la key en la credencial.
19
+ *
20
+ * ## Por qué siete
21
+ *
22
+ * Las tres del polling (`startRun`, `getRun`, `getDatasetItems`), la que lo
23
+ * evita (`runActorAndWait`), su gemela para tareas guardadas (`runTask`), el
24
+ * key-value store (`getKeyValueRecord`: `OUTPUT`, un `results-map`, lo que el
25
+ * actor guarde con nombre) y `abortRun`. Lo que queda fuera a propósito:
26
+ * listar actores y datasets del usuario, webhooks de Apify y el request
27
+ * queue — nada de eso hace falta para correr un actor y leer su resultado.
28
+ *
29
+ * ⚠️ El orden de este array es el orden del desplegable.
30
+ */
31
+ export declare const APIFY_OPERATIONS: readonly ["runActorAndWait", "startRun", "getRun", "getDatasetItems", "getKeyValueRecord", "runTask", "abortRun"];
32
+ export type ApifyOperation = (typeof APIFY_OPERATIONS)[number];
33
+ export declare function isApifyOperation(value: unknown): value is ApifyOperation;
34
+ /**
35
+ * Las que devuelven una COLECCIÓN sobre la que el nodo de abajo repite: los
36
+ * items de un dataset. `runActorAndWait` y `runTask` los traen en la misma
37
+ * respuesta; `getDatasetItems` los pide aparte. Las otras devuelven UN objeto
38
+ * (la corrida, el registro).
39
+ *
40
+ * ⚠️ Se itera `items`, y sólo `items`. La salida lleva `_meta.iterable: true`
41
+ * con `iterateField: 'items'`, como el crawl de Firecrawl.
42
+ */
43
+ export declare const APIFY_ITERABLE_OPERATIONS: ReadonlyArray<ApifyOperation>;
44
+ export type ApifyParamType = "template" | "textarea" | "json" | "select" | "number" | "booleanSelect";
45
+ export interface ApifyParamSpec {
46
+ name: string;
47
+ label: string;
48
+ type: ApifyParamType;
49
+ required?: boolean;
50
+ description?: string;
51
+ placeholder?: string;
52
+ default?: string | number;
53
+ options?: ReadonlyArray<{
54
+ value: string;
55
+ label: string;
56
+ }>;
57
+ min?: number;
58
+ max?: number;
59
+ advanced?: boolean;
60
+ }
61
+ export interface ApifyOperationSpec {
62
+ label: string;
63
+ description: string;
64
+ apiRoute: string;
65
+ params: ApifyParamSpec[];
66
+ }
67
+ export declare const APIFY_OPERATION_SPECS: Record<ApifyOperation, ApifyOperationSpec>;
@@ -0,0 +1,263 @@
1
+ /**
2
+ * El nodo de Apify: correr actores y tareas, y leer lo que dejan.
3
+ *
4
+ * ## Por qué existe
5
+ *
6
+ * [2026-09-13] Él tenía el polling montado a mano: «Start Apify job (HTTP) →
7
+ * Check status (HTTP) → Loop Until Complete (conditional) → else → Check», con
8
+ * el token pegado en cada HTTP. Apify no tiene OAuth para terceros —Zapier,
9
+ * Make y n8n van con token igual— así que la credencial es una API key como
10
+ * la de Firecrawl, y lo demás es un nodo con las llamadas ya escritas.
11
+ *
12
+ * ## La operación que motiva el nodo
13
+ *
14
+ * `runActorAndWait`: `run-sync-get-dataset-items` corre el actor y devuelve
15
+ * los items del dataset en la MISMA respuesta (hasta 300 s; pasado eso, 408).
16
+ * Con eso el flujo de arriba cabe en un nodo. Para actores más lentos siguen
17
+ * estando `startRun` + `getRun` + `getDatasetItems`, que es lo que él hacía a
18
+ * mano, ahora con la key en la credencial.
19
+ *
20
+ * ## Por qué siete
21
+ *
22
+ * Las tres del polling (`startRun`, `getRun`, `getDatasetItems`), la que lo
23
+ * evita (`runActorAndWait`), su gemela para tareas guardadas (`runTask`), el
24
+ * key-value store (`getKeyValueRecord`: `OUTPUT`, un `results-map`, lo que el
25
+ * actor guarde con nombre) y `abortRun`. Lo que queda fuera a propósito:
26
+ * listar actores y datasets del usuario, webhooks de Apify y el request
27
+ * queue — nada de eso hace falta para correr un actor y leer su resultado.
28
+ *
29
+ * ⚠️ El orden de este array es el orden del desplegable.
30
+ */
31
+ export const APIFY_OPERATIONS = [
32
+ "runActorAndWait",
33
+ "startRun",
34
+ "getRun",
35
+ "getDatasetItems",
36
+ "getKeyValueRecord",
37
+ "runTask",
38
+ "abortRun",
39
+ ];
40
+ export function isApifyOperation(value) {
41
+ return (typeof value === "string" &&
42
+ APIFY_OPERATIONS.includes(value));
43
+ }
44
+ /**
45
+ * Las que devuelven una COLECCIÓN sobre la que el nodo de abajo repite: los
46
+ * items de un dataset. `runActorAndWait` y `runTask` los traen en la misma
47
+ * respuesta; `getDatasetItems` los pide aparte. Las otras devuelven UN objeto
48
+ * (la corrida, el registro).
49
+ *
50
+ * ⚠️ Se itera `items`, y sólo `items`. La salida lleva `_meta.iterable: true`
51
+ * con `iterateField: 'items'`, como el crawl de Firecrawl.
52
+ */
53
+ export const APIFY_ITERABLE_OPERATIONS = [
54
+ "runActorAndWait",
55
+ "runTask",
56
+ "getDatasetItems",
57
+ ];
58
+ /* El actor se nombra como lo nombra Apify: `usuario~nombre` o su id. */
59
+ const actorId = () => ({
60
+ name: "actorId",
61
+ label: "Actor",
62
+ type: "template",
63
+ required: true,
64
+ placeholder: "apify~web-scraper or nwua9Gu5YrADL7ZDj",
65
+ description: "The actor to run, as username~actor-name or its ID. Supports {{payload.x}}.",
66
+ });
67
+ /* El input del actor es JSON libre: cada actor define el suyo. `json` se
68
+ escribe en la caja en corto (`clave: valor`) o como JSON de verdad, y las
69
+ cadenas de dentro admiten plantillas. */
70
+ const actorInput = () => ({
71
+ name: "input",
72
+ label: "Actor input",
73
+ type: "json",
74
+ description: "The input the actor expects (each actor documents its own). Strings inside may use {{payload.x}}. Leave it empty to run with the actor's defaults.",
75
+ });
76
+ const runId = () => ({
77
+ name: "runId",
78
+ label: "Run ID",
79
+ type: "template",
80
+ required: true,
81
+ placeholder: "{{payload.data.id}}",
82
+ description: "The run to look at — usually the `data.id` that Start actor run returned.",
83
+ });
84
+ /* Los tres ajustes de una corrida, en todas las que arrancan una. */
85
+ const runSettings = () => [
86
+ {
87
+ name: "timeoutSecs",
88
+ label: "Run timeout (seconds)",
89
+ type: "number",
90
+ min: 0,
91
+ max: 3600,
92
+ advanced: true,
93
+ description: "How long Apify lets the actor run. Empty = the actor's own default.",
94
+ },
95
+ {
96
+ name: "memoryMbytes",
97
+ label: "Memory (MB)",
98
+ type: "number",
99
+ min: 128,
100
+ max: 32768,
101
+ advanced: true,
102
+ description: "Memory for the run, a power of two from 128. Empty = the actor's own default.",
103
+ },
104
+ {
105
+ name: "build",
106
+ label: "Build",
107
+ type: "template",
108
+ placeholder: "latest",
109
+ advanced: true,
110
+ description: "Which build to run — a tag like latest or beta, or a build number. Empty = latest.",
111
+ },
112
+ ];
113
+ /* Cómo se piden los items de un dataset, en las tres que los devuelven. */
114
+ const itemSettings = () => [
115
+ {
116
+ name: "limit",
117
+ label: "Max items",
118
+ type: "number",
119
+ min: 1,
120
+ max: 250000,
121
+ description: "How many items to bring into the flow. Empty = all of them (careful with big datasets).",
122
+ },
123
+ {
124
+ name: "clean",
125
+ label: "Clean items",
126
+ type: "booleanSelect",
127
+ options: [
128
+ { value: "true", label: "Yes — skip empty items and hidden fields" },
129
+ { value: "false", label: "No — everything, as stored" },
130
+ ],
131
+ advanced: true,
132
+ description: 'Apify\'s "clean" flag: drops empty items and fields starting with #. Default is Yes.',
133
+ },
134
+ ];
135
+ export const APIFY_OPERATION_SPECS = {
136
+ runActorAndWait: {
137
+ label: "Run actor and wait",
138
+ description: "Runs the actor and returns its dataset items in the same step — no polling. Waits up to 5 minutes; for slower actors use Start actor run.",
139
+ apiRoute: "POST /v2/actors/{actorId}/run-sync-get-dataset-items",
140
+ params: [actorId(), actorInput(), ...itemSettings(), ...runSettings()],
141
+ },
142
+ startRun: {
143
+ label: "Start actor run",
144
+ description: "Starts the actor and returns the run right away (its ID, status and dataset ID). Check it later with Get run, or wait a bit with the option below.",
145
+ apiRoute: "POST /v2/actors/{actorId}/runs",
146
+ params: [
147
+ actorId(),
148
+ actorInput(),
149
+ {
150
+ name: "waitForFinishSecs",
151
+ label: "Wait for finish (seconds)",
152
+ type: "number",
153
+ min: 0,
154
+ max: 60,
155
+ description: "Up to 60 s: if the run finishes in time, the returned run already says SUCCEEDED. 0 or empty = come back immediately.",
156
+ },
157
+ ...runSettings(),
158
+ ],
159
+ },
160
+ getRun: {
161
+ label: "Get run",
162
+ description: "The current state of a run: RUNNING, SUCCEEDED, FAILED… plus its dataset and key-value store IDs. This is the check in a polling loop.",
163
+ apiRoute: "GET /v2/actor-runs/{runId}",
164
+ params: [runId()],
165
+ },
166
+ getDatasetItems: {
167
+ label: "Get dataset items",
168
+ description: "Reads the items of a dataset — usually the run's defaultDatasetId. Sent with your token, so it also works once the account is set to Restricted.",
169
+ apiRoute: "GET /v2/datasets/{datasetId}/items",
170
+ params: [
171
+ {
172
+ name: "datasetId",
173
+ label: "Dataset ID",
174
+ type: "template",
175
+ required: true,
176
+ placeholder: "{{payload.data.defaultDatasetId}}",
177
+ description: "The dataset to read, by ID or username~name.",
178
+ },
179
+ ...itemSettings(),
180
+ {
181
+ name: "offset",
182
+ label: "Skip items",
183
+ type: "number",
184
+ min: 0,
185
+ advanced: true,
186
+ description: "How many items to skip from the start. Empty = none.",
187
+ },
188
+ {
189
+ name: "fields",
190
+ label: "Only these fields",
191
+ type: "template",
192
+ placeholder: "title, url, price",
193
+ advanced: true,
194
+ description: "Comma-separated field names to keep in each item. Empty = every field.",
195
+ },
196
+ ],
197
+ },
198
+ getKeyValueRecord: {
199
+ label: "Get key-value record",
200
+ description: "Reads one record from a key-value store — the run's OUTPUT, a results-map, anything the actor stored by name. JSON comes back parsed; anything else as text.",
201
+ apiRoute: "GET /v2/key-value-stores/{storeId}/records/{recordKey}",
202
+ params: [
203
+ {
204
+ name: "storeId",
205
+ label: "Store ID",
206
+ type: "template",
207
+ required: true,
208
+ placeholder: "{{payload.data.defaultKeyValueStoreId}}",
209
+ description: "The key-value store, by ID or username~name.",
210
+ },
211
+ {
212
+ name: "recordKey",
213
+ label: "Record key",
214
+ type: "template",
215
+ required: true,
216
+ placeholder: "OUTPUT",
217
+ description: "The record to read.",
218
+ },
219
+ ],
220
+ },
221
+ runTask: {
222
+ label: "Run task and wait",
223
+ description: "Runs a saved task (an actor with its input already set in Apify) and returns its dataset items. Waits up to 5 minutes.",
224
+ apiRoute: "POST /v2/actor-tasks/{taskId}/run-sync-get-dataset-items",
225
+ params: [
226
+ {
227
+ name: "taskId",
228
+ label: "Task",
229
+ type: "template",
230
+ required: true,
231
+ placeholder: "username~my-task or its ID",
232
+ description: "The task to run, as username~task-name or its ID.",
233
+ },
234
+ {
235
+ name: "input",
236
+ label: "Input overrides",
237
+ type: "json",
238
+ description: "Fields to override on top of the task's saved input. Empty = run the task as saved.",
239
+ },
240
+ ...itemSettings(),
241
+ ...runSettings(),
242
+ ],
243
+ },
244
+ abortRun: {
245
+ label: "Abort run",
246
+ description: "Stops a run that is still going. Returns the run with its final state.",
247
+ apiRoute: "POST /v2/actor-runs/{runId}/abort",
248
+ params: [
249
+ runId(),
250
+ {
251
+ name: "gracefully",
252
+ label: "Gracefully",
253
+ type: "booleanSelect",
254
+ options: [
255
+ { value: "true", label: "Yes — let it finish the current item" },
256
+ { value: "false", label: "No — stop it now" },
257
+ ],
258
+ advanced: true,
259
+ description: "With Yes, Apify sends the actor a signal and waits up to 30 s before killing it.",
260
+ },
261
+ ],
262
+ },
263
+ };
@@ -74,6 +74,7 @@ export const NODE_CONNECTIONS = {
74
74
  githubAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
75
75
  jiraAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
76
76
  bucketAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
77
+ apifyAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
77
78
  googleContactsAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
78
79
  googleAnalyticsAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
79
80
  notionAction: { acceptsInputFrom: ACTION_INPUTS, canOutputTo: PROCESSING_OUTPUTS },
@@ -70,6 +70,8 @@ export declare const CREDENTIAL_TYPES: readonly [{
70
70
  readonly type: "llm_ollama";
71
71
  }, {
72
72
  readonly type: "firecrawl";
73
+ }, {
74
+ readonly type: "apify";
73
75
  }, {
74
76
  readonly type: "http_auth";
75
77
  }, {
@@ -50,6 +50,9 @@ export const CREDENTIAL_TYPES = [
50
50
  { type: 'llm_openrouter' },
51
51
  { type: 'llm_ollama' },
52
52
  { type: 'firecrawl' },
53
+ /* [2026-09-13] Apify no tiene OAuth para terceros: es un API token, como
54
+ Firecrawl. Lo lee el nodo `apifyAction`. */
55
+ { type: 'apify' },
53
56
  { type: 'http_auth' },
54
57
  { type: 'aws_s3' },
55
58
  { type: 'memory_contextwindow' },
@@ -57,6 +57,7 @@ export const NODE_DISPATCH = {
57
57
  githubAction: { service: 'githubActionsService', collection: 'githubactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
58
58
  jiraAction: { service: 'jiraActionsService', collection: 'jiraactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
59
59
  bucketAction: { service: 'bucketActionsService', collection: 'bucketactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
60
+ apifyAction: { service: 'apifyActionsService', collection: 'apifyactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
60
61
  slackAction: { service: 'slackActionsService', collection: 'slackactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
61
62
  googleContactsAction: { service: 'googleContactsActionsService', collection: 'googlecontactsactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
62
63
  googleAnalyticsAction: { service: 'googleAnalyticsActionsService', collection: 'googleanalyticsactions', hasFilters: true, outputFields: ['outputNodes'], customDispatch: true, pipelineDispatch: 'excluded', downstreamPayload: 'result' },
@@ -38,6 +38,8 @@ export { JIRA_OPERATIONS, JIRA_OPERATION_SPECS, JIRA_DROPDOWN_OPERATIONS, JIRA_I
38
38
  export type { JiraOperation, JiraParamType, JiraParamSpec, JiraOperationSpec, } from './jira-operations.js';
39
39
  export { BUCKET_OPERATIONS, BUCKET_OPERATION_SPECS, BUCKET_ITERABLE_OPERATIONS, isBucketOperation, } from './bucket-operations.js';
40
40
  export type { BucketOperation, BucketParamType, BucketParamSpec, BucketOperationSpec, } from './bucket-operations.js';
41
+ export { APIFY_OPERATIONS, APIFY_OPERATION_SPECS, APIFY_ITERABLE_OPERATIONS, isApifyOperation, } from './apify-operations.js';
42
+ export type { ApifyOperation, ApifyParamType, ApifyParamSpec, ApifyOperationSpec, } from './apify-operations.js';
41
43
  export { SLACK_OPERATIONS, SLACK_OPERATION_SPECS, SLACK_CAPACIDADES_POR_CREDENCIAL, operacionesDeSlackPara, slackPuedeEjecutar, camposDeSlackNoDisponibles, isSlackOperation, } from './slack-operations.js';
42
44
  export type { SlackOperation, SlackParamSpec, SlackOperationSpec, } from './slack-operations.js';
43
45
  export { SLACK_TOOLKIT_SPECS, SLACK_TOOLKIT_BY_TOOL_NAME, herramientasDeSlackPara, } from './slack-toolkit.js';
package/dist/esm/index.js CHANGED
@@ -35,6 +35,7 @@ export { SHOPIFY_OPERATIONS, SHOPIFY_OPERATION_SPECS, SHOPIFY_OPERATION_SCOPES,
35
35
  export { GITHUB_OPERATIONS, GITHUB_OPERATION_SPECS, GITHUB_DROPDOWN_OPERATIONS, GITHUB_ITERABLE_OPERATIONS, isGithubOperation, } from './github-operations.js';
36
36
  export { JIRA_OPERATIONS, JIRA_OPERATION_SPECS, JIRA_DROPDOWN_OPERATIONS, JIRA_ITERABLE_OPERATIONS, isJiraOperation, } from './jira-operations.js';
37
37
  export { BUCKET_OPERATIONS, BUCKET_OPERATION_SPECS, BUCKET_ITERABLE_OPERATIONS, isBucketOperation, } from './bucket-operations.js';
38
+ export { APIFY_OPERATIONS, APIFY_OPERATION_SPECS, APIFY_ITERABLE_OPERATIONS, isApifyOperation, } from './apify-operations.js';
38
39
  export { SLACK_OPERATIONS, SLACK_OPERATION_SPECS, SLACK_CAPACIDADES_POR_CREDENCIAL, operacionesDeSlackPara, slackPuedeEjecutar, camposDeSlackNoDisponibles, isSlackOperation, } from './slack-operations.js';
39
40
  /* Misma pareja que en Discord: `SlackOperationSpec` es el formulario,
40
41
  `SlackToolkitSpec` es la herramienta que ve el LLM. */
@@ -629,6 +629,22 @@ export const NODE_REGISTRY = {
629
629
  veces —specs del dashboard para el AI Node y specs de la api para MCP— y
630
630
  esa duplicacion no se paga antes de ver el nodo en pantalla. */
631
631
  },
632
+ apifyAction: {
633
+ type: "apifyAction",
634
+ prefix: "apify",
635
+ label: "Apify",
636
+ group: "Actions",
637
+ detailPath: "/dashboard/apify-actions",
638
+ apiPath: "/apify-actions",
639
+ stateKey: "apifyActions",
640
+ allStateKey: "allApifyActions",
641
+ /* [2026-09-13] El verde de Apify (`#97d700` en su marca), oscurecido
642
+ para que aguante sobre el lienzo claro y no se confunda con el verde
643
+ de éxito de los pasos. Mírese en el minimapa, como los vecinos. */
644
+ color: "#5f8f00",
645
+ testable: true,
646
+ /* Sin `isToolOnly`: no trae modo toolkit de IA todavía. */
647
+ },
632
648
  telegramAction: {
633
649
  type: "telegramAction",
634
650
  prefix: "tg",
@@ -1,5 +1,5 @@
1
1
  /** All valid node type identifiers */
2
- export type NodeType = 'webhook' | 'scheduledWorkflow' | 'chatTrigger' | 'trigger' | 'voiceAgent' | 'filter' | 'transform' | 'schemaValidator' | 'conditional' | 'delay' | 'rateLimiter' | 'aggregator' | 'cache' | 'code' | 'ai' | 'merge' | 'approval' | 'split' | 'loop' | 'markdown' | 'fileTransform' | 'limit' | 'router' | 'emailAction' | 'gmailAction' | 'httpAction' | 'mongoAction' | 'postgresAction' | 'notificationAction' | 'sheetsAction' | 'calendarAction' | 'docsAction' | 'driveAction' | 'firecrawlAction' | 'telegramAction' | 'whatsappAction' | 'discordAction' | 'slackAction' | 'googleContactsAction' | 'googleAnalyticsAction' | 'notionAction' | 'vectorStore' | 'rssAction' | 'socialMediaAction' | 'mailchimpAction' | 'shopifyAction' | 'githubAction' | 'jiraAction' | 'bucketAction' | 'stickyNote';
2
+ export type NodeType = 'webhook' | 'scheduledWorkflow' | 'chatTrigger' | 'trigger' | 'voiceAgent' | 'filter' | 'transform' | 'schemaValidator' | 'conditional' | 'delay' | 'rateLimiter' | 'aggregator' | 'cache' | 'code' | 'ai' | 'merge' | 'approval' | 'split' | 'loop' | 'markdown' | 'fileTransform' | 'limit' | 'router' | 'emailAction' | 'gmailAction' | 'httpAction' | 'mongoAction' | 'postgresAction' | 'notificationAction' | 'sheetsAction' | 'calendarAction' | 'docsAction' | 'driveAction' | 'firecrawlAction' | 'telegramAction' | 'whatsappAction' | 'discordAction' | 'slackAction' | 'googleContactsAction' | 'googleAnalyticsAction' | 'notionAction' | 'vectorStore' | 'rssAction' | 'socialMediaAction' | 'mailchimpAction' | 'shopifyAction' | 'githubAction' | 'jiraAction' | 'bucketAction' | 'apifyAction' | 'stickyNote';
3
3
  /** Node role in the pipeline */
4
4
  export type NodeRole = 'source' | 'processing' | 'flowControl' | 'routing' | 'action' | 'monitoring';
5
5
  /** Handle positions on the canvas node */
package/dist/esm/ui.js CHANGED
@@ -94,6 +94,7 @@ export const NODE_UI = {
94
94
  githubAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'github' } },
95
95
  jiraAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'jira' } },
96
96
  bucketAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'bucket' } },
97
+ apifyAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'apify' } },
97
98
  slackAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'slack' } },
98
99
  googleContactsAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true } },
99
100
  googleAnalyticsAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true } },
@@ -122,6 +123,7 @@ export const PREFIX_TO_TYPE = [
122
123
  { prefix: 'gh-', type: 'githubAction', canvasType: 'githubAction' },
123
124
  { prefix: 'jr-', type: 'jiraAction', canvasType: 'jiraAction' },
124
125
  { prefix: 'bkt-', type: 'bucketAction', canvasType: 'bucketAction' },
126
+ { prefix: 'apify-', type: 'apifyAction', canvasType: 'apifyAction' },
125
127
  { prefix: 'gc-', type: 'googleContactsAction', canvasType: 'googleContactsAction' },
126
128
  { prefix: 'gaa-', type: 'googleAnalyticsAction', canvasType: 'googleAnalyticsAction' },
127
129
  { prefix: 'ntn-', type: 'notionAction', canvasType: 'notionAction' },
package/dist/index.d.ts CHANGED
@@ -38,6 +38,8 @@ export { JIRA_OPERATIONS, JIRA_OPERATION_SPECS, JIRA_DROPDOWN_OPERATIONS, JIRA_I
38
38
  export type { JiraOperation, JiraParamType, JiraParamSpec, JiraOperationSpec, } from './jira-operations.js';
39
39
  export { BUCKET_OPERATIONS, BUCKET_OPERATION_SPECS, BUCKET_ITERABLE_OPERATIONS, isBucketOperation, } from './bucket-operations.js';
40
40
  export type { BucketOperation, BucketParamType, BucketParamSpec, BucketOperationSpec, } from './bucket-operations.js';
41
+ export { APIFY_OPERATIONS, APIFY_OPERATION_SPECS, APIFY_ITERABLE_OPERATIONS, isApifyOperation, } from './apify-operations.js';
42
+ export type { ApifyOperation, ApifyParamType, ApifyParamSpec, ApifyOperationSpec, } from './apify-operations.js';
41
43
  export { SLACK_OPERATIONS, SLACK_OPERATION_SPECS, SLACK_CAPACIDADES_POR_CREDENCIAL, operacionesDeSlackPara, slackPuedeEjecutar, camposDeSlackNoDisponibles, isSlackOperation, } from './slack-operations.js';
42
44
  export type { SlackOperation, SlackParamSpec, SlackOperationSpec, } from './slack-operations.js';
43
45
  export { SLACK_TOOLKIT_SPECS, SLACK_TOOLKIT_BY_TOOL_NAME, herramientasDeSlackPara, } from './slack-toolkit.js';
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DRIVE_OPERATIONS = exports.GOOGLE_CALENDAR_TOOLKIT_BY_TOOL_NAME = exports.GOOGLE_CALENDAR_TOOLKIT_SPECS = exports.isGoogleCalendarOperation = exports.GOOGLE_CALENDAR_OPERATION_SPECS = exports.GOOGLE_CALENDAR_OPERATIONS = exports.isGmailOperation = exports.resolveGmailSendFields = exports.GMAIL_SEND_LEGACY_FIELDS = exports.NATIVE_EMAIL_TOOLKIT_BY_TOOL_NAME = exports.GMAIL_TOOLKIT_BY_TOOL_NAME = exports.NATIVE_EMAIL_TOOLKIT_SPECS = exports.GMAIL_SEND_AND_WAIT_TOOL_SPEC = exports.GMAIL_ALL_TOOLKIT_SPECS = exports.GMAIL_TOOLKIT_SPECS = exports.GMAIL_TOOLKIT_OPERATIONS = exports.GMAIL_DROPDOWN_OPERATIONS = exports.GMAIL_OPERATION_GROUPS = exports.GMAIL_OPERATION_SPECS = exports.GMAIL_OPERATIONS = exports.versionCatalogErrors = exports.fieldsLost = exports.fieldsLostBetween = exports.currentVersion = exports.versionSpec = exports.versionsOf = exports.isVersioned = exports.NODE_TYPE_TO_PREFIX = exports.PREFIX_TO_NODE_TYPE = exports.NODE_STATE_KEYS = exports.NODE_COLORS = exports.NODE_DETAIL_PATHS = exports.getNodeRegistryEntry = exports.NODE_REGISTRY = exports.pasaLoQueRecibe = exports.getNodeDispatchConfig = exports.getAllNodeCollections = exports.NODE_DISPATCH = exports.resolveNodeId = exports.PREFIX_TO_TYPE = exports.NODE_UI = exports.ALL_NODE_TYPES = exports.isNodeType = exports.isTerminal = exports.canSendToNodes = exports.canReceiveFromNodes = exports.canReceiveFrom = exports.NODE_CONNECTIONS = exports.iterableMeta = exports.singleMeta = void 0;
4
4
  exports.BUCKET_ITERABLE_OPERATIONS = exports.BUCKET_OPERATION_SPECS = exports.BUCKET_OPERATIONS = exports.isJiraOperation = exports.JIRA_ITERABLE_OPERATIONS = exports.JIRA_DROPDOWN_OPERATIONS = exports.JIRA_OPERATION_SPECS = exports.JIRA_OPERATIONS = exports.isGithubOperation = exports.GITHUB_ITERABLE_OPERATIONS = exports.GITHUB_DROPDOWN_OPERATIONS = exports.GITHUB_OPERATION_SPECS = exports.GITHUB_OPERATIONS = exports.scopesQueFaltanEnShopify = exports.isShopifyOperation = exports.SHOPIFY_PRODUCT_STATUSES = exports.SHOPIFY_CANCEL_REASONS = exports.SHOPIFY_SEARCHABLE_RESOURCES = exports.SHOPIFY_TAGGABLE_RESOURCES = exports.SHOPIFY_OPERATION_SCOPES = exports.SHOPIFY_OPERATION_SPECS = exports.SHOPIFY_OPERATIONS = exports.isMailchimpOperation = exports.MAILCHIMP_CONTACT_STATUSES = exports.MAILCHIMP_OPERATION_SPECS = exports.MAILCHIMP_OPERATIONS = exports.herramientasDeDiscordPara = exports.DISCORD_TOOLKIT_BY_TOOL_NAME = exports.DISCORD_TOOLKIT_SPECS = exports.isDiscordOperation = exports.camposDeDiscordNoDisponibles = exports.discordPuedeEjecutar = exports.operacionesDeDiscordPara = exports.DISCORD_CAPACIDADES_POR_CREDENCIAL = exports.DISCORD_OPERATION_SPECS = exports.DISCORD_OPERATIONS = exports.camposNoDisponiblesPara = exports.puedeEjecutar = exports.operacionesPara = exports.isWhatsAppOperation = exports.WHATSAPP_OPERATIONS = exports.TELEGRAM_TOOLKIT_BY_TOOL_NAME = exports.TELEGRAM_TOOLKIT_SPECS = exports.isTelegramOperation = exports.TELEGRAM_OPERATION_SPECS = exports.TELEGRAM_OPERATIONS = exports.DRIVE_TOOLKIT_BY_TOOL_NAME = exports.DRIVE_TOOLKIT_SPECS = exports.isDriveOperation = exports.DRIVE_OPERATION_SPECS = void 0;
5
- exports.getDefaultModel = exports.getModelsFor = exports.MODEL_CONTEXT_WINDOWS = exports.LLM_MODELS = exports.LLM_PROVIDERS = exports.DOCS_TOOLKIT_DEFAULTABLE = exports.DOCS_TOOLKIT_BY_TOOL_NAME = exports.DOCS_TOOLKIT_SPECS = exports.isDocsOperation = exports.DOCS_OPERATION_SPECS = exports.DOCS_OPERATIONS = exports.isMongoOperation = exports.MONGO_OPERATION_SPECS = exports.MONGO_OPERATIONS = exports.isPostgresOperation = exports.POSTGRES_OPERATION_SPECS = exports.POSTGRES_MODES = exports.POSTGRES_OPERATIONS = exports.isNotionOperation = exports.NOTION_DROPDOWN_OPERATIONS = exports.NOTION_OPERATION_SPECS = exports.NOTION_OPERATIONS = exports.isGoogleAnalyticsOperation = exports.GOOGLE_ANALYTICS_DROPDOWN_OPERATIONS = exports.GOOGLE_ANALYTICS_OPERATION_SPECS = exports.GOOGLE_ANALYTICS_OPERATIONS = exports.isGoogleContactsOperation = exports.GOOGLE_CONTACTS_DEFAULT_PERSON_FIELDS = exports.GOOGLE_CONTACTS_OPERATION_GROUPS = exports.GOOGLE_CONTACTS_OPERATION_SPECS = exports.GOOGLE_CONTACTS_OPERATIONS_V2 = exports.GOOGLE_CONTACTS_OPERATIONS_V1 = exports.GOOGLE_CONTACTS_OPERATIONS = exports.SHEETS_TOOLKIT_DEFAULTABLE = exports.SHEETS_TOOLKIT_BY_TOOL_NAME = exports.SHEETS_TOOLKIT_SPECS = exports.isSheetsOperation = exports.SHEETS_OPERATION_SPECS = exports.SHEETS_OPERATIONS = exports.herramientasDeSlackPara = exports.SLACK_TOOLKIT_BY_TOOL_NAME = exports.SLACK_TOOLKIT_SPECS = exports.isSlackOperation = exports.camposDeSlackNoDisponibles = exports.slackPuedeEjecutar = exports.operacionesDeSlackPara = exports.SLACK_CAPACIDADES_POR_CREDENCIAL = exports.SLACK_OPERATION_SPECS = exports.SLACK_OPERATIONS = exports.isBucketOperation = void 0;
6
- exports.armarRespuestaDelSync = exports.RESPUESTA_DEL_SYNC_POR_DEFECTO = exports.TOPE_DE_ESPERA_DEL_SYNC = exports.TOPES_DE_ESTADO = exports.SOBRES_DE_RESPUESTA = exports.MODOS_DE_PAYLOAD = exports.NIVELES_DE_DETALLE = exports.RESULTADOS_DEL_VALIDADOR = exports.contestaEnSync = exports.NODOS_QUE_CONTESTAN_EN_SYNC = exports.isCredentialType = exports.getCredentialType = exports.credentialTypeValues = exports.CREDENTIAL_TYPE_VALUES = exports.CREDENTIAL_TYPES = exports.ventanaDeContextoDeOpenRouter = exports.opcionesDeModelosDeOpenRouter = exports.URL_DE_MODELOS_DE_OPENROUTER = exports.getModelLabel = void 0;
5
+ exports.LLM_PROVIDERS = exports.DOCS_TOOLKIT_DEFAULTABLE = exports.DOCS_TOOLKIT_BY_TOOL_NAME = exports.DOCS_TOOLKIT_SPECS = exports.isDocsOperation = exports.DOCS_OPERATION_SPECS = exports.DOCS_OPERATIONS = exports.isMongoOperation = exports.MONGO_OPERATION_SPECS = exports.MONGO_OPERATIONS = exports.isPostgresOperation = exports.POSTGRES_OPERATION_SPECS = exports.POSTGRES_MODES = exports.POSTGRES_OPERATIONS = exports.isNotionOperation = exports.NOTION_DROPDOWN_OPERATIONS = exports.NOTION_OPERATION_SPECS = exports.NOTION_OPERATIONS = exports.isGoogleAnalyticsOperation = exports.GOOGLE_ANALYTICS_DROPDOWN_OPERATIONS = exports.GOOGLE_ANALYTICS_OPERATION_SPECS = exports.GOOGLE_ANALYTICS_OPERATIONS = exports.isGoogleContactsOperation = exports.GOOGLE_CONTACTS_DEFAULT_PERSON_FIELDS = exports.GOOGLE_CONTACTS_OPERATION_GROUPS = exports.GOOGLE_CONTACTS_OPERATION_SPECS = exports.GOOGLE_CONTACTS_OPERATIONS_V2 = exports.GOOGLE_CONTACTS_OPERATIONS_V1 = exports.GOOGLE_CONTACTS_OPERATIONS = exports.SHEETS_TOOLKIT_DEFAULTABLE = exports.SHEETS_TOOLKIT_BY_TOOL_NAME = exports.SHEETS_TOOLKIT_SPECS = exports.isSheetsOperation = exports.SHEETS_OPERATION_SPECS = exports.SHEETS_OPERATIONS = exports.herramientasDeSlackPara = exports.SLACK_TOOLKIT_BY_TOOL_NAME = exports.SLACK_TOOLKIT_SPECS = exports.isSlackOperation = exports.camposDeSlackNoDisponibles = exports.slackPuedeEjecutar = exports.operacionesDeSlackPara = exports.SLACK_CAPACIDADES_POR_CREDENCIAL = exports.SLACK_OPERATION_SPECS = exports.SLACK_OPERATIONS = exports.isApifyOperation = exports.APIFY_ITERABLE_OPERATIONS = exports.APIFY_OPERATION_SPECS = exports.APIFY_OPERATIONS = exports.isBucketOperation = void 0;
6
+ exports.armarRespuestaDelSync = exports.RESPUESTA_DEL_SYNC_POR_DEFECTO = exports.TOPE_DE_ESPERA_DEL_SYNC = exports.TOPES_DE_ESTADO = exports.SOBRES_DE_RESPUESTA = exports.MODOS_DE_PAYLOAD = exports.NIVELES_DE_DETALLE = exports.RESULTADOS_DEL_VALIDADOR = exports.contestaEnSync = exports.NODOS_QUE_CONTESTAN_EN_SYNC = exports.isCredentialType = exports.getCredentialType = exports.credentialTypeValues = exports.CREDENTIAL_TYPE_VALUES = exports.CREDENTIAL_TYPES = exports.ventanaDeContextoDeOpenRouter = exports.opcionesDeModelosDeOpenRouter = exports.URL_DE_MODELOS_DE_OPENROUTER = exports.getModelLabel = exports.getDefaultModel = exports.getModelsFor = exports.MODEL_CONTEXT_WINDOWS = exports.LLM_MODELS = void 0;
7
7
  var types_js_1 = require("./types.js");
8
8
  Object.defineProperty(exports, "singleMeta", { enumerable: true, get: function () { return types_js_1.singleMeta; } });
9
9
  Object.defineProperty(exports, "iterableMeta", { enumerable: true, get: function () { return types_js_1.iterableMeta; } });
@@ -142,6 +142,11 @@ Object.defineProperty(exports, "BUCKET_OPERATIONS", { enumerable: true, get: fun
142
142
  Object.defineProperty(exports, "BUCKET_OPERATION_SPECS", { enumerable: true, get: function () { return bucket_operations_js_1.BUCKET_OPERATION_SPECS; } });
143
143
  Object.defineProperty(exports, "BUCKET_ITERABLE_OPERATIONS", { enumerable: true, get: function () { return bucket_operations_js_1.BUCKET_ITERABLE_OPERATIONS; } });
144
144
  Object.defineProperty(exports, "isBucketOperation", { enumerable: true, get: function () { return bucket_operations_js_1.isBucketOperation; } });
145
+ var apify_operations_js_1 = require("./apify-operations.js");
146
+ Object.defineProperty(exports, "APIFY_OPERATIONS", { enumerable: true, get: function () { return apify_operations_js_1.APIFY_OPERATIONS; } });
147
+ Object.defineProperty(exports, "APIFY_OPERATION_SPECS", { enumerable: true, get: function () { return apify_operations_js_1.APIFY_OPERATION_SPECS; } });
148
+ Object.defineProperty(exports, "APIFY_ITERABLE_OPERATIONS", { enumerable: true, get: function () { return apify_operations_js_1.APIFY_ITERABLE_OPERATIONS; } });
149
+ Object.defineProperty(exports, "isApifyOperation", { enumerable: true, get: function () { return apify_operations_js_1.isApifyOperation; } });
145
150
  var slack_operations_js_1 = require("./slack-operations.js");
146
151
  Object.defineProperty(exports, "SLACK_OPERATIONS", { enumerable: true, get: function () { return slack_operations_js_1.SLACK_OPERATIONS; } });
147
152
  Object.defineProperty(exports, "SLACK_OPERATION_SPECS", { enumerable: true, get: function () { return slack_operations_js_1.SLACK_OPERATION_SPECS; } });
package/dist/registry.js CHANGED
@@ -640,6 +640,22 @@ exports.NODE_REGISTRY = {
640
640
  veces —specs del dashboard para el AI Node y specs de la api para MCP— y
641
641
  esa duplicacion no se paga antes de ver el nodo en pantalla. */
642
642
  },
643
+ apifyAction: {
644
+ type: "apifyAction",
645
+ prefix: "apify",
646
+ label: "Apify",
647
+ group: "Actions",
648
+ detailPath: "/dashboard/apify-actions",
649
+ apiPath: "/apify-actions",
650
+ stateKey: "apifyActions",
651
+ allStateKey: "allApifyActions",
652
+ /* [2026-09-13] El verde de Apify (`#97d700` en su marca), oscurecido
653
+ para que aguante sobre el lienzo claro y no se confunda con el verde
654
+ de éxito de los pasos. Mírese en el minimapa, como los vecinos. */
655
+ color: "#5f8f00",
656
+ testable: true,
657
+ /* Sin `isToolOnly`: no trae modo toolkit de IA todavía. */
658
+ },
643
659
  telegramAction: {
644
660
  type: "telegramAction",
645
661
  prefix: "tg",
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** All valid node type identifiers */
2
- export type NodeType = 'webhook' | 'scheduledWorkflow' | 'chatTrigger' | 'trigger' | 'voiceAgent' | 'filter' | 'transform' | 'schemaValidator' | 'conditional' | 'delay' | 'rateLimiter' | 'aggregator' | 'cache' | 'code' | 'ai' | 'merge' | 'approval' | 'split' | 'loop' | 'markdown' | 'fileTransform' | 'limit' | 'router' | 'emailAction' | 'gmailAction' | 'httpAction' | 'mongoAction' | 'postgresAction' | 'notificationAction' | 'sheetsAction' | 'calendarAction' | 'docsAction' | 'driveAction' | 'firecrawlAction' | 'telegramAction' | 'whatsappAction' | 'discordAction' | 'slackAction' | 'googleContactsAction' | 'googleAnalyticsAction' | 'notionAction' | 'vectorStore' | 'rssAction' | 'socialMediaAction' | 'mailchimpAction' | 'shopifyAction' | 'githubAction' | 'jiraAction' | 'bucketAction' | 'stickyNote';
2
+ export type NodeType = 'webhook' | 'scheduledWorkflow' | 'chatTrigger' | 'trigger' | 'voiceAgent' | 'filter' | 'transform' | 'schemaValidator' | 'conditional' | 'delay' | 'rateLimiter' | 'aggregator' | 'cache' | 'code' | 'ai' | 'merge' | 'approval' | 'split' | 'loop' | 'markdown' | 'fileTransform' | 'limit' | 'router' | 'emailAction' | 'gmailAction' | 'httpAction' | 'mongoAction' | 'postgresAction' | 'notificationAction' | 'sheetsAction' | 'calendarAction' | 'docsAction' | 'driveAction' | 'firecrawlAction' | 'telegramAction' | 'whatsappAction' | 'discordAction' | 'slackAction' | 'googleContactsAction' | 'googleAnalyticsAction' | 'notionAction' | 'vectorStore' | 'rssAction' | 'socialMediaAction' | 'mailchimpAction' | 'shopifyAction' | 'githubAction' | 'jiraAction' | 'bucketAction' | 'apifyAction' | 'stickyNote';
3
3
  /** Node role in the pipeline */
4
4
  export type NodeRole = 'source' | 'processing' | 'flowControl' | 'routing' | 'action' | 'monitoring';
5
5
  /** Handle positions on the canvas node */
package/dist/ui.js CHANGED
@@ -98,6 +98,7 @@ exports.NODE_UI = {
98
98
  githubAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'github' } },
99
99
  jiraAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'jira' } },
100
100
  bucketAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'bucket' } },
101
+ apifyAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'apify' } },
101
102
  slackAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true, routerTargetLabel: 'slack' } },
102
103
  googleContactsAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true } },
103
104
  googleAnalyticsAction: { fromNodes: true, toNodes: true, inputHandles: ['left'], dotHandles: { input: ['left-in'], output: ['right-out'] }, special: { loopBackAllowed: true } },
@@ -126,6 +127,7 @@ exports.PREFIX_TO_TYPE = [
126
127
  { prefix: 'gh-', type: 'githubAction', canvasType: 'githubAction' },
127
128
  { prefix: 'jr-', type: 'jiraAction', canvasType: 'jiraAction' },
128
129
  { prefix: 'bkt-', type: 'bucketAction', canvasType: 'bucketAction' },
130
+ { prefix: 'apify-', type: 'apifyAction', canvasType: 'apifyAction' },
129
131
  { prefix: 'gc-', type: 'googleContactsAction', canvasType: 'googleContactsAction' },
130
132
  { prefix: 'gaa-', type: 'googleAnalyticsAction', canvasType: 'googleAnalyticsAction' },
131
133
  { prefix: 'ntn-', type: 'notionAction', canvasType: 'notionAction' },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostwebhook/node-types",
3
- "version": "1.80.0",
3
+ "version": "1.81.0",
4
4
  "description": "Shared node type definitions, connection rules, and dispatch config for HostWebhook",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",