@fachkraftfreund/n8n-nodes-supabase 1.3.8 → 1.3.10
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.
|
@@ -62,7 +62,16 @@ function deduplicateByConflictKeys(rows, conflictColumns) {
|
|
|
62
62
|
const seen = new Map();
|
|
63
63
|
for (let i = 0; i < rows.length; i++) {
|
|
64
64
|
const row = rows[i];
|
|
65
|
-
const compositeKey = keys.map((k) => {
|
|
65
|
+
const compositeKey = keys.map((k) => {
|
|
66
|
+
const val = row[k];
|
|
67
|
+
if (val === null || val === undefined)
|
|
68
|
+
return '\x00null';
|
|
69
|
+
const str = String(val).trim();
|
|
70
|
+
const num = Number(str);
|
|
71
|
+
if (str !== '' && !isNaN(num))
|
|
72
|
+
return String(num);
|
|
73
|
+
return str.toLowerCase();
|
|
74
|
+
}).join('\0');
|
|
66
75
|
seen.set(compositeKey, i);
|
|
67
76
|
}
|
|
68
77
|
return Array.from(seen.values()).sort((a, b) => a - b).map((i) => rows[i]);
|
|
@@ -206,38 +215,27 @@ async function handleBulkUpsert(supabase, itemCount) {
|
|
|
206
215
|
const deduplicate = this.getNodeParameter('deduplicateByConflict', 0, false);
|
|
207
216
|
(0, supabaseClient_1.validateTableName)(table);
|
|
208
217
|
let rows = collectRowData(this, itemCount);
|
|
209
|
-
console.log(`[Supabase UPSERT ${table}] rows=${rows.length}, onConflict="${onConflict}", deduplicate=${deduplicate}`);
|
|
210
218
|
const options = {};
|
|
211
219
|
if (onConflict)
|
|
212
220
|
options.onConflict = onConflict;
|
|
213
221
|
if (deduplicate && onConflict) {
|
|
214
222
|
const before = rows.length;
|
|
215
223
|
rows = deduplicateByConflictKeys(rows, onConflict);
|
|
216
|
-
|
|
224
|
+
if (rows.length < before) {
|
|
225
|
+
console.log(`[Supabase UPSERT ${table}] dedup by "${onConflict}": ${before} → ${rows.length} rows`);
|
|
226
|
+
}
|
|
217
227
|
}
|
|
218
228
|
const returnData = [];
|
|
219
|
-
const duplicateError = 'cannot affect row a second time';
|
|
220
229
|
for (let offset = 0; offset < rows.length; offset += BULK_BATCH_SIZE) {
|
|
221
|
-
|
|
230
|
+
const batch = rows.slice(offset, offset + BULK_BATCH_SIZE);
|
|
222
231
|
const batchLabel = `UPSERT ${table} batch ${Math.floor(offset / BULK_BATCH_SIZE) + 1}`;
|
|
223
232
|
const data = await withRetry(async () => {
|
|
224
233
|
const { data, error } = await supabase
|
|
225
234
|
.from(table)
|
|
226
235
|
.upsert(batch, options)
|
|
227
236
|
.select();
|
|
228
|
-
if (error)
|
|
229
|
-
|
|
230
|
-
if (msg.toLowerCase().includes(duplicateError) && onConflict) {
|
|
231
|
-
const before = batch.length;
|
|
232
|
-
batch = deduplicateByConflictKeys(batch, onConflict);
|
|
233
|
-
console.log(`[Supabase ${batchLabel}] duplicate-row error caught, dedup fallback: ${before} → ${batch.length} rows`);
|
|
234
|
-
const retry = await supabase.from(table).upsert(batch, options).select();
|
|
235
|
-
if (retry.error)
|
|
236
|
-
throw new Error((0, supabaseClient_1.formatSupabaseError)(retry.error));
|
|
237
|
-
return retry.data;
|
|
238
|
-
}
|
|
239
|
-
throw new Error(msg);
|
|
240
|
-
}
|
|
237
|
+
if (error)
|
|
238
|
+
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
241
239
|
return data;
|
|
242
240
|
}, batchLabel);
|
|
243
241
|
if (Array.isArray(data)) {
|
|
@@ -258,7 +256,6 @@ async function handleBulkUpdate(supabase, itemCount) {
|
|
|
258
256
|
}
|
|
259
257
|
const deduplicate = this.getNodeParameter('deduplicateByConflict', 0, false);
|
|
260
258
|
let rows = collectRowData(this, itemCount);
|
|
261
|
-
console.log(`[Supabase UPDATE ${table}] rows=${rows.length}, matchColumn="${matchColumn}", deduplicate=${deduplicate}`);
|
|
262
259
|
for (let i = 0; i < rows.length; i++) {
|
|
263
260
|
const row = rows[i];
|
|
264
261
|
if (!row || row[matchColumn] === undefined) {
|
|
@@ -271,28 +268,16 @@ async function handleBulkUpdate(supabase, itemCount) {
|
|
|
271
268
|
console.log(`[Supabase UPDATE ${table}] dedup by "${matchColumn}": ${before} → ${rows.length} rows`);
|
|
272
269
|
}
|
|
273
270
|
const returnData = [];
|
|
274
|
-
const duplicateError = 'cannot affect row a second time';
|
|
275
271
|
for (let offset = 0; offset < rows.length; offset += BULK_BATCH_SIZE) {
|
|
276
|
-
|
|
272
|
+
const batch = rows.slice(offset, offset + BULK_BATCH_SIZE);
|
|
277
273
|
const batchLabel = `UPDATE ${table} batch ${Math.floor(offset / BULK_BATCH_SIZE) + 1}`;
|
|
278
274
|
const data = await withRetry(async () => {
|
|
279
275
|
const { data, error } = await supabase
|
|
280
276
|
.from(table)
|
|
281
277
|
.upsert(batch, { onConflict: matchColumn })
|
|
282
278
|
.select();
|
|
283
|
-
if (error)
|
|
284
|
-
|
|
285
|
-
if (msg.toLowerCase().includes(duplicateError)) {
|
|
286
|
-
const before = batch.length;
|
|
287
|
-
batch = deduplicateByConflictKeys(batch, matchColumn);
|
|
288
|
-
console.log(`[Supabase ${batchLabel}] duplicate-row error caught, dedup fallback: ${before} → ${batch.length} rows`);
|
|
289
|
-
const retry = await supabase.from(table).upsert(batch, { onConflict: matchColumn }).select();
|
|
290
|
-
if (retry.error)
|
|
291
|
-
throw new Error((0, supabaseClient_1.formatSupabaseError)(retry.error));
|
|
292
|
-
return retry.data;
|
|
293
|
-
}
|
|
294
|
-
throw new Error(msg);
|
|
295
|
-
}
|
|
279
|
+
if (error)
|
|
280
|
+
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
296
281
|
return data;
|
|
297
282
|
}, batchLabel);
|
|
298
283
|
if (Array.isArray(data)) {
|
package/package.json
CHANGED