@fachkraftfreund/n8n-nodes-supabase 1.2.6 → 1.2.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.
- package/dist/nodes/Supabase/Supabase.node.js +73 -24
- package/dist/nodes/Supabase/operations/database/index.d.ts +1 -0
- package/dist/nodes/Supabase/operations/database/index.js +155 -137
- package/dist/nodes/Supabase/utils/supabaseClient.d.ts +1 -0
- package/dist/nodes/Supabase/utils/supabaseClient.js +12 -1
- package/package.json +1 -1
|
@@ -335,6 +335,23 @@ class Supabase {
|
|
|
335
335
|
},
|
|
336
336
|
},
|
|
337
337
|
},
|
|
338
|
+
{
|
|
339
|
+
displayName: 'Match Column',
|
|
340
|
+
name: 'matchColumn',
|
|
341
|
+
type: 'options',
|
|
342
|
+
typeOptions: {
|
|
343
|
+
loadOptionsMethod: 'getColumns',
|
|
344
|
+
},
|
|
345
|
+
required: true,
|
|
346
|
+
default: '',
|
|
347
|
+
description: 'Column used to match rows for updating (typically the primary key). Each input item must include this column in its data. Uses upsert internally, so rows will be created if no match is found.',
|
|
348
|
+
displayOptions: {
|
|
349
|
+
show: {
|
|
350
|
+
resource: ['database'],
|
|
351
|
+
operation: ['update'],
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
338
355
|
{
|
|
339
356
|
displayName: 'Match Columns',
|
|
340
357
|
name: 'matchColumns',
|
|
@@ -431,7 +448,7 @@ class Supabase {
|
|
|
431
448
|
displayOptions: {
|
|
432
449
|
show: {
|
|
433
450
|
resource: ['database'],
|
|
434
|
-
operation: ['read', '
|
|
451
|
+
operation: ['read', 'delete'],
|
|
435
452
|
uiMode: ['simple'],
|
|
436
453
|
},
|
|
437
454
|
},
|
|
@@ -491,7 +508,7 @@ class Supabase {
|
|
|
491
508
|
displayOptions: {
|
|
492
509
|
show: {
|
|
493
510
|
resource: ['database'],
|
|
494
|
-
operation: ['read', '
|
|
511
|
+
operation: ['read', 'delete'],
|
|
495
512
|
uiMode: ['advanced'],
|
|
496
513
|
},
|
|
497
514
|
},
|
|
@@ -551,6 +568,19 @@ class Supabase {
|
|
|
551
568
|
},
|
|
552
569
|
],
|
|
553
570
|
},
|
|
571
|
+
{
|
|
572
|
+
displayName: 'Return All',
|
|
573
|
+
name: 'returnAll',
|
|
574
|
+
type: 'boolean',
|
|
575
|
+
default: false,
|
|
576
|
+
description: 'Whether to return all results or limit the number of results',
|
|
577
|
+
displayOptions: {
|
|
578
|
+
show: {
|
|
579
|
+
resource: ['database'],
|
|
580
|
+
operation: ['read'],
|
|
581
|
+
},
|
|
582
|
+
},
|
|
583
|
+
},
|
|
554
584
|
{
|
|
555
585
|
displayName: 'Limit',
|
|
556
586
|
name: 'limit',
|
|
@@ -561,6 +591,7 @@ class Supabase {
|
|
|
561
591
|
show: {
|
|
562
592
|
resource: ['database'],
|
|
563
593
|
operation: ['read'],
|
|
594
|
+
returnAll: [false],
|
|
564
595
|
},
|
|
565
596
|
},
|
|
566
597
|
},
|
|
@@ -574,6 +605,7 @@ class Supabase {
|
|
|
574
605
|
show: {
|
|
575
606
|
resource: ['database'],
|
|
576
607
|
operation: ['read'],
|
|
608
|
+
returnAll: [false],
|
|
577
609
|
},
|
|
578
610
|
},
|
|
579
611
|
},
|
|
@@ -868,34 +900,51 @@ class Supabase {
|
|
|
868
900
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid credentials: ${errorMessage}`);
|
|
869
901
|
}
|
|
870
902
|
const supabase = (0, supabaseClient_1.createSupabaseClient)(credentials);
|
|
871
|
-
|
|
903
|
+
const resource = this.getNodeParameter('resource', 0);
|
|
904
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
905
|
+
if (resource === 'database' && ['create', 'upsert', 'update'].includes(operation)) {
|
|
872
906
|
try {
|
|
873
|
-
const
|
|
874
|
-
|
|
875
|
-
let operationResults = [];
|
|
876
|
-
if (resource === 'database') {
|
|
877
|
-
operationResults = await database_1.executeDatabaseOperation.call(this, supabase, operation, itemIndex);
|
|
878
|
-
}
|
|
879
|
-
else if (resource === 'storage') {
|
|
880
|
-
operationResults = await storage_1.executeStorageOperation.call(this, supabase, operation, itemIndex);
|
|
881
|
-
}
|
|
882
|
-
else {
|
|
883
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown resource: ${resource}`);
|
|
884
|
-
}
|
|
885
|
-
returnData.push(...operationResults);
|
|
907
|
+
const results = await database_1.executeBulkDatabaseOperation.call(this, supabase, operation, items.length);
|
|
908
|
+
returnData.push(...results);
|
|
886
909
|
}
|
|
887
910
|
catch (error) {
|
|
888
911
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
889
912
|
if (this.continueOnFail()) {
|
|
890
|
-
returnData.push({
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
913
|
+
returnData.push({ json: { error: errorMessage } });
|
|
914
|
+
}
|
|
915
|
+
else {
|
|
916
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
else {
|
|
921
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
922
|
+
try {
|
|
923
|
+
let operationResults = [];
|
|
924
|
+
if (resource === 'database') {
|
|
925
|
+
operationResults = await database_1.executeDatabaseOperation.call(this, supabase, operation, itemIndex);
|
|
926
|
+
}
|
|
927
|
+
else if (resource === 'storage') {
|
|
928
|
+
operationResults = await storage_1.executeStorageOperation.call(this, supabase, operation, itemIndex);
|
|
929
|
+
}
|
|
930
|
+
else {
|
|
931
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown resource: ${resource}`);
|
|
932
|
+
}
|
|
933
|
+
returnData.push(...operationResults);
|
|
934
|
+
}
|
|
935
|
+
catch (error) {
|
|
936
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
937
|
+
if (this.continueOnFail()) {
|
|
938
|
+
returnData.push({
|
|
939
|
+
json: {
|
|
940
|
+
error: errorMessage,
|
|
941
|
+
itemIndex,
|
|
942
|
+
},
|
|
943
|
+
});
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { itemIndex });
|
|
897
947
|
}
|
|
898
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { itemIndex });
|
|
899
948
|
}
|
|
900
949
|
}
|
|
901
950
|
return [returnData];
|
|
@@ -2,3 +2,4 @@ import { SupabaseClient } from '@supabase/supabase-js';
|
|
|
2
2
|
import { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
|
3
3
|
import { DatabaseOperation } from '../../types';
|
|
4
4
|
export declare function executeDatabaseOperation(this: IExecuteFunctions, supabase: SupabaseClient, operation: DatabaseOperation, itemIndex: number): Promise<INodeExecutionData[]>;
|
|
5
|
+
export declare function executeBulkDatabaseOperation(this: IExecuteFunctions, supabase: SupabaseClient, operation: DatabaseOperation, itemCount: number): Promise<INodeExecutionData[]>;
|
|
@@ -1,26 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.executeDatabaseOperation = void 0;
|
|
3
|
+
exports.executeBulkDatabaseOperation = exports.executeDatabaseOperation = void 0;
|
|
4
4
|
const supabaseClient_1 = require("../../utils/supabaseClient");
|
|
5
5
|
async function executeDatabaseOperation(supabase, operation, itemIndex) {
|
|
6
6
|
const returnData = [];
|
|
7
7
|
try {
|
|
8
8
|
switch (operation) {
|
|
9
|
-
case 'create':
|
|
10
|
-
returnData.push(...await handleCreate.call(this, supabase, itemIndex));
|
|
11
|
-
break;
|
|
12
9
|
case 'read':
|
|
13
10
|
returnData.push(...await handleRead.call(this, supabase, itemIndex));
|
|
14
11
|
break;
|
|
15
|
-
case 'update':
|
|
16
|
-
returnData.push(...await handleUpdate.call(this, supabase, itemIndex));
|
|
17
|
-
break;
|
|
18
12
|
case 'delete':
|
|
19
13
|
returnData.push(...await handleDelete.call(this, supabase, itemIndex));
|
|
20
14
|
break;
|
|
21
|
-
case 'upsert':
|
|
22
|
-
returnData.push(...await handleUpsert.call(this, supabase, itemIndex));
|
|
23
|
-
break;
|
|
24
15
|
case 'createTable':
|
|
25
16
|
returnData.push(...await handleCreateTable.call(this, supabase, itemIndex));
|
|
26
17
|
break;
|
|
@@ -55,63 +46,130 @@ async function executeDatabaseOperation(supabase, operation, itemIndex) {
|
|
|
55
46
|
return returnData;
|
|
56
47
|
}
|
|
57
48
|
exports.executeDatabaseOperation = executeDatabaseOperation;
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
49
|
+
function collectRowData(context, itemCount) {
|
|
50
|
+
const rows = [];
|
|
51
|
+
for (let i = 0; i < itemCount; i++) {
|
|
52
|
+
const uiMode = context.getNodeParameter('uiMode', i, 'simple');
|
|
53
|
+
let row;
|
|
54
|
+
if (uiMode === 'advanced') {
|
|
55
|
+
const jsonData = context.getNodeParameter('jsonData', i, '{}');
|
|
56
|
+
try {
|
|
57
|
+
row = JSON.parse(jsonData);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new Error(`Invalid JSON data at item ${i}`);
|
|
61
|
+
}
|
|
67
62
|
}
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
else {
|
|
64
|
+
const columns = context.getNodeParameter('columns.column', i, []);
|
|
65
|
+
row = {};
|
|
66
|
+
for (const column of columns) {
|
|
67
|
+
if (column.name && column.value !== undefined) {
|
|
68
|
+
row[column.name] = column.value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
70
71
|
}
|
|
72
|
+
rows.push(row);
|
|
71
73
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
return rows;
|
|
75
|
+
}
|
|
76
|
+
async function executeBulkDatabaseOperation(supabase, operation, itemCount) {
|
|
77
|
+
try {
|
|
78
|
+
switch (operation) {
|
|
79
|
+
case 'create':
|
|
80
|
+
return await handleBulkCreate.call(this, supabase, itemCount);
|
|
81
|
+
case 'upsert':
|
|
82
|
+
return await handleBulkUpsert.call(this, supabase, itemCount);
|
|
83
|
+
case 'update':
|
|
84
|
+
return await handleBulkUpdate.call(this, supabase, itemCount);
|
|
85
|
+
default:
|
|
86
|
+
throw new Error(`Operation ${operation} does not support bulk mode`);
|
|
79
87
|
}
|
|
80
88
|
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
throw new Error(`Database operation failed: ${(0, supabaseClient_1.formatSupabaseError)(error)}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.executeBulkDatabaseOperation = executeBulkDatabaseOperation;
|
|
94
|
+
async function handleBulkCreate(supabase, itemCount) {
|
|
95
|
+
const table = this.getNodeParameter('table', 0);
|
|
96
|
+
(0, supabaseClient_1.validateTableName)(table);
|
|
97
|
+
const rows = collectRowData(this, itemCount);
|
|
81
98
|
const { data, error } = await supabase
|
|
82
99
|
.from(table)
|
|
83
|
-
.insert(
|
|
100
|
+
.insert(rows)
|
|
84
101
|
.select();
|
|
85
|
-
if (error)
|
|
102
|
+
if (error)
|
|
86
103
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
104
|
+
if (Array.isArray(data)) {
|
|
105
|
+
return data.map((row) => ({ json: row }));
|
|
87
106
|
}
|
|
88
107
|
return [{ json: { data, operation: 'create', table } }];
|
|
89
108
|
}
|
|
90
|
-
async function
|
|
91
|
-
const table = this.getNodeParameter('table',
|
|
92
|
-
const
|
|
109
|
+
async function handleBulkUpsert(supabase, itemCount) {
|
|
110
|
+
const table = this.getNodeParameter('table', 0);
|
|
111
|
+
const onConflict = this.getNodeParameter('onConflict', 0, '');
|
|
93
112
|
(0, supabaseClient_1.validateTableName)(table);
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
if (
|
|
97
|
-
|
|
113
|
+
const rows = collectRowData(this, itemCount);
|
|
114
|
+
const options = {};
|
|
115
|
+
if (onConflict)
|
|
116
|
+
options.onConflict = onConflict;
|
|
117
|
+
const { data, error } = await supabase
|
|
118
|
+
.from(table)
|
|
119
|
+
.upsert(rows, options)
|
|
120
|
+
.select();
|
|
121
|
+
if (error)
|
|
122
|
+
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
123
|
+
if (Array.isArray(data)) {
|
|
124
|
+
return data.map((row) => ({ json: row }));
|
|
125
|
+
}
|
|
126
|
+
return [{ json: { data, operation: 'upsert', table } }];
|
|
127
|
+
}
|
|
128
|
+
async function handleBulkUpdate(supabase, itemCount) {
|
|
129
|
+
const table = this.getNodeParameter('table', 0);
|
|
130
|
+
const matchColumn = this.getNodeParameter('matchColumn', 0);
|
|
131
|
+
(0, supabaseClient_1.validateTableName)(table);
|
|
132
|
+
if (!matchColumn) {
|
|
133
|
+
throw new Error('Match Column is required for update operations');
|
|
134
|
+
}
|
|
135
|
+
const rows = collectRowData(this, itemCount);
|
|
136
|
+
for (let i = 0; i < rows.length; i++) {
|
|
137
|
+
const row = rows[i];
|
|
138
|
+
if (!row || row[matchColumn] === undefined) {
|
|
139
|
+
throw new Error(`Item ${i} is missing the match column "${matchColumn}"`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const { data, error } = await supabase
|
|
143
|
+
.from(table)
|
|
144
|
+
.upsert(rows, { onConflict: matchColumn })
|
|
145
|
+
.select();
|
|
146
|
+
if (error)
|
|
147
|
+
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
148
|
+
if (Array.isArray(data)) {
|
|
149
|
+
return data.map((row) => ({ json: row }));
|
|
98
150
|
}
|
|
151
|
+
return [{ json: { data, operation: 'update', table } }];
|
|
152
|
+
}
|
|
153
|
+
function buildReadQuery(context, supabase, table, returnFields, itemIndex, options) {
|
|
154
|
+
const selectFields = returnFields && returnFields !== '*' ? returnFields : '*';
|
|
155
|
+
let query = supabase.from(table).select(selectFields, options);
|
|
156
|
+
const uiMode = context.getNodeParameter('uiMode', itemIndex, 'simple');
|
|
99
157
|
if (uiMode === 'simple') {
|
|
100
|
-
const filters =
|
|
158
|
+
const filters = context.getNodeParameter('filters.filter', itemIndex, []);
|
|
101
159
|
for (const filter of filters) {
|
|
102
160
|
const operator = (0, supabaseClient_1.convertFilterOperator)(filter.operator);
|
|
103
|
-
query = query.filter(filter.column, operator, filter.value);
|
|
161
|
+
query = query.filter(filter.column, operator, (0, supabaseClient_1.normalizeFilterValue)(filter.operator, filter.value));
|
|
104
162
|
}
|
|
105
163
|
}
|
|
106
164
|
else {
|
|
107
|
-
const advancedFilters =
|
|
165
|
+
const advancedFilters = context.getNodeParameter('advancedFilters', itemIndex, '');
|
|
108
166
|
if (advancedFilters) {
|
|
109
167
|
try {
|
|
110
168
|
const filters = JSON.parse(advancedFilters);
|
|
111
169
|
for (const [column, condition] of Object.entries(filters)) {
|
|
112
170
|
if (typeof condition === 'object' && condition !== null) {
|
|
113
171
|
const [operator, value] = Object.entries(condition)[0];
|
|
114
|
-
query = query.filter(column, (0, supabaseClient_1.convertFilterOperator)(operator), value);
|
|
172
|
+
query = query.filter(column, (0, supabaseClient_1.convertFilterOperator)(operator), (0, supabaseClient_1.normalizeFilterValue)(operator, value));
|
|
115
173
|
}
|
|
116
174
|
else {
|
|
117
175
|
query = query.eq(column, condition);
|
|
@@ -123,33 +181,65 @@ async function handleRead(supabase, itemIndex) {
|
|
|
123
181
|
}
|
|
124
182
|
}
|
|
125
183
|
}
|
|
126
|
-
const sort =
|
|
184
|
+
const sort = context.getNodeParameter('sort.sortField', itemIndex, []);
|
|
127
185
|
for (const sortField of sort) {
|
|
128
186
|
query = query.order(sortField.column, { ascending: sortField.ascending });
|
|
129
187
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
const { data, error, count } = await query;
|
|
139
|
-
if (error) {
|
|
140
|
-
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
141
|
-
}
|
|
188
|
+
return query;
|
|
189
|
+
}
|
|
190
|
+
async function handleRead(supabase, itemIndex) {
|
|
191
|
+
const table = this.getNodeParameter('table', itemIndex);
|
|
192
|
+
(0, supabaseClient_1.validateTableName)(table);
|
|
193
|
+
const returnFields = this.getNodeParameter('returnFields', itemIndex, '*');
|
|
194
|
+
const returnAll = this.getNodeParameter('returnAll', itemIndex, false);
|
|
142
195
|
const returnData = [];
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
|
|
196
|
+
if (returnAll) {
|
|
197
|
+
const batchSize = 1000;
|
|
198
|
+
let offset = 0;
|
|
199
|
+
let hasMore = true;
|
|
200
|
+
while (hasMore) {
|
|
201
|
+
const batchQuery = buildReadQuery(this, supabase, table, returnFields, itemIndex, { count: 'exact' });
|
|
202
|
+
const { data: batchData, error: batchError } = await batchQuery.range(offset, offset + batchSize - 1);
|
|
203
|
+
if (batchError) {
|
|
204
|
+
throw new Error((0, supabaseClient_1.formatSupabaseError)(batchError));
|
|
205
|
+
}
|
|
206
|
+
if (Array.isArray(batchData)) {
|
|
207
|
+
for (const row of batchData) {
|
|
208
|
+
returnData.push({ json: row });
|
|
209
|
+
}
|
|
210
|
+
hasMore = batchData.length === batchSize;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
hasMore = false;
|
|
214
|
+
}
|
|
215
|
+
offset += batchSize;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
const limit = this.getNodeParameter('limit', itemIndex, undefined);
|
|
220
|
+
const offset = this.getNodeParameter('offset', itemIndex, undefined);
|
|
221
|
+
let query = buildReadQuery(this, supabase, table, returnFields, itemIndex);
|
|
222
|
+
if (limit !== undefined) {
|
|
223
|
+
query = query.limit(limit);
|
|
224
|
+
}
|
|
225
|
+
if (offset !== undefined) {
|
|
226
|
+
query = query.range(offset, offset + (limit || 1000) - 1);
|
|
227
|
+
}
|
|
228
|
+
const { data, error } = await query;
|
|
229
|
+
if (error) {
|
|
230
|
+
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
231
|
+
}
|
|
232
|
+
if (Array.isArray(data)) {
|
|
233
|
+
for (const row of data) {
|
|
234
|
+
returnData.push({ json: row });
|
|
235
|
+
}
|
|
146
236
|
}
|
|
147
237
|
}
|
|
148
238
|
if (returnData.length === 0) {
|
|
149
239
|
returnData.push({
|
|
150
240
|
json: {
|
|
151
241
|
data: [],
|
|
152
|
-
count:
|
|
242
|
+
count: 0,
|
|
153
243
|
operation: 'read',
|
|
154
244
|
table,
|
|
155
245
|
message: 'No records found',
|
|
@@ -158,41 +248,6 @@ async function handleRead(supabase, itemIndex) {
|
|
|
158
248
|
}
|
|
159
249
|
return returnData;
|
|
160
250
|
}
|
|
161
|
-
async function handleUpdate(supabase, itemIndex) {
|
|
162
|
-
const table = this.getNodeParameter('table', itemIndex);
|
|
163
|
-
const uiMode = this.getNodeParameter('uiMode', itemIndex, 'simple');
|
|
164
|
-
(0, supabaseClient_1.validateTableName)(table);
|
|
165
|
-
let dataToUpdate;
|
|
166
|
-
if (uiMode === 'advanced') {
|
|
167
|
-
const jsonData = this.getNodeParameter('jsonData', itemIndex, '{}');
|
|
168
|
-
try {
|
|
169
|
-
dataToUpdate = JSON.parse(jsonData);
|
|
170
|
-
}
|
|
171
|
-
catch {
|
|
172
|
-
throw new Error('Invalid JSON data provided');
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
const columns = this.getNodeParameter('columns.column', itemIndex, []);
|
|
177
|
-
dataToUpdate = {};
|
|
178
|
-
for (const column of columns) {
|
|
179
|
-
if (column.name && column.value !== undefined) {
|
|
180
|
-
dataToUpdate[column.name] = column.value;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
let query = supabase.from(table).update(dataToUpdate);
|
|
185
|
-
const filters = this.getNodeParameter('filters.filter', itemIndex, []);
|
|
186
|
-
for (const filter of filters) {
|
|
187
|
-
const operator = (0, supabaseClient_1.convertFilterOperator)(filter.operator);
|
|
188
|
-
query = query.filter(filter.column, operator, filter.value);
|
|
189
|
-
}
|
|
190
|
-
const { data, error } = await query.select();
|
|
191
|
-
if (error) {
|
|
192
|
-
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
193
|
-
}
|
|
194
|
-
return [{ json: { data, operation: 'update', table, updated: (data === null || data === void 0 ? void 0 : data.length) || 0 } }];
|
|
195
|
-
}
|
|
196
251
|
async function handleDelete(supabase, itemIndex) {
|
|
197
252
|
const table = this.getNodeParameter('table', itemIndex);
|
|
198
253
|
(0, supabaseClient_1.validateTableName)(table);
|
|
@@ -203,7 +258,7 @@ async function handleDelete(supabase, itemIndex) {
|
|
|
203
258
|
}
|
|
204
259
|
for (const filter of filters) {
|
|
205
260
|
const operator = (0, supabaseClient_1.convertFilterOperator)(filter.operator);
|
|
206
|
-
query = query.filter(filter.column, operator, filter.value);
|
|
261
|
+
query = query.filter(filter.column, operator, (0, supabaseClient_1.normalizeFilterValue)(filter.operator, filter.value));
|
|
207
262
|
}
|
|
208
263
|
const { data, error } = await query.select();
|
|
209
264
|
if (error) {
|
|
@@ -211,43 +266,6 @@ async function handleDelete(supabase, itemIndex) {
|
|
|
211
266
|
}
|
|
212
267
|
return [{ json: { data, operation: 'delete', table, deleted: (data === null || data === void 0 ? void 0 : data.length) || 0 } }];
|
|
213
268
|
}
|
|
214
|
-
async function handleUpsert(supabase, itemIndex) {
|
|
215
|
-
const table = this.getNodeParameter('table', itemIndex);
|
|
216
|
-
const uiMode = this.getNodeParameter('uiMode', itemIndex, 'simple');
|
|
217
|
-
const onConflict = this.getNodeParameter('onConflict', itemIndex, '');
|
|
218
|
-
(0, supabaseClient_1.validateTableName)(table);
|
|
219
|
-
let dataToUpsert;
|
|
220
|
-
if (uiMode === 'advanced') {
|
|
221
|
-
const jsonData = this.getNodeParameter('jsonData', itemIndex, '{}');
|
|
222
|
-
try {
|
|
223
|
-
dataToUpsert = JSON.parse(jsonData);
|
|
224
|
-
}
|
|
225
|
-
catch {
|
|
226
|
-
throw new Error('Invalid JSON data provided');
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
const columns = this.getNodeParameter('columns.column', itemIndex, []);
|
|
231
|
-
dataToUpsert = {};
|
|
232
|
-
for (const column of columns) {
|
|
233
|
-
if (column.name && column.value !== undefined) {
|
|
234
|
-
dataToUpsert[column.name] = column.value;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
const options = {};
|
|
239
|
-
if (onConflict) {
|
|
240
|
-
options.onConflict = onConflict;
|
|
241
|
-
}
|
|
242
|
-
const { data, error } = await supabase
|
|
243
|
-
.from(table)
|
|
244
|
-
.upsert(dataToUpsert, options)
|
|
245
|
-
.select();
|
|
246
|
-
if (error) {
|
|
247
|
-
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
248
|
-
}
|
|
249
|
-
return [{ json: { data, operation: 'upsert', table } }];
|
|
250
|
-
}
|
|
251
269
|
async function handleCreateTable(supabase, itemIndex) {
|
|
252
270
|
const tableName = this.getNodeParameter('tableName', itemIndex);
|
|
253
271
|
const columns = this.getNodeParameter('columnDefinitions.column', itemIndex, []);
|
|
@@ -275,7 +293,7 @@ async function handleCreateTable(supabase, itemIndex) {
|
|
|
275
293
|
columnDefs.push(columnDef);
|
|
276
294
|
}
|
|
277
295
|
sql += columnDefs.join(', ') + ')';
|
|
278
|
-
const {
|
|
296
|
+
const { error } = await supabase.rpc('exec_sql', { sql });
|
|
279
297
|
if (error) {
|
|
280
298
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
281
299
|
}
|
|
@@ -286,7 +304,7 @@ async function handleDropTable(supabase, itemIndex) {
|
|
|
286
304
|
const cascade = this.getNodeParameter('cascade', itemIndex, false);
|
|
287
305
|
(0, supabaseClient_1.validateTableName)(tableName);
|
|
288
306
|
const sql = `DROP TABLE "${tableName}"${cascade ? ' CASCADE' : ''}`;
|
|
289
|
-
const {
|
|
307
|
+
const { error } = await supabase.rpc('exec_sql', { sql });
|
|
290
308
|
if (error) {
|
|
291
309
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
292
310
|
}
|
|
@@ -304,7 +322,7 @@ async function handleAddColumn(supabase, itemIndex) {
|
|
|
304
322
|
if (columnDefinition.defaultValue) {
|
|
305
323
|
sql += ` DEFAULT ${columnDefinition.defaultValue}`;
|
|
306
324
|
}
|
|
307
|
-
const {
|
|
325
|
+
const { error } = await supabase.rpc('exec_sql', { sql });
|
|
308
326
|
if (error) {
|
|
309
327
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
310
328
|
}
|
|
@@ -317,7 +335,7 @@ async function handleDropColumn(supabase, itemIndex) {
|
|
|
317
335
|
(0, supabaseClient_1.validateTableName)(tableName);
|
|
318
336
|
(0, supabaseClient_1.validateColumnName)(columnName);
|
|
319
337
|
const sql = `ALTER TABLE "${tableName}" DROP COLUMN "${columnName}"${cascade ? ' CASCADE' : ''}`;
|
|
320
|
-
const {
|
|
338
|
+
const { error } = await supabase.rpc('exec_sql', { sql });
|
|
321
339
|
if (error) {
|
|
322
340
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
323
341
|
}
|
|
@@ -334,7 +352,7 @@ async function handleCreateIndex(supabase, itemIndex) {
|
|
|
334
352
|
const method = indexDefinition.method ? ` USING ${indexDefinition.method}` : '';
|
|
335
353
|
const columnList = indexDefinition.columns.map(col => `"${col}"`).join(', ');
|
|
336
354
|
const sql = `CREATE ${uniqueKeyword}INDEX "${indexDefinition.name}" ON "${tableName}"${method} (${columnList})`;
|
|
337
|
-
const {
|
|
355
|
+
const { error } = await supabase.rpc('exec_sql', { sql });
|
|
338
356
|
if (error) {
|
|
339
357
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
340
358
|
}
|
|
@@ -347,7 +365,7 @@ async function handleDropIndex(supabase, itemIndex) {
|
|
|
347
365
|
throw new Error('Index name is required');
|
|
348
366
|
}
|
|
349
367
|
const sql = `DROP INDEX "${indexName}"${cascade ? ' CASCADE' : ''}`;
|
|
350
|
-
const {
|
|
368
|
+
const { error } = await supabase.rpc('exec_sql', { sql });
|
|
351
369
|
if (error) {
|
|
352
370
|
throw new Error((0, supabaseClient_1.formatSupabaseError)(error));
|
|
353
371
|
}
|
|
@@ -11,3 +11,4 @@ export declare function sanitizeColumnName(columnName: string): string;
|
|
|
11
11
|
export declare function validateTableName(tableName: string): void;
|
|
12
12
|
export declare function validateColumnName(columnName: string): void;
|
|
13
13
|
export declare function convertFilterOperator(operator: string): string;
|
|
14
|
+
export declare function normalizeFilterValue(operator: string, value: string | number | boolean | null): string | number | boolean | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.convertFilterOperator = exports.validateColumnName = exports.validateTableName = exports.sanitizeColumnName = exports.isNetworkError = exports.isAuthError = exports.formatSupabaseError = exports.getDatabaseUrl = exports.getStorageUrl = exports.validateCredentials = exports.createSupabaseClient = void 0;
|
|
3
|
+
exports.normalizeFilterValue = exports.convertFilterOperator = exports.validateColumnName = exports.validateTableName = exports.sanitizeColumnName = exports.isNetworkError = exports.isAuthError = exports.formatSupabaseError = exports.getDatabaseUrl = exports.getStorageUrl = exports.validateCredentials = exports.createSupabaseClient = void 0;
|
|
4
4
|
const supabase_js_1 = require("@supabase/supabase-js");
|
|
5
5
|
function createSupabaseClient(credentials) {
|
|
6
6
|
const client = (0, supabase_js_1.createClient)(credentials.host, credentials.serviceKey, {
|
|
@@ -136,3 +136,14 @@ function convertFilterOperator(operator) {
|
|
|
136
136
|
return operatorMap[operator] || 'eq';
|
|
137
137
|
}
|
|
138
138
|
exports.convertFilterOperator = convertFilterOperator;
|
|
139
|
+
function normalizeFilterValue(operator, value) {
|
|
140
|
+
if (operator === 'in' && typeof value === 'string') {
|
|
141
|
+
const trimmed = value.trim();
|
|
142
|
+
if (!trimmed.startsWith('(')) {
|
|
143
|
+
return `(${trimmed})`;
|
|
144
|
+
}
|
|
145
|
+
return trimmed;
|
|
146
|
+
}
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
exports.normalizeFilterValue = normalizeFilterValue;
|
package/package.json
CHANGED