Skip to content

Commit d7cc789

Browse files
authored
fix(Supabase Node): Allow for filtering on the same field multiple times (#12429)
1 parent 4d1d5d9 commit d7cc789

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

packages/nodes-base/nodes/Supabase/Supabase.node.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,8 @@ export class Supabase implements INodeType {
293293

294294
if (keys.length !== 0) {
295295
if (matchType === 'allFilters') {
296-
const data = keys.reduce((obj, value) => buildQuery(obj, value), {});
297-
Object.assign(qs, data);
296+
const data = keys.map((key) => buildOrQuery(key));
297+
Object.assign(qs, { and: `(${data.join(',')})` });
298298
}
299299
if (matchType === 'anyFilter') {
300300
const data = keys.map((key) => buildOrQuery(key));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { mock } from 'jest-mock-extended';
2+
import { get } from 'lodash';
3+
import {
4+
type IDataObject,
5+
type IExecuteFunctions,
6+
type IGetNodeParameterOptions,
7+
type INodeExecutionData,
8+
type IPairedItemData,
9+
NodeOperationError,
10+
} from 'n8n-workflow';
11+
12+
import * as utils from '../GenericFunctions';
13+
import { Supabase } from '../Supabase.node';
14+
15+
describe('Test Supabase Node', () => {
16+
const node = new Supabase();
17+
18+
const input = [{ json: {} }];
19+
20+
const createMockExecuteFunction = (
21+
nodeParameters: IDataObject,
22+
continueOnFail: boolean = false,
23+
) => {
24+
const fakeExecuteFunction = {
25+
getNodeParameter(
26+
parameterName: string,
27+
itemIndex: number,
28+
fallbackValue?: IDataObject | undefined,
29+
options?: IGetNodeParameterOptions | undefined,
30+
) {
31+
const parameter = options?.extractValue ? `${parameterName}.value` : parameterName;
32+
33+
const parameterValue = get(nodeParameters, parameter, fallbackValue);
34+
35+
if ((parameterValue as IDataObject)?.nodeOperationError) {
36+
throw new NodeOperationError(mock(), 'Get Options Error', { itemIndex });
37+
}
38+
39+
return parameterValue;
40+
},
41+
getNode() {
42+
return node;
43+
},
44+
continueOnFail: () => continueOnFail,
45+
getInputData: () => input,
46+
helpers: {
47+
constructExecutionMetaData: (
48+
_inputData: INodeExecutionData[],
49+
_options: { itemData: IPairedItemData | IPairedItemData[] },
50+
) => [],
51+
returnJsonArray: (_jsonData: IDataObject | IDataObject[]) => [],
52+
},
53+
} as unknown as IExecuteFunctions;
54+
return fakeExecuteFunction;
55+
};
56+
57+
it('should allow filtering on the same field multiple times', async () => {
58+
const supabaseApiRequest = jest
59+
.spyOn(utils, 'supabaseApiRequest')
60+
.mockImplementation(async () => {
61+
return [];
62+
});
63+
64+
const fakeExecuteFunction = createMockExecuteFunction({
65+
resource: 'row',
66+
operation: 'getAll',
67+
returnAll: true,
68+
filterType: 'manual',
69+
matchType: 'allFilters',
70+
tableId: 'my_table',
71+
filters: {
72+
conditions: [
73+
{
74+
condition: 'gt',
75+
keyName: 'created_at',
76+
keyValue: '2025-01-02 08:03:43.952051+00',
77+
},
78+
{
79+
condition: 'lt',
80+
keyName: 'created_at',
81+
keyValue: '2025-01-02 08:07:36.102231+00',
82+
},
83+
],
84+
},
85+
});
86+
87+
await node.execute.call(fakeExecuteFunction);
88+
89+
expect(supabaseApiRequest).toHaveBeenCalledWith(
90+
'GET',
91+
'/my_table',
92+
{},
93+
{
94+
and: '(created_at.gt.2025-01-02 08:03:43.952051+00,created_at.lt.2025-01-02 08:07:36.102231+00)',
95+
offset: 0,
96+
},
97+
);
98+
});
99+
});

0 commit comments

Comments
 (0)