UNPKG

@tealbase/postgres-js

Version:
514 lines 17.5 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import fetch from 'isomorphic-unfetch'; import { URL } from 'url'; /** * Base builder */ export class PostgrestBuilder { constructor(builder) { Object.assign(this, builder); } then(onfulfilled, onrejected) { // https://postgrest.org/en/stable/api.html#switching-schemas if (typeof this.schema === 'undefined') { // skip } else if (['GET', 'HEAD'].includes(this.method)) { this.headers['Accept-Profile'] = this.schema; } else { this.headers['Content-Profile'] = this.schema; } if (this.method !== 'GET' && this.method !== 'HEAD') { this.headers['Content-Type'] = 'application/json'; } return fetch(this.url.toString(), { method: this.method, headers: this.headers, body: JSON.stringify(this.body), }) .then((res) => __awaiter(this, void 0, void 0, function* () { let error, data; if (res.ok) { error = null; data = yield res.json(); } else { error = yield res.json(); data = null; } return { error, data, status: res.status, statusText: res.statusText, body: data, }; })) .then(onfulfilled, onrejected); } } /** * CRUD */ export class PostgrestQueryBuilder extends PostgrestBuilder { constructor(url, { headers = {}, schema } = {}) { super({}); this.url = new URL(url); this.headers = headers; this.schema = schema; } /** * Performs horizontal filtering with SELECT. * * @param columns The columns to retrieve, separated by commas. */ select(columns = '*') { this.method = 'GET'; // 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 new PostgrestFilterBuilder(this); } /** * Performs an INSERT into the table. * * @param values The values to insert. * @param upsert If `true`, performs an UPSERT. */ insert(values, { upsert = false } = {}) { this.method = 'POST'; this.headers['Prefer'] = upsert ? 'return=representation,resolution=merge-duplicates' : 'return=representation'; this.body = values; return this; } /** * Performs an UPDATE on the table. * * @param values The values to update. */ update(values) { this.method = 'PATCH'; this.headers['Prefer'] = 'return=representation'; this.body = values; return new PostgrestFilterBuilder(this); } /** * Performs a DELETE on the table. */ delete() { this.method = 'DELETE'; this.headers['Prefer'] = 'return=representation'; return new PostgrestFilterBuilder(this); } /** @internal */ rpc(params) { this.method = 'POST'; this.body = params; return this; } } /** * Post-filters (transforms) */ class PostgrestTransformBuilder extends PostgrestBuilder { /** * Orders the result with the specified `column`. * * @param column The column to order on. * @param ascending If `true`, the result will be in ascending order. * @param nullsFirst If `true`, `null`s appear first. * @param foreignTable The foreign table to use (if `column` is a foreign column). */ order(column, { ascending = true, nullsFirst = false, foreignTable, } = {}) { const key = typeof foreignTable === 'undefined' ? 'order' : `"${foreignTable}".order`; this.url.searchParams.set(key, `"${column}".${ascending ? 'asc' : 'desc'}.${nullsFirst ? 'nullsfirst' : 'nullslast'}`); return this; } /** * Limits the result with the specified `count`. * * @param count The maximum no. of rows to limit to. * @param foreignTable The foreign table to use (for foreign columns). */ limit(count, { foreignTable } = {}) { const key = typeof foreignTable === 'undefined' ? 'limit' : `"${foreignTable}".limit`; this.url.searchParams.set(key, `${count}`); return this; } /** * Limits the result to rows within the specified range, inclusive. * * @param from The starting index from which to limit the result, inclusive. * @param to The last index to which to limit the result, inclusive. * @param foreignTable The foreign table to use (for foreign columns). */ range(from, to, { foreignTable } = {}) { const keyOffset = typeof foreignTable === 'undefined' ? 'offset' : `"${foreignTable}".offset`; const keyLimit = typeof foreignTable === 'undefined' ? 'limit' : `"${foreignTable}".limit`; this.url.searchParams.set(keyOffset, `${from}`); // Range is inclusive, so add 1 this.url.searchParams.set(keyLimit, `${to - from + 1}`); return this; } /** * Retrieves only one row from the result. Result must be one row (e.g. using * `limit`), otherwise this will result in an error. */ single() { this.headers['Accept'] = 'application/vnd.pgrst.object+json'; return this; } } /** * Filters */ const cleanFilterArray = (filter) => filter.map((s) => `"${s}"`).join(','); class PostgrestFilterBuilder extends PostgrestTransformBuilder { /** * Finds all rows which doesn't satisfy the filter. * * @param column The column to filter on. * @param operator The operator to filter with. * @param value The value to filter with. */ not(column, operator, value) { this.url.searchParams.append(`${column}`, `not.${operator}.${value}`); return this; } /** * Finds all rows satisfying at least one of the filters. * * @param filters The filters to use, separated by commas. */ or(filters) { this.url.searchParams.append('or', `(${filters})`); return this; } /** * Finds all rows whose value on the stated `column` exactly matches the * specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ eq(column, value) { this.url.searchParams.append(`${column}`, `eq.${value}`); return this; } /** * Finds all rows whose value on the stated `column` doesn't match the * specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ neq(column, value) { this.url.searchParams.append(`${column}`, `neq.${value}`); return this; } /** * Finds all rows whose value on the stated `column` is greater than the * specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ gt(column, value) { this.url.searchParams.append(`${column}`, `gt.${value}`); return this; } /** * Finds all rows whose value on the stated `column` is greater than or * equal to the specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ gte(column, value) { this.url.searchParams.append(`${column}`, `gte.${value}`); return this; } /** * Finds all rows whose value on the stated `column` is less than the * specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ lt(column, value) { this.url.searchParams.append(`${column}`, `lt.${value}`); return this; } /** * Finds all rows whose value on the stated `column` is less than or equal * to the specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ lte(column, value) { this.url.searchParams.append(`${column}`, `lte.${value}`); return this; } /** * Finds all rows whose value in the stated `column` matches the supplied * `pattern` (case sensitive). * * @param column The column to filter on. * @param pattern The pattern to filter with. */ like(column, pattern) { this.url.searchParams.append(`${column}`, `like.${pattern}`); return this; } /** * Finds all rows whose value in the stated `column` matches the supplied * `pattern` (case insensitive). * * @param column The column to filter on. * @param pattern The pattern to filter with. */ ilike(column, pattern) { this.url.searchParams.append(`${column}`, `ilike.${pattern}`); return this; } /** * A check for exact equality (null, true, false), finds all rows whose * value on the stated `column` exactly match the specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ is(column, value) { this.url.searchParams.append(`${column}`, `is.${value}`); return this; } /** * Finds all rows whose value on the stated `column` is found on the * specified `values`. * * @param column The column to filter on. * @param values The values to filter with. */ in(column, values) { this.url.searchParams.append(`${column}`, `in.(${cleanFilterArray(values)})`); return this; } /** * Finds all rows whose json, array, or range value on the stated `column` * contains the values specified in `value`. * * @param column The column to filter on. * @param value The value to filter with. */ cs(column, value) { if (typeof value === 'string') { // range types can be inclusive '[', ']' or exclusive '(', ')' so just // keep it simple and accept a string this.url.searchParams.append(`${column}`, `cs.${value}`); } else if (Array.isArray(value)) { // array this.url.searchParams.append(`${column}`, `cs.{${cleanFilterArray(value)}}`); } else { // json this.url.searchParams.append(`${column}`, `cs.${JSON.stringify(value)}`); } return this; } /** * Finds all rows whose json, array, or range value on the stated `column` is * contained by the specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ cd(column, value) { if (typeof value === 'string') { // range this.url.searchParams.append(`${column}`, `cd.${value}`); } else if (Array.isArray(value)) { // array this.url.searchParams.append(`${column}`, `cd.{${cleanFilterArray(value)}}`); } else { // json this.url.searchParams.append(`${column}`, `cd.${JSON.stringify(value)}`); } return this; } /** * Finds all rows whose range value on the stated `column` is strictly to the * left of the specified `range`. * * @param column The column to filter on. * @param range The range to filter with. */ sl(column, range) { this.url.searchParams.append(`${column}`, `sl.${range}`); return this; } /** * Finds all rows whose range value on the stated `column` is strictly to * the right of the specified `range`. * * @param column The column to filter on. * @param range The range to filter with. */ sr(column, range) { this.url.searchParams.append(`${column}`, `sr.${range}`); return this; } /** * Finds all rows whose range value on the stated `column` does not extend * to the left of the specified `range`. * * @param column The column to filter on. * @param range The range to filter with. */ nxl(column, range) { this.url.searchParams.append(`${column}`, `nxl.${range}`); return this; } /** * Finds all rows whose range value on the stated `column` does not extend * to the right of the specified `range`. * * @param column The column to filter on. * @param range The range to filter with. */ nxr(column, range) { this.url.searchParams.append(`${column}`, `nxr.${range}`); return this; } /** * Finds all rows whose range value on the stated `column` is adjacent to * the specified `range`. * * @param column The column to filter on. * @param range The range to filter with. */ adj(column, range) { this.url.searchParams.append(`${column}`, `adj.${range}`); return this; } /** * Finds all rows whose array or range value on the stated `column` is * contained by the specified `value`. * * @param column The column to filter on. * @param value The value to filter with. */ ov(column, value) { if (typeof value === 'string') { // range this.url.searchParams.append(`${column}`, `ov.${value}`); } else { // array this.url.searchParams.append(`${column}`, `ov.{${cleanFilterArray(value)}}`); } return this; } /** * Finds all rows whose tsvector value on the stated `column` matches * to_tsquery(`query`). * * @param column The column to filter on. * @param query The Postgres tsquery string to filter with. * @param config The text search configuration to use. */ fts(column, query, { config } = {}) { const configPart = typeof config === 'undefined' ? '' : `(${config})`; this.url.searchParams.append(`${column}`, `fts${configPart}.${query}`); return this; } /** * Finds all rows whose tsvector value on the stated `column` matches * plainto_tsquery(`query`). * * @param column The column to filter on. * @param query The Postgres tsquery string to filter with. * @param config The text search configuration to use. */ plfts(column, query, { config } = {}) { const configPart = typeof config === 'undefined' ? '' : `(${config})`; this.url.searchParams.append(`${column}`, `plfts${configPart}.${query}`); return this; } /** * Finds all rows whose tsvector value on the stated `column` matches * phraseto_tsquery(`query`). * * @param column The column to filter on. * @param query The Postgres tsquery string to filter with. * @param config The text search configuration to use. */ phfts(column, query, { config } = {}) { const configPart = typeof config === 'undefined' ? '' : `(${config})`; this.url.searchParams.append(`${column}`, `phfts${configPart}.${query}`); return this; } /** * Finds all rows whose tsvector value on the stated `column` matches * websearch_to_tsquery(`query`). * * @param column The column to filter on. * @param query The Postgres tsquery string to filter with. * @param config The text search configuration to use. */ wfts(column, query, { config } = {}) { const configPart = typeof config === 'undefined' ? '' : `(${config})`; this.url.searchParams.append(`${column}`, `wfts${configPart}.${query}`); return this; } /** * Finds all rows whose `column` satisfies the filter. * * @param column The column to filter on. * @param operator The operator to filter with. * @param value The value to filter with. */ filter(column, operator, value) { this.url.searchParams.append(`${column}`, `${operator}.${value}`); return this; } /** * Finds all rows whose columns match the specified `query` object. * * @param query The object to filter with, with column names as keys mapped * to their filter values. */ match(query) { Object.keys(query).forEach((key) => { this.url.searchParams.append(`${key}`, `eq.${query[key]}`); }); return this; } } //# sourceMappingURL=builder.js.map