Skip to content

Commit

Permalink
feat: add vertical filtering on CUD
Browse files Browse the repository at this point in the history
  • Loading branch information
soedirgo committed Jan 5, 2021
1 parent 11d9366 commit d56d69a
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 11 deletions.
3 changes: 2 additions & 1 deletion src/PostgrestClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PostgrestQueryBuilder from './lib/PostgrestQueryBuilder'
import PostgrestTransformBuilder from './lib/PostgrestTransformBuilder'
import { PostgrestBuilder } from './lib/types'

export default class PostgrestClient {
Expand Down Expand Up @@ -48,7 +49,7 @@ export default class PostgrestClient {
* @param fn The function name to call.
* @param params The parameters to pass to the function call.
*/
rpc<T = any>(fn: string, params?: object): PostgrestBuilder<T> {
rpc<T = any>(fn: string, params?: object): PostgrestTransformBuilder<T> {
const url = `${this.url}/rpc/${fn}`
return new PostgrestQueryBuilder<T>(url, { headers: this.headers, schema: this.schema }).rpc(
params
Expand Down
11 changes: 4 additions & 7 deletions src/lib/PostgrestQueryBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { PostgrestBuilder } from './types'
import PostgrestFilterBuilder from './PostgrestFilterBuilder'

/**
* CRUD
*/
import PostgrestTransformBuilder from './PostgrestTransformBuilder'

export default class PostgrestQueryBuilder<T> extends PostgrestBuilder<T> {
constructor(
Expand All @@ -17,7 +14,7 @@ export default class PostgrestQueryBuilder<T> extends PostgrestBuilder<T> {
}

/**
* Performs horizontal filtering with SELECT.
* Performs vertical filtering with SELECT.
*
* @param columns The columns to retrieve, separated by commas.
*/
Expand Down Expand Up @@ -103,9 +100,9 @@ export default class PostgrestQueryBuilder<T> extends PostgrestBuilder<T> {
}

/** @internal */
rpc(params?: object): PostgrestBuilder<T> {
rpc(params?: object): PostgrestTransformBuilder<T> {
this.method = 'POST'
this.body = params
return this
return new PostgrestTransformBuilder(this)
}
}
30 changes: 27 additions & 3 deletions src/lib/PostgrestTransformBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ import { PostgrestBuilder, PostgrestSingleResponse } from './types'
*/

export default class PostgrestTransformBuilder<T> extends PostgrestBuilder<T> {
/**
* Performs vertical filtering with SELECT.
*
* @param columns The columns to retrieve, separated by commas.
*/
select(columns = '*'): this {
// Remove whitespaces except when quoted
let quoted = false
const cleanedColumns = columns
.split('')
.map((c) => {
if (/\s/.test(c) && !quoted) {
return ''
}
if (c === '"') {
quoted = !quoted
}
return c
})
.join('')
this.url.searchParams.set('select', cleanedColumns)
return this
}

/**
* Orders the result with the specified `column`.
*
Expand All @@ -20,7 +44,7 @@ export default class PostgrestTransformBuilder<T> extends PostgrestBuilder<T> {
nullsFirst = false,
foreignTable,
}: { ascending?: boolean; nullsFirst?: boolean; foreignTable?: string } = {}
): PostgrestTransformBuilder<T> {
): this {
const key = typeof foreignTable === 'undefined' ? 'order' : `"${foreignTable}".order`
this.url.searchParams.set(
key,
Expand All @@ -38,7 +62,7 @@ export default class PostgrestTransformBuilder<T> extends PostgrestBuilder<T> {
limit(
count: number,
{ foreignTable }: { foreignTable?: string } = {}
): PostgrestTransformBuilder<T> {
): this {
const key = typeof foreignTable === 'undefined' ? 'limit' : `"${foreignTable}".limit`
this.url.searchParams.set(key, `${count}`)
return this
Expand All @@ -55,7 +79,7 @@ export default class PostgrestTransformBuilder<T> extends PostgrestBuilder<T> {
from: number,
to: number,
{ foreignTable }: { foreignTable?: string } = {}
): PostgrestTransformBuilder<T> {
): this {
const keyOffset = typeof foreignTable === 'undefined' ? 'offset' : `"${foreignTable}".offset`
const keyLimit = typeof foreignTable === 'undefined' ? 'limit' : `"${foreignTable}".limit`
this.url.searchParams.set(keyOffset, `${from}`)
Expand Down
36 changes: 36 additions & 0 deletions test/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1970,6 +1970,42 @@ Object {
}
`;

exports[`select on insert 1`] = `
Object {
"body": Array [
Object {
"status": "ONLINE",
},
],
"data": Array [
Object {
"status": "ONLINE",
},
],
"error": null,
"status": 201,
"statusText": "Created",
}
`;

exports[`select on stored procedure 1`] = `
Object {
"body": Array [
Object {
"status": "ONLINE",
},
],
"data": Array [
Object {
"status": "ONLINE",
},
],
"error": null,
"status": 200,
"statusText": "OK",
}
`;

exports[`single 1`] = `
Object {
"body": Object {
Expand Down
5 changes: 5 additions & 0 deletions test/db/00-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ RETURNS user_status AS $$
SELECT status from users WHERE username=name_param;
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION public.get_username_and_status(name_param text)
RETURNS TABLE(username text, status user_status) AS $$
SELECT username, status from users WHERE username=name_param;
$$ LANGUAGE SQL IMMUTABLE;

-- SECOND SCHEMA USERS
CREATE TYPE personal.user_status AS ENUM ('ONLINE', 'OFFLINE');
CREATE TABLE personal.users(
Expand Down
12 changes: 12 additions & 0 deletions test/transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,15 @@ test('single on insert', async () => {

await postgrest.from('users').delete().eq('username', 'foo')
})

test('select on insert', async () => {
const res = await postgrest.from('users').insert({ username: 'foo' }).select('status')
expect(res).toMatchSnapshot()

await postgrest.from('users').delete().eq('username', 'foo')
})

test('select on stored procedure', async () => {
const res = await postgrest.rpc('get_username_and_status', { name_param: 'supabot' }).select('status')
expect(res).toMatchSnapshot()
})

0 comments on commit d56d69a

Please sign in to comment.