Skip to content

Commit cfcd6d6

Browse files
authored
Merge pull request #167 from psteinroe/fix/mutate-with-pks-only
fix: only mutate with pks only, if the key either does not fitler on …
2 parents edf969c + 4d16f00 commit cfcd6d6

File tree

11 files changed

+322
-15
lines changed

11 files changed

+322
-15
lines changed

.changeset/old-countries-bow.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@supabase-cache-helpers/postgrest-filter": patch
3+
"@supabase-cache-helpers/postgrest-mutate": patch
4+
---
5+
6+
only mutate with pks only, if the key either does not fitler on pks, or the input matches all pk filters

packages/postgrest-filter/__tests__/lib/transform-recursive.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,29 @@
11
import { transformRecursive } from '../../src';
22

33
describe('transformRecursive', () => {
4+
it('should transform nulls to null', () => {
5+
expect(
6+
transformRecursive(
7+
[
8+
{
9+
alias: 'id',
10+
declaration: 'id',
11+
path: 'id',
12+
},
13+
{
14+
alias: 'full_name',
15+
declaration: 'full_name:display_name',
16+
path: 'display_name',
17+
},
18+
],
19+
{
20+
id: null,
21+
display_name: null,
22+
},
23+
'path'
24+
)
25+
).toEqual({ id: null, display_name: null });
26+
});
427
it('should transform nulls of relation to null', () => {
528
expect(
629
transformRecursive(

packages/postgrest-filter/__tests__/postgrest-filter.spec.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,129 @@ describe('PostgrestFilter', () => {
354354
).toEqual(false);
355355
});
356356
});
357+
358+
describe('.hasFiltersOnPaths', () => {
359+
it('should return false if there is no filter on the given paths', () => {
360+
expect(
361+
new PostgrestFilter({
362+
filters: [
363+
{
364+
or: [
365+
{
366+
path: 'some_other_path',
367+
alias: 'text',
368+
negate: false,
369+
operator: 'eq',
370+
value: 'some-text',
371+
},
372+
],
373+
},
374+
],
375+
paths: [
376+
{ path: 'text', declaration: 'text' },
377+
{ path: 'array', declaration: 'array' },
378+
{ path: 'some.nested.value', declaration: 'some.nested.value' },
379+
],
380+
}).hasFiltersOnPaths(['some_path', 'some_unexisting_path'])
381+
).toEqual(false);
382+
});
383+
it('should return true if any path is included', () => {
384+
expect(
385+
new PostgrestFilter({
386+
filters: [
387+
{
388+
or: [
389+
{
390+
path: 'id',
391+
alias: undefined,
392+
negate: false,
393+
operator: 'eq',
394+
value: 1,
395+
},
396+
{
397+
path: 'some_other_path',
398+
alias: 'text',
399+
negate: false,
400+
operator: 'eq',
401+
value: 'some-text',
402+
},
403+
],
404+
},
405+
],
406+
paths: [
407+
{ path: 'text', declaration: 'text' },
408+
{ path: 'array', declaration: 'array' },
409+
{ path: 'some.nested.value', declaration: 'some.nested.value' },
410+
],
411+
}).hasFiltersOnPaths(['some_unexisting_path', 'id'])
412+
).toEqual(true);
413+
});
414+
});
415+
416+
describe('.applyFiltersOnPaths', () => {
417+
it('with and', () => {
418+
expect(
419+
new PostgrestFilter({
420+
filters: [
421+
{
422+
and: [
423+
{
424+
path: 'some_other_path',
425+
alias: 'text',
426+
negate: false,
427+
operator: 'eq',
428+
value: 'some-text',
429+
},
430+
{
431+
path: 'id',
432+
negate: false,
433+
operator: 'eq',
434+
value: 5,
435+
},
436+
],
437+
},
438+
],
439+
paths: [
440+
{ path: 'text', declaration: 'text' },
441+
{ path: 'array', declaration: 'array' },
442+
{ path: 'some.nested.value', declaration: 'some.nested.value' },
443+
],
444+
}).applyFiltersOnPaths(MOCK, ['some_other_path'])
445+
).toEqual(true);
446+
});
447+
it('with or', () => {
448+
expect(
449+
new PostgrestFilter({
450+
filters: [
451+
{
452+
or: [
453+
{
454+
path: 'some_other_path',
455+
alias: 'text',
456+
negate: false,
457+
operator: 'eq',
458+
value: 'some-text-123',
459+
},
460+
461+
{
462+
path: 'id',
463+
negate: false,
464+
operator: 'eq',
465+
value: 1,
466+
},
467+
],
468+
},
469+
],
470+
paths: [
471+
{ path: 'text', declaration: 'text' },
472+
{ path: 'array', declaration: 'array' },
473+
{ path: 'some.nested.value', declaration: 'some.nested.value' },
474+
],
475+
}).applyFiltersOnPaths(MOCK, ['some_other_path'])
476+
).toEqual(false);
477+
});
478+
});
479+
357480
describe('.apply', () => {
358481
it('with alias', () => {
359482
expect(
@@ -368,6 +491,12 @@ describe('PostgrestFilter', () => {
368491
operator: 'eq',
369492
value: 'some-text',
370493
},
494+
{
495+
path: 'id',
496+
negate: false,
497+
operator: 'eq',
498+
value: 5,
499+
},
371500
],
372501
},
373502
],
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {
2+
isAndFilter,
3+
isOrFilter,
4+
isFilterDefinition,
5+
FilterDefinitions,
6+
} from './types';
7+
8+
export const filterFilterDefinitionsByPaths = (
9+
f: FilterDefinitions,
10+
paths: string[]
11+
) => {
12+
return f.reduce<FilterDefinitions>((prev, filter) => {
13+
if (isAndFilter(filter)) {
14+
const filters = filterFilterDefinitionsByPaths(filter.and, paths);
15+
if (filters.length > 0) {
16+
prev.push({ and: filters });
17+
}
18+
} else if (isOrFilter(filter)) {
19+
const filters = filterFilterDefinitionsByPaths(filter.or, paths);
20+
if (filters.length > 0) {
21+
prev.push({ or: filters });
22+
}
23+
} else if (isFilterDefinition(filter) && paths.includes(filter.path)) {
24+
prev.push(filter);
25+
}
26+
return prev;
27+
}, []);
28+
};

packages/postgrest-filter/src/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './extract-paths-from-filters';
2+
export * from './filter-filter-definitions-by-paths';
23
export * from './group-paths-recursive';
34
export * from './normalize';
45
export * from './operators';

packages/postgrest-filter/src/postgrest-filter.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
ValueType,
1414
extractPathsFromFilters,
1515
transformRecursive,
16+
filterFilterDefinitionsByPaths,
1617
} from './lib';
1718
import {
1819
PostgrestQueryParser,
@@ -80,6 +81,22 @@ export class PostgrestFilter<Result extends Record<string, unknown>> {
8081
return this._filtersFn(obj);
8182
}
8283

84+
hasFiltersOnPaths(paths: string[]): boolean {
85+
return (
86+
filterFilterDefinitionsByPaths(this.params.filters, paths).length > 0
87+
);
88+
}
89+
90+
applyFiltersOnPaths(obj: unknown, paths: string[]): obj is Result {
91+
const filterFns = filterFilterDefinitionsByPaths(
92+
this.params.filters,
93+
paths
94+
).map((d) => this.buildFilterFn(d));
95+
const filtersFn = (obj: unknown): obj is Result =>
96+
filterFns.every((fn) => isObject(obj) && fn(obj));
97+
return filtersFn(obj);
98+
}
99+
83100
hasPaths(obj: unknown): obj is Result {
84101
if (!this._selectFn) {
85102
this._selectFn = (obj): obj is Result =>

packages/postgrest-mutate/__tests__/delete.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ describe('deleteItem', () => {
2727
},
2828
getPostgrestFilter() {
2929
return {
30+
applyFiltersOnPaths: (obj: unknown): obj is ItemType => true,
31+
hasFiltersOnPaths() {
32+
return true;
33+
},
3034
transform: (obj) => obj,
3135
apply(obj): obj is ItemType {
3236
return true;

0 commit comments

Comments
 (0)