@fachkraftfreund/n8n-nodes-supabase 1.3.13 → 1.4.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.
@@ -69,6 +69,12 @@ class Supabase {
69
69
  description: 'Read rows from table',
70
70
  action: 'Read rows',
71
71
  },
72
+ {
73
+ name: 'Count',
74
+ value: 'count',
75
+ description: 'Count rows matching conditions',
76
+ action: 'Count rows',
77
+ },
72
78
  {
73
79
  name: 'Update',
74
80
  value: 'update',
@@ -250,7 +256,7 @@ class Supabase {
250
256
  displayOptions: {
251
257
  show: {
252
258
  resource: ['database'],
253
- operation: ['create', 'read', 'update', 'delete', 'upsert', 'updateByQuery'],
259
+ operation: ['create', 'read', 'update', 'delete', 'upsert', 'updateByQuery', 'count'],
254
260
  },
255
261
  },
256
262
  },
@@ -267,7 +273,7 @@ class Supabase {
267
273
  displayOptions: {
268
274
  show: {
269
275
  resource: ['database'],
270
- operation: ['create', 'read', 'update', 'delete', 'upsert', 'findOrCreate', 'updateByQuery'],
276
+ operation: ['create', 'read', 'update', 'delete', 'upsert', 'findOrCreate', 'updateByQuery', 'count'],
271
277
  },
272
278
  },
273
279
  },
@@ -467,7 +473,7 @@ class Supabase {
467
473
  displayOptions: {
468
474
  show: {
469
475
  resource: ['database'],
470
- operation: ['read', 'delete', 'updateByQuery'],
476
+ operation: ['read', 'delete', 'updateByQuery', 'count'],
471
477
  uiMode: ['simple'],
472
478
  },
473
479
  },
@@ -527,7 +533,7 @@ class Supabase {
527
533
  displayOptions: {
528
534
  show: {
529
535
  resource: ['database'],
530
- operation: ['read', 'delete', 'updateByQuery'],
536
+ operation: ['read', 'delete', 'updateByQuery', 'count'],
531
537
  uiMode: ['advanced'],
532
538
  },
533
539
  },
@@ -559,7 +565,7 @@ class Supabase {
559
565
  displayOptions: {
560
566
  show: {
561
567
  resource: ['database'],
562
- operation: ['read'],
568
+ operation: ['read', 'count'],
563
569
  },
564
570
  },
565
571
  options: [
@@ -1039,7 +1045,7 @@ class Supabase {
1039
1045
  }
1040
1046
  }
1041
1047
  }
1042
- else if (resource === 'database' && operation === 'read') {
1048
+ else if (resource === 'database' && (operation === 'read' || operation === 'count')) {
1043
1049
  try {
1044
1050
  const operationResults = await database_1.executeDatabaseOperation.call(this, supabase, operation, 0, credentials.host);
1045
1051
  for (const r of operationResults)
@@ -42,6 +42,9 @@ async function executeDatabaseOperation(supabase, operation, itemIndex, hostUrl)
42
42
  case 'updateByQuery':
43
43
  returnData.push(...await handleUpdateByQuery.call(this, supabase, itemIndex, hostUrl));
44
44
  break;
45
+ case 'count':
46
+ returnData.push(...await handleCount.call(this, supabase, itemIndex, hostUrl));
47
+ break;
45
48
  default:
46
49
  throw new Error(`Unknown database operation: ${operation}`);
47
50
  }
@@ -779,3 +782,34 @@ async function handleUpdateByQuery(supabase, itemIndex, hostUrl) {
779
782
  }
780
783
  return returnData;
781
784
  }
785
+ async function handleCount(supabase, itemIndex, hostUrl) {
786
+ const table = this.getNodeParameter('table', itemIndex);
787
+ (0, supabaseClient_1.validateTableName)(table);
788
+ const filters = getFilters(this, itemIndex);
789
+ const joins = this.getNodeParameter('joins.join', itemIndex, []);
790
+ let selectWithJoins = '*';
791
+ for (const j of joins) {
792
+ if (!j.table)
793
+ continue;
794
+ const cols = j.columns || '*';
795
+ const hint = j.joinType === 'inner' ? `${j.table}!inner` : j.table;
796
+ selectWithJoins += `,${hint}(${cols})`;
797
+ }
798
+ const overhead = (0, supabaseClient_1.estimateUrlOverhead)(hostUrl, table, selectWithJoins, filters);
799
+ const maxInChars = Math.max(500, supabaseClient_1.MAX_SAFE_URL_LENGTH - overhead);
800
+ const maxItems = (0, supabaseClient_1.computeMaxIdsPerChunk)(selectWithJoins);
801
+ const filterChunks = (0, supabaseClient_1.expandChunkedFilters)(filters, maxInChars, maxItems);
802
+ let totalCount = 0;
803
+ for (const chunkFilters of filterChunks) {
804
+ let query = supabase.from(table).select(selectWithJoins, { count: 'exact', head: true });
805
+ for (const filter of chunkFilters) {
806
+ const operator = (0, supabaseClient_1.convertFilterOperator)(filter.operator);
807
+ query = query.filter(filter.column, operator, (0, supabaseClient_1.normalizeFilterValue)(filter.operator, filter.value));
808
+ }
809
+ const { count, error } = await query;
810
+ if (error)
811
+ throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
812
+ totalCount += count !== null && count !== void 0 ? count : 0;
813
+ }
814
+ return [{ json: { count: totalCount, table } }];
815
+ }
@@ -75,7 +75,7 @@ export interface ISupabaseStorageResponse<T = any> {
75
75
  statusCode?: string;
76
76
  } | null;
77
77
  }
78
- export type DatabaseOperation = 'create' | 'read' | 'update' | 'delete' | 'upsert' | 'createTable' | 'dropTable' | 'addColumn' | 'dropColumn' | 'createIndex' | 'dropIndex' | 'customQuery' | 'findOrCreate' | 'updateByQuery';
78
+ export type DatabaseOperation = 'create' | 'read' | 'update' | 'delete' | 'upsert' | 'createTable' | 'dropTable' | 'addColumn' | 'dropColumn' | 'createIndex' | 'dropIndex' | 'customQuery' | 'findOrCreate' | 'updateByQuery' | 'count';
79
79
  export type StorageOperation = 'uploadFile' | 'downloadFile' | 'listFiles' | 'deleteFile' | 'moveFile' | 'copyFile' | 'createBucket' | 'deleteBucket' | 'listBuckets' | 'getBucketDetails' | 'getFileInfo' | 'generateSignedUrl';
80
80
  export type SupabaseResource = 'database' | 'storage';
81
81
  export interface ISupabaseNodeParameters {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fachkraftfreund/n8n-nodes-supabase",
3
- "version": "1.3.13",
3
+ "version": "1.4.0",
4
4
  "description": "Comprehensive n8n community node for Supabase with database and storage operations",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",