@fachkraftfreund/n8n-nodes-supabase 1.2.22 → 1.2.23
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.
|
@@ -527,6 +527,58 @@ class Supabase {
|
|
|
527
527
|
},
|
|
528
528
|
},
|
|
529
529
|
},
|
|
530
|
+
{
|
|
531
|
+
displayName: 'Joins',
|
|
532
|
+
name: 'joins',
|
|
533
|
+
type: 'fixedCollection',
|
|
534
|
+
typeOptions: {
|
|
535
|
+
multipleValues: true,
|
|
536
|
+
},
|
|
537
|
+
default: {},
|
|
538
|
+
placeholder: 'Add Join',
|
|
539
|
+
description: 'Join related tables via foreign keys (PostgREST resource embedding)',
|
|
540
|
+
displayOptions: {
|
|
541
|
+
show: {
|
|
542
|
+
resource: ['database'],
|
|
543
|
+
operation: ['read'],
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
options: [
|
|
547
|
+
{
|
|
548
|
+
displayName: 'Join',
|
|
549
|
+
name: 'join',
|
|
550
|
+
values: [
|
|
551
|
+
{
|
|
552
|
+
displayName: 'Table',
|
|
553
|
+
name: 'table',
|
|
554
|
+
type: 'string',
|
|
555
|
+
default: '',
|
|
556
|
+
placeholder: 'company_email',
|
|
557
|
+
description: 'Related table to join',
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
displayName: 'Columns',
|
|
561
|
+
name: 'columns',
|
|
562
|
+
type: 'string',
|
|
563
|
+
default: '*',
|
|
564
|
+
placeholder: 'email,verified',
|
|
565
|
+
description: 'Comma-separated columns to select from the joined table (* for all)',
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
displayName: 'Join Type',
|
|
569
|
+
name: 'joinType',
|
|
570
|
+
type: 'options',
|
|
571
|
+
options: [
|
|
572
|
+
{ name: 'Left Join', value: 'left' },
|
|
573
|
+
{ name: 'Inner Join', value: 'inner' },
|
|
574
|
+
],
|
|
575
|
+
default: 'left',
|
|
576
|
+
description: 'Left returns all rows even without a match; Inner only returns rows with a match',
|
|
577
|
+
},
|
|
578
|
+
],
|
|
579
|
+
},
|
|
580
|
+
],
|
|
581
|
+
},
|
|
530
582
|
{
|
|
531
583
|
displayName: 'Sort',
|
|
532
584
|
name: 'sort',
|
|
@@ -196,16 +196,26 @@ async function handleRead(supabase, itemIndex, hostUrl) {
|
|
|
196
196
|
(0, supabaseClient_1.validateTableName)(table);
|
|
197
197
|
const returnFields = this.getNodeParameter('returnFields', itemIndex, '*');
|
|
198
198
|
const returnAll = this.getNodeParameter('returnAll', itemIndex, false);
|
|
199
|
+
const singleItem = this.getNodeParameter('singleItem', itemIndex, false);
|
|
199
200
|
const filters = getFilters(this, itemIndex);
|
|
200
201
|
const sort = this.getNodeParameter('sort.sortField', itemIndex, []);
|
|
202
|
+
const joins = this.getNodeParameter('joins.join', itemIndex, []);
|
|
203
|
+
let selectWithJoins = returnFields;
|
|
204
|
+
for (const j of joins) {
|
|
205
|
+
if (!j.table)
|
|
206
|
+
continue;
|
|
207
|
+
const cols = j.columns || '*';
|
|
208
|
+
const hint = j.joinType === 'inner' ? `${j.table}!inner` : j.table;
|
|
209
|
+
selectWithJoins += `,${hint}(${cols})`;
|
|
210
|
+
}
|
|
201
211
|
for (const f of filters) {
|
|
202
212
|
const valType = Array.isArray(f.value) ? `array[${f.value.length}]` : typeof f.value;
|
|
203
213
|
const valLen = typeof f.value === 'string' ? f.value.length : Array.isArray(f.value) ? f.value.length : 0;
|
|
204
214
|
console.log(`[Supabase READ] item=${itemIndex} filter: ${f.column} ${f.operator} (${valType}, len=${valLen})`);
|
|
205
215
|
}
|
|
206
|
-
const overhead = (0, supabaseClient_1.estimateUrlOverhead)(hostUrl, table,
|
|
216
|
+
const overhead = (0, supabaseClient_1.estimateUrlOverhead)(hostUrl, table, selectWithJoins, filters, sort);
|
|
207
217
|
const maxInChars = Math.max(500, supabaseClient_1.MAX_SAFE_URL_LENGTH - overhead);
|
|
208
|
-
const maxItems = (0, supabaseClient_1.computeMaxIdsPerChunk)(
|
|
218
|
+
const maxItems = (0, supabaseClient_1.computeMaxIdsPerChunk)(selectWithJoins);
|
|
209
219
|
const filterChunks = (0, supabaseClient_1.expandChunkedFilters)(filters, maxInChars, maxItems);
|
|
210
220
|
console.log(`[Supabase READ] item=${itemIndex} table=${table} returnAll=${returnAll} chunks=${filterChunks.length} maxItems=${maxItems} maxInChars=${maxInChars}`);
|
|
211
221
|
const returnData = [];
|
|
@@ -224,7 +234,7 @@ async function handleRead(supabase, itemIndex, hostUrl) {
|
|
|
224
234
|
if (hasIdColumn) {
|
|
225
235
|
let lastId = null;
|
|
226
236
|
while (hasMore) {
|
|
227
|
-
let query = buildReadQuery(supabase, table,
|
|
237
|
+
let query = buildReadQuery(supabase, table, selectWithJoins, chunkFilters, []);
|
|
228
238
|
if (lastId !== null) {
|
|
229
239
|
query = query.gt('id', lastId);
|
|
230
240
|
}
|
|
@@ -252,7 +262,7 @@ async function handleRead(supabase, itemIndex, hostUrl) {
|
|
|
252
262
|
else {
|
|
253
263
|
let batchOffset = 0;
|
|
254
264
|
while (hasMore) {
|
|
255
|
-
const query = buildReadQuery(supabase, table,
|
|
265
|
+
const query = buildReadQuery(supabase, table, selectWithJoins, chunkFilters, sort);
|
|
256
266
|
const { data, error } = await query.range(batchOffset, batchOffset + batchSize - 1);
|
|
257
267
|
if (error) {
|
|
258
268
|
console.log(`[Supabase READ] chunk ${ci + 1} batch ${batchCount + 1} FAILED after ${Date.now() - chunkStart}ms: ${(0, supabaseClient_1.formatSupabaseError)(error)}`);
|
|
@@ -301,7 +311,7 @@ async function handleRead(supabase, itemIndex, hostUrl) {
|
|
|
301
311
|
const userOffset = this.getNodeParameter('offset', itemIndex, 0);
|
|
302
312
|
const isMultiChunk = filterChunks.length > 1;
|
|
303
313
|
for (const chunkFilters of filterChunks) {
|
|
304
|
-
let query = buildReadQuery(supabase, table,
|
|
314
|
+
let query = buildReadQuery(supabase, table, selectWithJoins, chunkFilters, sort);
|
|
305
315
|
if (isMultiChunk) {
|
|
306
316
|
query = query.limit(userOffset + limit);
|
|
307
317
|
}
|
|
@@ -341,10 +351,13 @@ async function handleRead(supabase, itemIndex, hostUrl) {
|
|
|
341
351
|
},
|
|
342
352
|
});
|
|
343
353
|
}
|
|
344
|
-
const singleItem = this.getNodeParameter('singleItem', itemIndex, false);
|
|
345
354
|
if (singleItem && returnData.length > 0) {
|
|
346
|
-
const
|
|
347
|
-
|
|
355
|
+
const count = returnData.length;
|
|
356
|
+
const allRows = new Array(count);
|
|
357
|
+
for (let i = 0; i < count; i++)
|
|
358
|
+
allRows[i] = returnData[i].json;
|
|
359
|
+
returnData.length = 0;
|
|
360
|
+
return [{ json: { data: allRows, count } }];
|
|
348
361
|
}
|
|
349
362
|
return returnData;
|
|
350
363
|
}
|
package/package.json
CHANGED