n8n-nodes-prestashop8 2.6.0 → 2.7.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/README.md
CHANGED
|
@@ -30,6 +30,7 @@ A comprehensive n8n community node for PrestaShop 8 integration with automatic X
|
|
|
30
30
|
- ✅ **25+ resources supported**: products, customers, orders, stocks...
|
|
31
31
|
- ✅ **Advanced filtering** with 10 search operators
|
|
32
32
|
- ✅ **Raw mode** for debugging and advanced use cases
|
|
33
|
+
- ✅ **Retry on error** to automatically recover from transient failures (timeouts, connection drops)
|
|
33
34
|
|
|
34
35
|
## 🚀 Quick Start
|
|
35
36
|
|
|
@@ -137,6 +138,7 @@ npm install n8n-nodes-prestashop8
|
|
|
137
138
|
- **Sorting**: `[price_ASC]`, `[date_add_DESC]`
|
|
138
139
|
- **Fields**: `full`, `minimal`, or custom
|
|
139
140
|
- **Debug**: URL, headers, timeout
|
|
141
|
+
- **Retry on error**: automatically retry a call that fails on a transient error — network timeout, connection drop, 5xx server error or 429 rate-limit (never on 4xx). Configurable max attempts and fixed delay between attempts; the retry budget is reset for each failing call. Each attempt is logged to the n8n server logs.
|
|
140
142
|
|
|
141
143
|
## 🎯 Usage Examples
|
|
142
144
|
|
|
@@ -169,7 +171,7 @@ Cron → PrestaShop 8 Node → Calculate KPIs → Email Report
|
|
|
169
171
|
### Common Problems
|
|
170
172
|
- **401 Unauthorized** → Check API key and permissions
|
|
171
173
|
- **404 Not Found** → Verify base URL and Webservices enabled
|
|
172
|
-
- **Timeout** → Increase timeout in debug options
|
|
174
|
+
- **Timeout** → Increase timeout in debug options, or enable **Retry on error** to auto-recover from transient timeouts
|
|
173
175
|
|
|
174
176
|
### Get Help
|
|
175
177
|
- 🐞 **[GitHub Issues](https://github.com/PPCM/n8n-nodes-prestashop8/issues)** - Bugs and questions
|
|
@@ -682,7 +682,7 @@ exports.PrestaShop8Description = {
|
|
|
682
682
|
name: 'retryEnabled',
|
|
683
683
|
type: 'boolean',
|
|
684
684
|
default: false,
|
|
685
|
-
description: 'Whether to retry a call that fails on a transient error
|
|
685
|
+
description: 'Whether to retry a call that fails on a transient error. Retries on: network timeout, connection drop (ECONNRESET / ECONNREFUSED / socket hang up), 5xx server errors and 429 rate-limit. Never retries client errors (4xx — invalid API key, 404, invalid XML). The retry budget is reset for each failing call.',
|
|
686
686
|
},
|
|
687
687
|
{
|
|
688
688
|
displayName: 'Max Retries',
|
|
@@ -100,6 +100,12 @@ class PrestaShop8 {
|
|
|
100
100
|
let requestDebugInfo = {};
|
|
101
101
|
const opts = (0, http_1.getOperationOptions)(this, i);
|
|
102
102
|
const { rawMode, timeout, neverError, includeResponseHeaders, showRequestInfo, showRequestUrl } = opts;
|
|
103
|
+
// Trace each retry attempt to the n8n server logs (Option A).
|
|
104
|
+
if (opts.retry.enabled) {
|
|
105
|
+
opts.retry.onRetry = (attempt, error) => {
|
|
106
|
+
this.logger.warn(`PrestaShop8: retry ${attempt}/${opts.retry.maxRetries} on ${resource}/${operation} after ${(0, http_1.describeError)(error)} — waiting ${opts.retry.retryDelay}ms`);
|
|
107
|
+
};
|
|
108
|
+
}
|
|
103
109
|
// Throttle: pause before each PrestaShop call except the first.
|
|
104
110
|
if (i > 0 && opts.delayBetweenCalls > 0) {
|
|
105
111
|
await (0, http_1.sleep)(opts.delayBetweenCalls);
|
|
@@ -270,9 +276,12 @@ class PrestaShop8 {
|
|
|
270
276
|
const filterValue = filter.value !== null && filter.value !== undefined ? String(filter.value).trim() : '';
|
|
271
277
|
const format = http_1.FILTER_OPERATOR_FORMATS[filter.operator];
|
|
272
278
|
if (format) {
|
|
273
|
-
|
|
274
|
-
|
|
279
|
+
// Guard: operators that require a value must not be silently dropped
|
|
280
|
+
// when the value is empty, otherwise PrestaShop returns all records.
|
|
281
|
+
if (format.requiresValue && !filterValue) {
|
|
282
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Filter operator "${filter.operator}" on field "${filter.field}" requires a value. Use the "IS_EMPTY" operator to match empty fields.`);
|
|
275
283
|
}
|
|
284
|
+
filterParams[key] = format.template.replace('{v}', filterValue);
|
|
276
285
|
}
|
|
277
286
|
else if (filterValue) {
|
|
278
287
|
filterParams[key] = `[${filterValue}]`;
|
|
@@ -29,6 +29,8 @@ export interface RetryOptions {
|
|
|
29
29
|
enabled: boolean;
|
|
30
30
|
maxRetries: number;
|
|
31
31
|
retryDelay: number;
|
|
32
|
+
/** Optional hook called before each retry wait, with the upcoming retry number (1-based) and the error. */
|
|
33
|
+
onRetry?: (attempt: number, error: any) => void;
|
|
32
34
|
}
|
|
33
35
|
/**
|
|
34
36
|
* Pause execution for the given number of milliseconds (used to throttle calls).
|
|
@@ -40,6 +42,11 @@ export declare function sleep(ms: number): Promise<void>;
|
|
|
40
42
|
* Never retries on 4xx (invalid key, not found, invalid XML, etc.).
|
|
41
43
|
*/
|
|
42
44
|
export declare function isRetryableError(error: any): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Build a short human-readable reason from an error, for retry logging.
|
|
47
|
+
* Prefers the network code, then the HTTP status, then the message.
|
|
48
|
+
*/
|
|
49
|
+
export declare function describeError(error: any): string;
|
|
43
50
|
/**
|
|
44
51
|
* Run an async HTTP operation with per-call retry on transient errors.
|
|
45
52
|
* Each call gets its own retry budget; on the last attempt the error is rethrown
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FILTER_OPERATOR_FORMATS = void 0;
|
|
4
4
|
exports.sleep = sleep;
|
|
5
5
|
exports.isRetryableError = isRetryableError;
|
|
6
|
+
exports.describeError = describeError;
|
|
6
7
|
exports.withRetry = withRetry;
|
|
7
8
|
exports.getOperationOptions = getOperationOptions;
|
|
8
9
|
exports.buildHttpOptions = buildHttpOptions;
|
|
@@ -69,12 +70,30 @@ function isRetryableError(error) {
|
|
|
69
70
|
}
|
|
70
71
|
return false;
|
|
71
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Build a short human-readable reason from an error, for retry logging.
|
|
75
|
+
* Prefers the network code, then the HTTP status, then the message.
|
|
76
|
+
*/
|
|
77
|
+
function describeError(error) {
|
|
78
|
+
var _a, _b;
|
|
79
|
+
const code = (error === null || error === void 0 ? void 0 : error.code) || ((_a = error === null || error === void 0 ? void 0 : error.cause) === null || _a === void 0 ? void 0 : _a.code);
|
|
80
|
+
if (code) {
|
|
81
|
+
return code;
|
|
82
|
+
}
|
|
83
|
+
const status = (error === null || error === void 0 ? void 0 : error.httpCode) || ((_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.status);
|
|
84
|
+
if (status) {
|
|
85
|
+
return `HTTP ${status}`;
|
|
86
|
+
}
|
|
87
|
+
const message = error === null || error === void 0 ? void 0 : error.message;
|
|
88
|
+
return message ? String(message) : 'unknown error';
|
|
89
|
+
}
|
|
72
90
|
/**
|
|
73
91
|
* Run an async HTTP operation with per-call retry on transient errors.
|
|
74
92
|
* Each call gets its own retry budget; on the last attempt the error is rethrown
|
|
75
93
|
* so existing neverError / continueOnFail handling applies unchanged.
|
|
76
94
|
*/
|
|
77
95
|
async function withRetry(retry, fn) {
|
|
96
|
+
var _a;
|
|
78
97
|
const maxRetries = retry.enabled ? Math.max(0, retry.maxRetries) : 0;
|
|
79
98
|
for (let attempt = 0;; attempt++) {
|
|
80
99
|
try {
|
|
@@ -84,6 +103,8 @@ async function withRetry(retry, fn) {
|
|
|
84
103
|
if (attempt >= maxRetries || !isRetryableError(error)) {
|
|
85
104
|
throw error;
|
|
86
105
|
}
|
|
106
|
+
// attempt is 0-based; report the upcoming retry number (1-based)
|
|
107
|
+
(_a = retry.onRetry) === null || _a === void 0 ? void 0 : _a.call(retry, attempt + 1, error);
|
|
87
108
|
if (retry.retryDelay > 0) {
|
|
88
109
|
await sleep(retry.retryDelay);
|
|
89
110
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-prestashop8",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "Nœud n8n personnalisé pour PrestaShop 8 avec support CRUD complet et conversion XML/JSON automatique",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"brace-expansion": "^1.1.13",
|
|
87
87
|
"uuid": "^14.0.0",
|
|
88
88
|
"axios": "^1.16.0",
|
|
89
|
-
"form-data": "^4.0.
|
|
89
|
+
"form-data": "^4.0.6",
|
|
90
90
|
"follow-redirects": "^1.16.0"
|
|
91
91
|
}
|
|
92
92
|
}
|