n8n-nodes-apivault-newegg 0.1.0 → 0.2.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.
package/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Apivault
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction... THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Apivault
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction... THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
package/README.md CHANGED
@@ -1,14 +1,11 @@
1
- # n8n-nodes-apivault-newegg
2
-
3
- n8n community node for **Newegg Product Scraper**.
4
-
5
- Scrape Newegg product pages in real-time — title, price, rating, reviews, brand, availability. Ideal for PC parts, electronics, tech arbitrage.
6
-
7
- ## Install
8
- n8n: Settings → Community Nodes → Install → `n8n-nodes-apivault-newegg`
9
-
10
- ## Credential
11
- Add an **Apify API** credential with your Apify token (Apify Console → Settings → Integrations). Free account includes monthly credits.
12
-
13
- ---
14
- Backed by the Apify Actor [`apivault_labs/newegg-product-scraper`](https://apify.com/apivault_labs/newegg-product-scraper).
1
+ # Newegg Product Scraper — n8n node
2
+
3
+ Calls the hosted [Apify Actor](https://apify.com/apivault_labs/newegg-product-scraper). Requires your own Apify credential; Apify run charges apply.
4
+
5
+ Install `n8n-nodes-apivault-newegg` through Settings → Community nodes → Install in self-hosted n8n.
6
+
7
+ ## Upgrade compatibility
8
+
9
+ Existing node names, credential type and input parameter names are retained. Existing version 1 workflows keep their previous charge behavior unless an event cap is selected. New version 2 nodes default to a $0.05 event charge cap and 1,000 downloaded rows; platform usage can be charged separately. Select Read Existing Run and provide the Run ID to resume without starting a paid duplicate. Full output includes run metadata, SUMMARY and ERRORS when available. Dataset rows retain their original fields and paired input item. Actor build is latest.
10
+
11
+ Runtime dependencies: none. n8n Cloud availability requires separate n8n verification.
@@ -1,6 +1,10 @@
1
1
  import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
2
  export declare class ApifyApi implements ICredentialType {
3
3
  name: string;
4
+ icon: {
5
+ readonly light: "file:apivault.svg";
6
+ readonly dark: "file:apivault.svg";
7
+ };
4
8
  displayName: string;
5
9
  documentationUrl: string;
6
10
  properties: INodeProperties[];
@@ -2,27 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ApifyApi = void 0;
4
4
  class ApifyApi {
5
- constructor() {
6
- this.name = 'apifyApi';
7
- this.displayName = 'Apify API';
8
- this.documentationUrl = 'https://docs.apify.com/platform/integrations/api';
9
- this.properties = [
10
- {
11
- displayName: 'API Token',
12
- name: 'apiToken',
13
- type: 'string',
14
- typeOptions: { password: true },
15
- default: '',
16
- required: true,
17
- description: 'Your personal Apify API token (Apify Console -> Settings -> Integrations).',
18
- },
19
- ];
20
- this.authenticate = {
21
- type: 'generic',
22
- properties: { headers: { Authorization: '=Bearer {{$credentials.apiToken}}' } },
23
- };
24
- this.test = { request: { baseURL: 'https://api.apify.com/v2', url: '/users/me' } };
25
- }
5
+ name = 'apifyApi';
6
+ icon = { light: 'file:apivault.svg', dark: 'file:apivault.svg' };
7
+ displayName = 'Apify API';
8
+ documentationUrl = 'https://docs.apify.com/platform/integrations/api';
9
+ properties = [
10
+ {
11
+ displayName: 'API Token',
12
+ name: 'apiToken',
13
+ type: 'string',
14
+ typeOptions: { password: true },
15
+ default: '',
16
+ required: true,
17
+ description: 'Your personal Apify API token (Apify Console -> Settings -> Integrations).',
18
+ },
19
+ ];
20
+ authenticate = {
21
+ type: 'generic',
22
+ properties: { headers: { Authorization: '=Bearer {{$credentials.apiToken}}' } },
23
+ };
24
+ test = { request: { baseURL: 'https://api.apify.com/v2', url: '/users/me' } };
26
25
  }
27
26
  exports.ApifyApi = ApifyApi;
28
- //# sourceMappingURL=ApifyApi.credentials.js.map
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="14" fill="#4f46e5"/><path d="M16 48 28 16h8l12 32H38l-2-7H26l-2 7zm12-15h6l-3-10z" fill="white"/></svg>
@@ -2,194 +2,320 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Newegg = void 0;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
- const ACTOR_ID = 'apivault_labs~newegg-product-scraper';
5
+ const actorTransport_1 = require("../helpers/actorTransport");
6
+ const ACTOR_ID = 't0oWsDLob7QOPxcCh';
6
7
  class Newegg {
7
- constructor() {
8
- this.description = {
9
- displayName: 'Newegg Product Scraper',
10
- name: 'newegg',
11
- icon: 'file:newegg.svg',
12
- group: ['transform'],
13
- version: 1,
14
- description: 'Scrape Newegg product pages in real-time — title, price, rating, reviews, brand, availability. Ideal for PC parts, electronics, tech arbitrage.',
15
- defaults: { name: 'Newegg Product Scraper' },
16
- inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
17
- outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
18
- usableAsTool: true,
19
- credentials: [{ name: 'apifyApi', required: true }],
20
- properties: [
8
+ description = {
9
+ "displayName": "Newegg Product Scraper",
10
+ "name": "newegg",
11
+ "icon": {
12
+ "light": "file:newegg.svg",
13
+ "dark": "file:newegg.svg"
14
+ },
15
+ "subtitle": "={{$parameter[\"apivaultMode\"]}}",
16
+ "group": [
17
+ "transform"
18
+ ],
19
+ "version": [
20
+ 1,
21
+ 2
22
+ ],
23
+ "description": "Run Newegg Product Scraper through the hosted Apify Actor and read its results",
24
+ "defaults": {
25
+ "name": "Newegg Product Scraper"
26
+ },
27
+ "inputs": [
28
+ n8n_workflow_1.NodeConnectionTypes.Main
29
+ ],
30
+ "outputs": [
31
+ n8n_workflow_1.NodeConnectionTypes.Main
32
+ ],
33
+ "usableAsTool": true,
34
+ "credentials": [
35
+ {
36
+ "name": "apifyApi",
37
+ "required": true
38
+ }
39
+ ],
40
+ "defaultVersion": 2,
41
+ properties: [...actorTransport_1.executionProperties, ...[
21
42
  {
22
43
  "displayName": "Newegg Product URLs or Item IDs",
23
44
  "name": "productUrls",
24
- "description": "Full Newegg product URLs (https://www.newegg.com/p/N82E16820232869) or bare Item IDs (N82E16820232869). Both formats are accepted. (comma or new-line separated)",
45
+ "description": "Actor input: Newegg Product URLs or Item IDs",
25
46
  "type": "string",
26
47
  "default": "",
27
- "required": true
48
+ "required": true,
49
+ "displayOptions": {
50
+ "show": {
51
+ "apivaultMode": [
52
+ "run"
53
+ ]
54
+ }
55
+ }
28
56
  },
29
57
  {
30
58
  "displayName": "Product Title",
31
59
  "name": "extractTitle",
32
- "description": "Extract product name / title",
60
+ "description": "Actor input: Product Title",
33
61
  "type": "boolean",
34
- "default": true
62
+ "default": true,
63
+ "displayOptions": {
64
+ "show": {
65
+ "apivaultMode": [
66
+ "run"
67
+ ]
68
+ }
69
+ }
35
70
  },
36
71
  {
37
72
  "displayName": "Price",
38
73
  "name": "extractPrice",
39
- "description": "Extract current price",
74
+ "description": "Actor input: Price",
40
75
  "type": "boolean",
41
- "default": true
76
+ "default": true,
77
+ "displayOptions": {
78
+ "show": {
79
+ "apivaultMode": [
80
+ "run"
81
+ ]
82
+ }
83
+ }
42
84
  },
43
85
  {
44
86
  "displayName": "Original Price",
45
87
  "name": "extractOriginalPrice",
46
- "description": "Extract original price before discount",
88
+ "description": "Actor input: Original Price",
47
89
  "type": "boolean",
48
- "default": true
90
+ "default": true,
91
+ "displayOptions": {
92
+ "show": {
93
+ "apivaultMode": [
94
+ "run"
95
+ ]
96
+ }
97
+ }
49
98
  },
50
99
  {
51
100
  "displayName": "Rating",
52
101
  "name": "extractRating",
53
- "description": "Extract 'eggs' rating (Newegg's star rating 1-5)",
102
+ "description": "Actor input: Rating",
54
103
  "type": "boolean",
55
- "default": true
104
+ "default": true,
105
+ "displayOptions": {
106
+ "show": {
107
+ "apivaultMode": [
108
+ "run"
109
+ ]
110
+ }
111
+ }
56
112
  },
57
113
  {
58
114
  "displayName": "Reviews Count",
59
115
  "name": "extractReviewsCount",
60
- "description": "Extract number of reviews",
116
+ "description": "Actor input: Reviews Count",
61
117
  "type": "boolean",
62
- "default": true
118
+ "default": true,
119
+ "displayOptions": {
120
+ "show": {
121
+ "apivaultMode": [
122
+ "run"
123
+ ]
124
+ }
125
+ }
63
126
  },
64
127
  {
65
128
  "displayName": "Brand",
66
129
  "name": "extractBrand",
67
- "description": "Extract brand name",
130
+ "description": "Actor input: Brand",
68
131
  "type": "boolean",
69
- "default": true
132
+ "default": true,
133
+ "displayOptions": {
134
+ "show": {
135
+ "apivaultMode": [
136
+ "run"
137
+ ]
138
+ }
139
+ }
70
140
  },
71
141
  {
72
142
  "displayName": "Model Number",
73
143
  "name": "extractModel",
74
- "description": "Extract manufacturer model number (Newegg-specific)",
144
+ "description": "Actor input: Model Number",
75
145
  "type": "boolean",
76
- "default": true
146
+ "default": true,
147
+ "displayOptions": {
148
+ "show": {
149
+ "apivaultMode": [
150
+ "run"
151
+ ]
152
+ }
153
+ }
77
154
  },
78
155
  {
79
156
  "displayName": "Category",
80
157
  "name": "extractCategory",
81
- "description": "Extract category / breadcrumb",
158
+ "description": "Actor input: Category",
82
159
  "type": "boolean",
83
- "default": true
160
+ "default": true,
161
+ "displayOptions": {
162
+ "show": {
163
+ "apivaultMode": [
164
+ "run"
165
+ ]
166
+ }
167
+ }
84
168
  },
85
169
  {
86
170
  "displayName": "Availability",
87
171
  "name": "extractAvailability",
88
- "description": "In Stock / Out of Stock / Sold Out",
172
+ "description": "Actor input: Availability",
89
173
  "type": "boolean",
90
- "default": true
174
+ "default": true,
175
+ "displayOptions": {
176
+ "show": {
177
+ "apivaultMode": [
178
+ "run"
179
+ ]
180
+ }
181
+ }
91
182
  },
92
183
  {
93
184
  "displayName": "Seller",
94
185
  "name": "extractSeller",
95
- "description": "Seller / merchant name (Newegg or third-party marketplace)",
186
+ "description": "Actor input: Seller",
96
187
  "type": "boolean",
97
- "default": true
188
+ "default": true,
189
+ "displayOptions": {
190
+ "show": {
191
+ "apivaultMode": [
192
+ "run"
193
+ ]
194
+ }
195
+ }
98
196
  },
99
197
  {
100
198
  "displayName": "Shipping Info",
101
199
  "name": "extractShipping",
102
- "description": "Shipping cost / free-shipping flag",
200
+ "description": "Actor input: Shipping Info",
103
201
  "type": "boolean",
104
- "default": true
202
+ "default": true,
203
+ "displayOptions": {
204
+ "show": {
205
+ "apivaultMode": [
206
+ "run"
207
+ ]
208
+ }
209
+ }
105
210
  },
106
211
  {
107
212
  "displayName": "Description",
108
213
  "name": "extractDescription",
109
- "description": "Extract product description",
214
+ "description": "Actor input: Description",
110
215
  "type": "boolean",
111
- "default": true
216
+ "default": true,
217
+ "displayOptions": {
218
+ "show": {
219
+ "apivaultMode": [
220
+ "run"
221
+ ]
222
+ }
223
+ }
112
224
  },
113
225
  {
114
226
  "displayName": "Main Image",
115
227
  "name": "extractImage",
116
- "description": "Extract main product image URL",
228
+ "description": "Actor input: Main Image",
117
229
  "type": "boolean",
118
- "default": true
230
+ "default": true,
231
+ "displayOptions": {
232
+ "show": {
233
+ "apivaultMode": [
234
+ "run"
235
+ ]
236
+ }
237
+ }
119
238
  },
120
239
  {
121
240
  "displayName": "Max Concurrency",
122
241
  "name": "maxConcurrency",
123
- "description": "Parallel product scrapes (recommended: 2-3)",
242
+ "description": "Actor input: Max Concurrency",
124
243
  "type": "number",
125
244
  "default": 3,
126
245
  "typeOptions": {
127
246
  "minValue": 1,
128
247
  "maxValue": 8
248
+ },
249
+ "displayOptions": {
250
+ "show": {
251
+ "apivaultMode": [
252
+ "run"
253
+ ]
254
+ }
129
255
  }
130
256
  },
131
257
  {
132
258
  "displayName": "Timeout per product (seconds)",
133
259
  "name": "timeout",
134
- "description": "Max wait per Newegg product page",
260
+ "description": "Actor input: Timeout per product (seconds)",
135
261
  "type": "number",
136
262
  "default": 180,
137
263
  "typeOptions": {
138
264
  "minValue": 60,
139
265
  "maxValue": 300
266
+ },
267
+ "displayOptions": {
268
+ "show": {
269
+ "apivaultMode": [
270
+ "run"
271
+ ]
272
+ }
140
273
  }
141
274
  }
142
- ],
143
- };
144
- }
275
+ ]]
276
+ };
145
277
  async execute() {
146
- const items = this.getInputData();
147
- const returnData = [];
148
- for (let i = 0; i < items.length; i++) {
278
+ const output = [];
279
+ for (let i = 0; i < this.getInputData().length; i++) {
149
280
  try {
150
- const body = {};
151
- {
152
- const _v = this.getNodeParameter("productUrls", i, '');
153
- const _a = _v.split(/[,\n]/).map(s => s.trim()).filter(s => s.length > 0);
154
- if (_a.length)
155
- body["productUrls"] = _a;
156
- }
157
- body["extractTitle"] = this.getNodeParameter("extractTitle", i);
158
- body["extractPrice"] = this.getNodeParameter("extractPrice", i);
159
- body["extractOriginalPrice"] = this.getNodeParameter("extractOriginalPrice", i);
160
- body["extractRating"] = this.getNodeParameter("extractRating", i);
161
- body["extractReviewsCount"] = this.getNodeParameter("extractReviewsCount", i);
162
- body["extractBrand"] = this.getNodeParameter("extractBrand", i);
163
- body["extractModel"] = this.getNodeParameter("extractModel", i);
164
- body["extractCategory"] = this.getNodeParameter("extractCategory", i);
165
- body["extractAvailability"] = this.getNodeParameter("extractAvailability", i);
166
- body["extractSeller"] = this.getNodeParameter("extractSeller", i);
167
- body["extractShipping"] = this.getNodeParameter("extractShipping", i);
168
- body["extractDescription"] = this.getNodeParameter("extractDescription", i);
169
- body["extractImage"] = this.getNodeParameter("extractImage", i);
170
- body["maxConcurrency"] = this.getNodeParameter("maxConcurrency", i);
171
- body["timeout"] = this.getNodeParameter("timeout", i);
172
- const options = {
173
- method: 'POST',
174
- url: `https://api.apify.com/v2/acts/${ACTOR_ID}/run-sync-get-dataset-items`,
175
- body,
176
- json: true,
177
- };
178
- const response = await this.helpers.requestWithAuthentication.call(this, 'apifyApi', options);
179
- const results = Array.isArray(response) ? response : [response];
281
+ const body = this.getNodeParameter('apivaultMode', i, 'run') === 'read' ? {} : (() => {
282
+ const body = {};
283
+ {
284
+ const _v = this.getNodeParameter("productUrls", i, '');
285
+ const _a = _v.split(/[,\n]/).map(s => s.trim()).filter(s => s.length > 0);
286
+ if (_a.length)
287
+ body["productUrls"] = _a;
288
+ }
289
+ body["extractTitle"] = this.getNodeParameter("extractTitle", i);
290
+ body["extractPrice"] = this.getNodeParameter("extractPrice", i);
291
+ body["extractOriginalPrice"] = this.getNodeParameter("extractOriginalPrice", i);
292
+ body["extractRating"] = this.getNodeParameter("extractRating", i);
293
+ body["extractReviewsCount"] = this.getNodeParameter("extractReviewsCount", i);
294
+ body["extractBrand"] = this.getNodeParameter("extractBrand", i);
295
+ body["extractModel"] = this.getNodeParameter("extractModel", i);
296
+ body["extractCategory"] = this.getNodeParameter("extractCategory", i);
297
+ body["extractAvailability"] = this.getNodeParameter("extractAvailability", i);
298
+ body["extractSeller"] = this.getNodeParameter("extractSeller", i);
299
+ body["extractShipping"] = this.getNodeParameter("extractShipping", i);
300
+ body["extractDescription"] = this.getNodeParameter("extractDescription", i);
301
+ body["extractImage"] = this.getNodeParameter("extractImage", i);
302
+ body["maxConcurrency"] = this.getNodeParameter("maxConcurrency", i);
303
+ body["timeout"] = this.getNodeParameter("timeout", i);
304
+ return body;
305
+ })();
306
+ const results = await (0, actorTransport_1.runActor)(this, i, ACTOR_ID, body);
180
307
  for (const result of results)
181
- returnData.push({ json: result, pairedItem: { item: i } });
308
+ output.push({ json: result, pairedItem: { item: i } });
182
309
  }
183
310
  catch (error) {
184
- if (this.continueOnFail()) {
185
- returnData.push({ json: { error: error.message }, pairedItem: { item: i } });
186
- continue;
187
- }
188
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
311
+ const message = error instanceof actorTransport_1.SafeActorError ? error.message : 'Could not finish the Actor request. Check inputs and credentials; use Read Existing Run if a run was already started';
312
+ if (this.continueOnFail())
313
+ output.push({ json: { error: message }, pairedItem: { item: i } });
314
+ else
315
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), message, { itemIndex: i });
189
316
  }
190
317
  }
191
- return [returnData];
318
+ return [output];
192
319
  }
193
320
  }
194
321
  exports.Newegg = Newegg;
195
- //# sourceMappingURL=Newegg.node.js.map
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64"><rect width="64" height="64" rx="12" fill="#4f46e5"/><text x="32" y="40" font-family="Arial" font-size="28" font-weight="700" fill="#fff" text-anchor="middle">N</text></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64"><rect width="64" height="64" rx="12" fill="#4f46e5"/><text x="32" y="40" font-family="Arial" font-size="28" font-weight="700" fill="#fff" text-anchor="middle">N</text></svg>
@@ -0,0 +1,9 @@
1
+ import type { IExecuteFunctions, INodeProperties, IDataObject } from 'n8n-workflow';
2
+ import { NodeOperationError } from 'n8n-workflow';
3
+ export declare class SafeActorError extends NodeOperationError {
4
+ readonly runId: string;
5
+ constructor(context: IExecuteFunctions, runId: string, item: number);
6
+ }
7
+ export declare const executionProperties: INodeProperties[];
8
+ export declare function runActor(context: IExecuteFunctions, item: number, actorId: string, body: Record<string, unknown>): Promise<IDataObject[]>;
9
+ export declare function legacyRequest(context: IExecuteFunctions, item: number, raw: unknown): Promise<any>;
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executionProperties = exports.SafeActorError = void 0;
4
+ exports.runActor = runActor;
5
+ exports.legacyRequest = legacyRequest;
6
+ const n8n_workflow_1 = require("n8n-workflow");
7
+ const API = 'https://api.apify.com/v2';
8
+ const id = (value) => {
9
+ if (typeof value !== 'string' || !/^[A-Za-z0-9_-]{1,100}$/.test(value))
10
+ throw new Error('Invalid Apify identifier');
11
+ return value;
12
+ };
13
+ class SafeActorError extends n8n_workflow_1.NodeOperationError {
14
+ runId;
15
+ constructor(context, runId, item) {
16
+ super(context.getNode(), runId ? `Could not finish reading run ${runId}; select Read Existing Run to resume` : 'Could not start or read the Actor. Check inputs and credentials before retrying', { itemIndex: item });
17
+ this.runId = runId;
18
+ }
19
+ }
20
+ exports.SafeActorError = SafeActorError;
21
+ exports.executionProperties = [
22
+ { displayName: 'Run Mode', name: 'apivaultMode', type: 'options', noDataExpression: true,
23
+ options: [{ name: 'Run Actor', value: 'run', action: 'Run the actor' }, { name: 'Read Existing Run', value: 'read', action: 'Read an existing run' }], default: 'run' },
24
+ { displayName: 'Execution Options', name: 'apivaultExecution', type: 'collection', placeholder: 'Add Option', default: {}, options: [
25
+ { displayName: 'Run ID', name: 'runId', type: 'string', default: '', description: 'Existing Apify run to resume without starting a paid duplicate' },
26
+ { displayName: 'Maximum Event Charge (USD)', name: 'maxTotalChargeUsd', type: 'number', default: 0.05,
27
+ typeOptions: { minValue: 0.001, maxValue: 1000, numberPrecision: 3 }, description: 'Event charge cap. Platform usage may be billed separately.' },
28
+ { displayName: 'Maximum Rows to Read', name: 'maxRows', type: 'number', default: 1000,
29
+ typeOptions: { minValue: 1, maxValue: 100000, numberPrecision: 0 }, description: 'Download cap only. Actor input limits control paid collection.' },
30
+ { displayName: 'Output', name: 'output', type: 'options', default: 'rows',
31
+ options: [{ name: 'Dataset Rows', value: 'rows' }, { name: 'Run, Rows and Diagnostics', value: 'full' }], description: 'Include SUMMARY and ERRORS to inspect partial or empty results' },
32
+ ] },
33
+ ];
34
+ async function runActor(context, item, actorId, body) {
35
+ let runId = '';
36
+ try {
37
+ const mode = context.getNodeParameter('apivaultMode', item, 'run');
38
+ const options = context.getNodeParameter('apivaultExecution', item, {});
39
+ const legacy = context.getNode().typeVersion < 2;
40
+ const maxRows = options.maxRows ?? (legacy ? 100000 : 1000);
41
+ if (!Number.isInteger(maxRows) || maxRows < 1 || maxRows > 100000)
42
+ throw new Error('Invalid row limit');
43
+ const request = async (requestOptions) => context.helpers.httpRequestWithAuthentication.call(context, 'apifyApi', requestOptions);
44
+ if (mode === 'run') {
45
+ const cap = options.maxTotalChargeUsd ?? (legacy ? undefined : 0.05);
46
+ if (cap !== undefined && (!Number.isFinite(cap) || cap <= 0 || cap > 1000))
47
+ throw new Error('Invalid event charge cap');
48
+ // Legacy workflows retain their existing charge behavior unless a cap is selected.
49
+ const qs = { build: 'latest' };
50
+ if (cap !== undefined)
51
+ qs.maxTotalChargeUsd = cap;
52
+ // Never retry POST: a duplicate could create a second paid Actor run.
53
+ const started = await request({ method: 'POST', url: `${API}/acts/${id(actorId)}/runs`, body: body, qs, json: true });
54
+ runId = id(started?.data?.id);
55
+ }
56
+ else if (mode === 'read')
57
+ runId = id(options.runId);
58
+ else
59
+ throw new Error('Unsupported run mode');
60
+ const deadline = Date.now() + 10 * 60 * 1000;
61
+ let run;
62
+ while (true) {
63
+ if (Date.now() >= deadline)
64
+ throw new Error('Waiting timed out');
65
+ const response = await request({ method: 'GET', url: `${API}/actor-runs/${runId}`, qs: { waitForFinish: 20 }, json: true });
66
+ run = response.data;
67
+ if (run.status === 'SUCCEEDED')
68
+ break;
69
+ if (['FAILED', 'TIMED-OUT', 'ABORTED'].includes(run.status))
70
+ throw new Error('Run did not succeed');
71
+ }
72
+ const datasetId = id(run.defaultDatasetId);
73
+ const dataset = await request({ method: 'GET', url: `${API}/datasets/${datasetId}`, json: true });
74
+ const rows = [];
75
+ while (rows.length < maxRows) {
76
+ const limit = Math.min(1000, maxRows - rows.length);
77
+ const page = await request({ method: 'GET', url: `${API}/datasets/${datasetId}/items`, qs: { clean: true, offset: rows.length, limit }, json: true });
78
+ if (!Array.isArray(page) || page.length > limit)
79
+ throw new Error('Invalid Dataset response');
80
+ rows.push(...page);
81
+ if (page.length < limit)
82
+ break;
83
+ }
84
+ const truncated = (dataset.data?.itemCount ?? rows.length) > rows.length;
85
+ if (options.output === 'full') {
86
+ const storeId = id(run.defaultKeyValueStoreId);
87
+ const records = {};
88
+ for (const key of ['SUMMARY', 'ERRORS']) {
89
+ try {
90
+ records[key] = await request({ method: 'GET', url: `${API}/key-value-stores/${storeId}/records/${key}`, json: true });
91
+ }
92
+ catch (error) {
93
+ const e = error;
94
+ if (e.statusCode === 404 || e.response?.status === 404)
95
+ records[key] = null;
96
+ else
97
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Diagnostics unavailable');
98
+ }
99
+ }
100
+ return [{ runId, datasetId, status: run.status, rows, summary: records.SUMMARY ?? null, errors: records.ERRORS ?? null, truncated }];
101
+ }
102
+ return rows.map(row => ({ ...row, _apifyRunId: runId, _apifyTruncated: truncated }));
103
+ }
104
+ catch {
105
+ const safeError = new SafeActorError(context, runId, item);
106
+ throw safeError;
107
+ }
108
+ }
109
+ // Keep specialized legacy output modes (including asynchronous start and MCP_RESPONSE).
110
+ async function legacyRequest(context, item, raw) {
111
+ const options = raw;
112
+ const controls = context.getNodeParameter('apivaultExecution', item, {});
113
+ const request = async (value) => context.helpers.httpRequestWithAuthentication.call(context, 'apifyApi', value);
114
+ if (options.method === 'POST' && options.url.endsWith('/runs')) {
115
+ const qs = { ...(options.qs ?? {}) };
116
+ const wait = qs.waitForFinish;
117
+ delete qs.waitForFinish;
118
+ const cap = controls.maxTotalChargeUsd ?? (context.getNode().typeVersion < 2 ? undefined : 0.05);
119
+ if (cap !== undefined) {
120
+ if (!Number.isFinite(cap) || cap <= 0 || cap > 1000)
121
+ throw new Error('Invalid event charge cap');
122
+ qs.maxTotalChargeUsd = cap;
123
+ }
124
+ const started = await request({ ...options, qs });
125
+ if (!wait)
126
+ return started;
127
+ const runId = id(started?.data?.id);
128
+ const deadline = Date.now() + 10 * 60 * 1000;
129
+ while (Date.now() < deadline) {
130
+ const result = await request({ method: 'GET', url: `${API}/actor-runs/${runId}`, qs: { waitForFinish: 20 }, json: true });
131
+ if (result.data.status === 'SUCCEEDED')
132
+ return result;
133
+ if (['FAILED', 'TIMED-OUT', 'ABORTED'].includes(result.data.status))
134
+ throw new Error('Run did not succeed');
135
+ }
136
+ throw new Error('Waiting timed out');
137
+ }
138
+ if (options.method === 'GET' && /\/datasets\/[A-Za-z0-9_-]+\/items$/.test(options.url)) {
139
+ const maxRows = controls.maxRows ?? (context.getNode().typeVersion < 2 ? 100000 : 1000);
140
+ if (!Number.isInteger(maxRows) || maxRows < 1 || maxRows > 100000)
141
+ throw new Error('Invalid row limit');
142
+ const rows = [];
143
+ while (rows.length < maxRows) {
144
+ const limit = Math.min(1000, maxRows - rows.length);
145
+ const page = await request({ ...options, qs: { ...(options.qs ?? {}), offset: rows.length, limit } });
146
+ if (!Array.isArray(page) || page.length > limit)
147
+ throw new Error('Invalid Dataset response');
148
+ rows.push(...page);
149
+ if (page.length < limit)
150
+ break;
151
+ }
152
+ return rows;
153
+ }
154
+ return request(options);
155
+ }
package/index.js CHANGED
@@ -1 +1 @@
1
- module.exports = {};
1
+ module.exports = {};
package/package.json CHANGED
@@ -1,48 +1,53 @@
1
- {
2
- "name": "n8n-nodes-apivault-newegg",
3
- "version": "0.1.0",
4
- "description": "n8n community node for Newegg Product Scraper — backed by the Apify Actor apivault_labs/newegg-product-scraper. No login. Pay-as-you-go via Apify.",
5
- "license": "MIT",
6
- "homepage": "https://apify.com/apivault_labs/newegg-product-scraper",
7
- "keywords": [
8
- "n8n-community-node-package",
9
- "n8n",
10
- "newegg",
11
- "apify",
12
- "no-code",
13
- "automation"
14
- ],
15
- "author": {
16
- "name": "apivault_labs"
17
- },
18
- "repository": {
19
- "type": "git",
20
- "url": "https://github.com/apivault-labs/n8n-nodes-apivault-newegg.git"
21
- },
22
- "main": "index.js",
23
- "scripts": {
24
- "build": "tsc && copyfiles \"nodes/**/*.svg\" dist",
25
- "dev": "tsc --watch"
26
- },
27
- "files": [
28
- "dist"
29
- ],
30
- "n8n": {
31
- "n8nNodesApiVersion": 1,
32
- "credentials": [
33
- "dist/credentials/ApifyApi.credentials.js"
34
- ],
35
- "nodes": [
36
- "dist/nodes/Newegg/Newegg.node.js"
37
- ]
38
- },
39
- "devDependencies": {
40
- "@types/node": "^20.10.0",
41
- "copyfiles": "^2.4.1",
42
- "n8n-workflow": "*",
43
- "typescript": "^5.4.0"
44
- },
45
- "peerDependencies": {
46
- "n8n-workflow": "*"
47
- }
48
- }
1
+ {
2
+ "name": "n8n-nodes-apivault-newegg",
3
+ "version": "0.2.0",
4
+ "description": "Run Newegg Product Scraper through the hosted Apify Actor and read its results",
5
+ "license": "MIT",
6
+ "homepage": "https://apify.com/apivault_labs/newegg-product-scraper",
7
+ "keywords": [
8
+ "n8n-community-node-package",
9
+ "n8n",
10
+ "newegg",
11
+ "apify",
12
+ "no-code",
13
+ "automation"
14
+ ],
15
+ "author": {
16
+ "name": "ApiVault Labs",
17
+ "email": "68965192+apivault-labs@users.noreply.github.com"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/apivault-labs/apivault-labs.git",
22
+ "directory": "community-nodes/n8n-nodes-apivault-newegg"
23
+ },
24
+ "main": "index.js",
25
+ "scripts": {
26
+ "build": "tsc && node scripts/copy-icons.cjs",
27
+ "lint": "n8n-node lint",
28
+ "test": "node test/contract.cjs",
29
+ "prepublishOnly": "npm run build"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "examples"
34
+ ],
35
+ "n8n": {
36
+ "n8nNodesApiVersion": 1,
37
+ "credentials": [
38
+ "dist/credentials/ApifyApi.credentials.js"
39
+ ],
40
+ "nodes": [
41
+ "dist/nodes/Newegg/Newegg.node.js"
42
+ ]
43
+ },
44
+ "devDependencies": {
45
+ "@n8n/node-cli": "0.52.2",
46
+ "n8n-workflow": "2.16.0",
47
+ "typescript": "npm:@typescript/typescript6@6.0.2",
48
+ "@types/node": "^22.0.0"
49
+ },
50
+ "peerDependencies": {
51
+ "n8n-workflow": "*"
52
+ }
53
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"ApifyApi.credentials.js","sourceRoot":"","sources":["../../credentials/ApifyApi.credentials.ts"],"names":[],"mappings":";;;AAOA;IAAA;QACC,SAAI,GAAG,UAAU,CAAC;QAClB,gBAAW,GAAG,WAAW,CAAC;QAC1B,qBAAgB,GAAG,kDAAkD,CAAC;QACtE,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,WAAW;gBACxB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,4EAA4E;aACzF;SACD,CAAC;QACF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,mCAAmC,EAAE,EAAE;SAC/E,CAAC;QACF,SAAI,GAA2B,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,0BAA0B,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC;IACvG,CAAC;CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Newegg.node.js","sourceRoot":"","sources":["../../../nodes/Newegg/Newegg.node.ts"],"names":[],"mappings":"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"}