@fachkraftfreund/n8n-nodes-supabase 1.3.3 → 1.3.5
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.
|
@@ -55,6 +55,18 @@ exports.executeDatabaseOperation = executeDatabaseOperation;
|
|
|
55
55
|
const BULK_BATCH_SIZE = 500;
|
|
56
56
|
const MAX_RETRIES = 3;
|
|
57
57
|
const RETRY_BASE_DELAY_MS = 1000;
|
|
58
|
+
function deduplicateByConflictKeys(rows, conflictColumns) {
|
|
59
|
+
const keys = conflictColumns.split(',').map((k) => k.trim()).filter(Boolean);
|
|
60
|
+
if (keys.length === 0)
|
|
61
|
+
return rows;
|
|
62
|
+
const seen = new Map();
|
|
63
|
+
for (let i = 0; i < rows.length; i++) {
|
|
64
|
+
const row = rows[i];
|
|
65
|
+
const compositeKey = keys.map((k) => { var _a; return String((_a = row[k]) !== null && _a !== void 0 ? _a : ''); }).join('\0');
|
|
66
|
+
seen.set(compositeKey, i);
|
|
67
|
+
}
|
|
68
|
+
return Array.from(seen.values()).sort((a, b) => a - b).map((i) => rows[i]);
|
|
69
|
+
}
|
|
58
70
|
function isRetryableError(msg) {
|
|
59
71
|
const lower = msg.toLowerCase();
|
|
60
72
|
return (lower.includes('lock timeout') ||
|
|
@@ -192,13 +204,20 @@ async function handleBulkUpsert(supabase, itemCount) {
|
|
|
192
204
|
const table = this.getNodeParameter('table', 0);
|
|
193
205
|
const onConflict = this.getNodeParameter('onConflict', 0, '');
|
|
194
206
|
(0, supabaseClient_1.validateTableName)(table);
|
|
195
|
-
|
|
207
|
+
let rows = collectRowData(this, itemCount);
|
|
196
208
|
const options = {};
|
|
197
|
-
if (onConflict)
|
|
209
|
+
if (onConflict) {
|
|
198
210
|
options.onConflict = onConflict;
|
|
211
|
+
const before = rows.length;
|
|
212
|
+
rows = deduplicateByConflictKeys(rows, onConflict);
|
|
213
|
+
if (rows.length < before) {
|
|
214
|
+
console.log(`[Supabase UPSERT ${table}] deduplicated input: ${before} → ${rows.length} rows by conflict key "${onConflict}"`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
199
217
|
const returnData = [];
|
|
200
218
|
for (let offset = 0; offset < rows.length; offset += BULK_BATCH_SIZE) {
|
|
201
219
|
const batch = rows.slice(offset, offset + BULK_BATCH_SIZE);
|
|
220
|
+
const batchLabel = `UPSERT ${table} batch ${Math.floor(offset / BULK_BATCH_SIZE) + 1}`;
|
|
202
221
|
const data = await withRetry(async () => {
|
|
203
222
|
const { data, error } = await supabase
|
|
204
223
|
.from(table)
|
|
@@ -207,7 +226,7 @@ async function handleBulkUpsert(supabase, itemCount) {
|
|
|
207
226
|
if (error)
|
|
208
227
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
209
228
|
return data;
|
|
210
|
-
},
|
|
229
|
+
}, batchLabel);
|
|
211
230
|
if (Array.isArray(data)) {
|
|
212
231
|
for (const row of data)
|
|
213
232
|
returnData.push({ json: row });
|
|
@@ -224,16 +243,22 @@ async function handleBulkUpdate(supabase, itemCount) {
|
|
|
224
243
|
if (!matchColumn) {
|
|
225
244
|
throw new Error('Match Column is required for update operations');
|
|
226
245
|
}
|
|
227
|
-
|
|
246
|
+
let rows = collectRowData(this, itemCount);
|
|
228
247
|
for (let i = 0; i < rows.length; i++) {
|
|
229
248
|
const row = rows[i];
|
|
230
249
|
if (!row || row[matchColumn] === undefined) {
|
|
231
250
|
throw new Error(`Item ${i} is missing the match column "${matchColumn}"`);
|
|
232
251
|
}
|
|
233
252
|
}
|
|
253
|
+
const before = rows.length;
|
|
254
|
+
rows = deduplicateByConflictKeys(rows, matchColumn);
|
|
255
|
+
if (rows.length < before) {
|
|
256
|
+
console.log(`[Supabase UPDATE ${table}] deduplicated input: ${before} → ${rows.length} rows by match column "${matchColumn}"`);
|
|
257
|
+
}
|
|
234
258
|
const returnData = [];
|
|
235
259
|
for (let offset = 0; offset < rows.length; offset += BULK_BATCH_SIZE) {
|
|
236
260
|
const batch = rows.slice(offset, offset + BULK_BATCH_SIZE);
|
|
261
|
+
const batchLabel = `UPDATE ${table} batch ${Math.floor(offset / BULK_BATCH_SIZE) + 1}`;
|
|
237
262
|
const data = await withRetry(async () => {
|
|
238
263
|
const { data, error } = await supabase
|
|
239
264
|
.from(table)
|
|
@@ -242,7 +267,7 @@ async function handleBulkUpdate(supabase, itemCount) {
|
|
|
242
267
|
if (error)
|
|
243
268
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
244
269
|
return data;
|
|
245
|
-
},
|
|
270
|
+
}, batchLabel);
|
|
246
271
|
if (Array.isArray(data)) {
|
|
247
272
|
for (const row of data)
|
|
248
273
|
returnData.push({ json: row });
|
package/package.json
CHANGED