@fachkraftfreund/n8n-nodes-supabase 1.3.6 → 1.3.8
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.
|
@@ -203,31 +203,41 @@ async function handleBulkCreate(supabase, itemCount) {
|
|
|
203
203
|
async function handleBulkUpsert(supabase, itemCount) {
|
|
204
204
|
const table = this.getNodeParameter('table', 0);
|
|
205
205
|
const onConflict = this.getNodeParameter('onConflict', 0, '');
|
|
206
|
-
(0, supabaseClient_1.validateTableName)(table);
|
|
207
206
|
const deduplicate = this.getNodeParameter('deduplicateByConflict', 0, false);
|
|
207
|
+
(0, supabaseClient_1.validateTableName)(table);
|
|
208
208
|
let rows = collectRowData(this, itemCount);
|
|
209
|
+
console.log(`[Supabase UPSERT ${table}] rows=${rows.length}, onConflict="${onConflict}", deduplicate=${deduplicate}`);
|
|
209
210
|
const options = {};
|
|
210
|
-
if (onConflict)
|
|
211
|
+
if (onConflict)
|
|
211
212
|
options.onConflict = onConflict;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
console.log(`[Supabase UPSERT ${table}] deduplicated input: ${before} → ${rows.length} rows by conflict key "${onConflict}"`);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
213
|
+
if (deduplicate && onConflict) {
|
|
214
|
+
const before = rows.length;
|
|
215
|
+
rows = deduplicateByConflictKeys(rows, onConflict);
|
|
216
|
+
console.log(`[Supabase UPSERT ${table}] dedup by "${onConflict}": ${before} → ${rows.length} rows`);
|
|
219
217
|
}
|
|
220
218
|
const returnData = [];
|
|
219
|
+
const duplicateError = 'cannot affect row a second time';
|
|
221
220
|
for (let offset = 0; offset < rows.length; offset += BULK_BATCH_SIZE) {
|
|
222
|
-
|
|
221
|
+
let batch = rows.slice(offset, offset + BULK_BATCH_SIZE);
|
|
223
222
|
const batchLabel = `UPSERT ${table} batch ${Math.floor(offset / BULK_BATCH_SIZE) + 1}`;
|
|
224
223
|
const data = await withRetry(async () => {
|
|
225
224
|
const { data, error } = await supabase
|
|
226
225
|
.from(table)
|
|
227
226
|
.upsert(batch, options)
|
|
228
227
|
.select();
|
|
229
|
-
if (error)
|
|
230
|
-
|
|
228
|
+
if (error) {
|
|
229
|
+
const msg = (0, supabaseClient_1.formatSupabaseError)(error);
|
|
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
|
+
}
|
|
231
241
|
return data;
|
|
232
242
|
}, batchLabel);
|
|
233
243
|
if (Array.isArray(data)) {
|
|
@@ -248,6 +258,7 @@ async function handleBulkUpdate(supabase, itemCount) {
|
|
|
248
258
|
}
|
|
249
259
|
const deduplicate = this.getNodeParameter('deduplicateByConflict', 0, false);
|
|
250
260
|
let rows = collectRowData(this, itemCount);
|
|
261
|
+
console.log(`[Supabase UPDATE ${table}] rows=${rows.length}, matchColumn="${matchColumn}", deduplicate=${deduplicate}`);
|
|
251
262
|
for (let i = 0; i < rows.length; i++) {
|
|
252
263
|
const row = rows[i];
|
|
253
264
|
if (!row || row[matchColumn] === undefined) {
|
|
@@ -257,21 +268,31 @@ async function handleBulkUpdate(supabase, itemCount) {
|
|
|
257
268
|
if (deduplicate) {
|
|
258
269
|
const before = rows.length;
|
|
259
270
|
rows = deduplicateByConflictKeys(rows, matchColumn);
|
|
260
|
-
|
|
261
|
-
console.log(`[Supabase UPDATE ${table}] deduplicated input: ${before} → ${rows.length} rows by match column "${matchColumn}"`);
|
|
262
|
-
}
|
|
271
|
+
console.log(`[Supabase UPDATE ${table}] dedup by "${matchColumn}": ${before} → ${rows.length} rows`);
|
|
263
272
|
}
|
|
264
273
|
const returnData = [];
|
|
274
|
+
const duplicateError = 'cannot affect row a second time';
|
|
265
275
|
for (let offset = 0; offset < rows.length; offset += BULK_BATCH_SIZE) {
|
|
266
|
-
|
|
276
|
+
let batch = rows.slice(offset, offset + BULK_BATCH_SIZE);
|
|
267
277
|
const batchLabel = `UPDATE ${table} batch ${Math.floor(offset / BULK_BATCH_SIZE) + 1}`;
|
|
268
278
|
const data = await withRetry(async () => {
|
|
269
279
|
const { data, error } = await supabase
|
|
270
280
|
.from(table)
|
|
271
281
|
.upsert(batch, { onConflict: matchColumn })
|
|
272
282
|
.select();
|
|
273
|
-
if (error)
|
|
274
|
-
|
|
283
|
+
if (error) {
|
|
284
|
+
const msg = (0, supabaseClient_1.formatSupabaseError)(error);
|
|
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
|
+
}
|
|
275
296
|
return data;
|
|
276
297
|
}, batchLabel);
|
|
277
298
|
if (Array.isArray(data)) {
|
package/package.json
CHANGED