1367 lines
47 KiB
JavaScript
1367 lines
47 KiB
JavaScript
//#region src/PostgrestError.ts
|
|
/**
|
|
* Error format
|
|
*
|
|
* {@link https://postgrest.org/en/stable/api.html?highlight=options#errors-and-http-status-codes}
|
|
*/
|
|
var PostgrestError = class extends Error {
|
|
/**
|
|
* @example
|
|
* ```ts
|
|
* import PostgrestError from '@supabase/postgrest-js'
|
|
*
|
|
* throw new PostgrestError({
|
|
* message: 'Row level security prevented the request',
|
|
* details: 'RLS denied the insert',
|
|
* hint: 'Check your policies',
|
|
* code: 'PGRST301',
|
|
* })
|
|
* ```
|
|
*/
|
|
constructor(context) {
|
|
super(context.message);
|
|
this.name = "PostgrestError";
|
|
this.details = context.details;
|
|
this.hint = context.hint;
|
|
this.code = context.code;
|
|
}
|
|
};
|
|
|
|
//#endregion
|
|
//#region src/PostgrestBuilder.ts
|
|
var PostgrestBuilder = class {
|
|
/**
|
|
* Creates a builder configured for a specific PostgREST request.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* import PostgrestQueryBuilder from '@supabase/postgrest-js'
|
|
*
|
|
* const builder = new PostgrestQueryBuilder(
|
|
* new URL('https://xyzcompany.supabase.co/rest/v1/users'),
|
|
* { headers: new Headers({ apikey: 'public-anon-key' }) }
|
|
* )
|
|
* ```
|
|
*/
|
|
constructor(builder) {
|
|
var _builder$shouldThrowO, _builder$isMaybeSingl, _builder$urlLengthLim;
|
|
this.shouldThrowOnError = false;
|
|
this.method = builder.method;
|
|
this.url = builder.url;
|
|
this.headers = new Headers(builder.headers);
|
|
this.schema = builder.schema;
|
|
this.body = builder.body;
|
|
this.shouldThrowOnError = (_builder$shouldThrowO = builder.shouldThrowOnError) !== null && _builder$shouldThrowO !== void 0 ? _builder$shouldThrowO : false;
|
|
this.signal = builder.signal;
|
|
this.isMaybeSingle = (_builder$isMaybeSingl = builder.isMaybeSingle) !== null && _builder$isMaybeSingl !== void 0 ? _builder$isMaybeSingl : false;
|
|
this.urlLengthLimit = (_builder$urlLengthLim = builder.urlLengthLimit) !== null && _builder$urlLengthLim !== void 0 ? _builder$urlLengthLim : 8e3;
|
|
if (builder.fetch) this.fetch = builder.fetch;
|
|
else this.fetch = fetch;
|
|
}
|
|
/**
|
|
* If there's an error with the query, throwOnError will reject the promise by
|
|
* throwing the error instead of returning it as part of a successful response.
|
|
*
|
|
* {@link https://github.com/supabase/supabase-js/issues/92}
|
|
*/
|
|
throwOnError() {
|
|
this.shouldThrowOnError = true;
|
|
return this;
|
|
}
|
|
/**
|
|
* Set an HTTP header for the request.
|
|
*/
|
|
setHeader(name, value) {
|
|
this.headers = new Headers(this.headers);
|
|
this.headers.set(name, value);
|
|
return this;
|
|
}
|
|
then(onfulfilled, onrejected) {
|
|
var _this = this;
|
|
if (this.schema === void 0) {} else if (["GET", "HEAD"].includes(this.method)) this.headers.set("Accept-Profile", this.schema);
|
|
else this.headers.set("Content-Profile", this.schema);
|
|
if (this.method !== "GET" && this.method !== "HEAD") this.headers.set("Content-Type", "application/json");
|
|
const _fetch = this.fetch;
|
|
let res = _fetch(this.url.toString(), {
|
|
method: this.method,
|
|
headers: this.headers,
|
|
body: JSON.stringify(this.body),
|
|
signal: this.signal
|
|
}).then(async (res$1) => {
|
|
let error = null;
|
|
let data = null;
|
|
let count = null;
|
|
let status = res$1.status;
|
|
let statusText = res$1.statusText;
|
|
if (res$1.ok) {
|
|
var _this$headers$get2, _res$headers$get;
|
|
if (_this.method !== "HEAD") {
|
|
var _this$headers$get;
|
|
const body = await res$1.text();
|
|
if (body === "") {} else if (_this.headers.get("Accept") === "text/csv") data = body;
|
|
else if (_this.headers.get("Accept") && ((_this$headers$get = _this.headers.get("Accept")) === null || _this$headers$get === void 0 ? void 0 : _this$headers$get.includes("application/vnd.pgrst.plan+text"))) data = body;
|
|
else data = JSON.parse(body);
|
|
}
|
|
const countHeader = (_this$headers$get2 = _this.headers.get("Prefer")) === null || _this$headers$get2 === void 0 ? void 0 : _this$headers$get2.match(/count=(exact|planned|estimated)/);
|
|
const contentRange = (_res$headers$get = res$1.headers.get("content-range")) === null || _res$headers$get === void 0 ? void 0 : _res$headers$get.split("/");
|
|
if (countHeader && contentRange && contentRange.length > 1) count = parseInt(contentRange[1]);
|
|
if (_this.isMaybeSingle && _this.method === "GET" && Array.isArray(data)) if (data.length > 1) {
|
|
error = {
|
|
code: "PGRST116",
|
|
details: `Results contain ${data.length} rows, application/vnd.pgrst.object+json requires 1 row`,
|
|
hint: null,
|
|
message: "JSON object requested, multiple (or no) rows returned"
|
|
};
|
|
data = null;
|
|
count = null;
|
|
status = 406;
|
|
statusText = "Not Acceptable";
|
|
} else if (data.length === 1) data = data[0];
|
|
else data = null;
|
|
} else {
|
|
var _error$details;
|
|
const body = await res$1.text();
|
|
try {
|
|
error = JSON.parse(body);
|
|
if (Array.isArray(error) && res$1.status === 404) {
|
|
data = [];
|
|
error = null;
|
|
status = 200;
|
|
statusText = "OK";
|
|
}
|
|
} catch (_unused) {
|
|
if (res$1.status === 404 && body === "") {
|
|
status = 204;
|
|
statusText = "No Content";
|
|
} else error = { message: body };
|
|
}
|
|
if (error && _this.isMaybeSingle && (error === null || error === void 0 || (_error$details = error.details) === null || _error$details === void 0 ? void 0 : _error$details.includes("0 rows"))) {
|
|
error = null;
|
|
status = 200;
|
|
statusText = "OK";
|
|
}
|
|
if (error && _this.shouldThrowOnError) throw new PostgrestError(error);
|
|
}
|
|
return {
|
|
error,
|
|
data,
|
|
count,
|
|
status,
|
|
statusText
|
|
};
|
|
});
|
|
if (!this.shouldThrowOnError) res = res.catch((fetchError) => {
|
|
var _fetchError$name2;
|
|
let errorDetails = "";
|
|
let hint = "";
|
|
let code = "";
|
|
const cause = fetchError === null || fetchError === void 0 ? void 0 : fetchError.cause;
|
|
if (cause) {
|
|
var _cause$message, _cause$code, _fetchError$name, _cause$name;
|
|
const causeMessage = (_cause$message = cause === null || cause === void 0 ? void 0 : cause.message) !== null && _cause$message !== void 0 ? _cause$message : "";
|
|
const causeCode = (_cause$code = cause === null || cause === void 0 ? void 0 : cause.code) !== null && _cause$code !== void 0 ? _cause$code : "";
|
|
errorDetails = `${(_fetchError$name = fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) !== null && _fetchError$name !== void 0 ? _fetchError$name : "FetchError"}: ${fetchError === null || fetchError === void 0 ? void 0 : fetchError.message}`;
|
|
errorDetails += `\n\nCaused by: ${(_cause$name = cause === null || cause === void 0 ? void 0 : cause.name) !== null && _cause$name !== void 0 ? _cause$name : "Error"}: ${causeMessage}`;
|
|
if (causeCode) errorDetails += ` (${causeCode})`;
|
|
if (cause === null || cause === void 0 ? void 0 : cause.stack) errorDetails += `\n${cause.stack}`;
|
|
} else {
|
|
var _fetchError$stack;
|
|
errorDetails = (_fetchError$stack = fetchError === null || fetchError === void 0 ? void 0 : fetchError.stack) !== null && _fetchError$stack !== void 0 ? _fetchError$stack : "";
|
|
}
|
|
const urlLength = this.url.toString().length;
|
|
if ((fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) === "AbortError" || (fetchError === null || fetchError === void 0 ? void 0 : fetchError.code) === "ABORT_ERR") {
|
|
code = "";
|
|
hint = "Request was aborted (timeout or manual cancellation)";
|
|
if (urlLength > this.urlLengthLimit) hint += `. Note: Your request URL is ${urlLength} characters, which may exceed server limits. If selecting many fields, consider using views. If filtering with large arrays (e.g., .in('id', [many IDs])), consider using an RPC function to pass values server-side.`;
|
|
} else if ((cause === null || cause === void 0 ? void 0 : cause.name) === "HeadersOverflowError" || (cause === null || cause === void 0 ? void 0 : cause.code) === "UND_ERR_HEADERS_OVERFLOW") {
|
|
code = "";
|
|
hint = "HTTP headers exceeded server limits (typically 16KB)";
|
|
if (urlLength > this.urlLengthLimit) hint += `. Your request URL is ${urlLength} characters. If selecting many fields, consider using views. If filtering with large arrays (e.g., .in('id', [200+ IDs])), consider using an RPC function instead.`;
|
|
}
|
|
return {
|
|
error: {
|
|
message: `${(_fetchError$name2 = fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) !== null && _fetchError$name2 !== void 0 ? _fetchError$name2 : "FetchError"}: ${fetchError === null || fetchError === void 0 ? void 0 : fetchError.message}`,
|
|
details: errorDetails,
|
|
hint,
|
|
code
|
|
},
|
|
data: null,
|
|
count: null,
|
|
status: 0,
|
|
statusText: ""
|
|
};
|
|
});
|
|
return res.then(onfulfilled, onrejected);
|
|
}
|
|
/**
|
|
* Override the type of the returned `data`.
|
|
*
|
|
* @typeParam NewResult - The new result type to override with
|
|
* @deprecated Use overrideTypes<yourType, { merge: false }>() method at the end of your call chain instead
|
|
*/
|
|
returns() {
|
|
/* istanbul ignore next */
|
|
return this;
|
|
}
|
|
/**
|
|
* Override the type of the returned `data` field in the response.
|
|
*
|
|
* @typeParam NewResult - The new type to cast the response data to
|
|
* @typeParam Options - Optional type configuration (defaults to { merge: true })
|
|
* @typeParam Options.merge - When true, merges the new type with existing return type. When false, replaces the existing types entirely (defaults to true)
|
|
* @example
|
|
* ```typescript
|
|
* // Merge with existing types (default behavior)
|
|
* const query = supabase
|
|
* .from('users')
|
|
* .select()
|
|
* .overrideTypes<{ custom_field: string }>()
|
|
*
|
|
* // Replace existing types completely
|
|
* const replaceQuery = supabase
|
|
* .from('users')
|
|
* .select()
|
|
* .overrideTypes<{ id: number; name: string }, { merge: false }>()
|
|
* ```
|
|
* @returns A PostgrestBuilder instance with the new type
|
|
*/
|
|
overrideTypes() {
|
|
return this;
|
|
}
|
|
};
|
|
|
|
//#endregion
|
|
//#region src/PostgrestTransformBuilder.ts
|
|
var PostgrestTransformBuilder = class extends PostgrestBuilder {
|
|
/**
|
|
* Perform a SELECT on the query result.
|
|
*
|
|
* By default, `.insert()`, `.update()`, `.upsert()`, and `.delete()` do not
|
|
* return modified rows. By calling this method, modified rows are returned in
|
|
* `data`.
|
|
*
|
|
* @param columns - The columns to retrieve, separated by commas
|
|
*/
|
|
select(columns) {
|
|
let quoted = false;
|
|
const cleanedColumns = (columns !== null && columns !== void 0 ? columns : "*").split("").map((c) => {
|
|
if (/\s/.test(c) && !quoted) return "";
|
|
if (c === "\"") quoted = !quoted;
|
|
return c;
|
|
}).join("");
|
|
this.url.searchParams.set("select", cleanedColumns);
|
|
this.headers.append("Prefer", "return=representation");
|
|
return this;
|
|
}
|
|
/**
|
|
* Order the query result by `column`.
|
|
*
|
|
* You can call this method multiple times to order by multiple columns.
|
|
*
|
|
* You can order referenced tables, but it only affects the ordering of the
|
|
* parent table if you use `!inner` in the query.
|
|
*
|
|
* @param column - The column to order by
|
|
* @param options - Named parameters
|
|
* @param options.ascending - If `true`, the result will be in ascending order
|
|
* @param options.nullsFirst - If `true`, `null`s appear first. If `false`,
|
|
* `null`s appear last.
|
|
* @param options.referencedTable - Set this to order a referenced table by
|
|
* its columns
|
|
* @param options.foreignTable - Deprecated, use `options.referencedTable`
|
|
* instead
|
|
*/
|
|
order(column, { ascending = true, nullsFirst, foreignTable, referencedTable = foreignTable } = {}) {
|
|
const key = referencedTable ? `${referencedTable}.order` : "order";
|
|
const existingOrder = this.url.searchParams.get(key);
|
|
this.url.searchParams.set(key, `${existingOrder ? `${existingOrder},` : ""}${column}.${ascending ? "asc" : "desc"}${nullsFirst === void 0 ? "" : nullsFirst ? ".nullsfirst" : ".nullslast"}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Limit the query result by `count`.
|
|
*
|
|
* @param count - The maximum number of rows to return
|
|
* @param options - Named parameters
|
|
* @param options.referencedTable - Set this to limit rows of referenced
|
|
* tables instead of the parent table
|
|
* @param options.foreignTable - Deprecated, use `options.referencedTable`
|
|
* instead
|
|
*/
|
|
limit(count, { foreignTable, referencedTable = foreignTable } = {}) {
|
|
const key = typeof referencedTable === "undefined" ? "limit" : `${referencedTable}.limit`;
|
|
this.url.searchParams.set(key, `${count}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Limit the query result by starting at an offset `from` and ending at the offset `to`.
|
|
* Only records within this range are returned.
|
|
* This respects the query order and if there is no order clause the range could behave unexpectedly.
|
|
* The `from` and `to` values are 0-based and inclusive: `range(1, 3)` will include the second, third
|
|
* and fourth rows of the query.
|
|
*
|
|
* @param from - The starting index from which to limit the result
|
|
* @param to - The last index to which to limit the result
|
|
* @param options - Named parameters
|
|
* @param options.referencedTable - Set this to limit rows of referenced
|
|
* tables instead of the parent table
|
|
* @param options.foreignTable - Deprecated, use `options.referencedTable`
|
|
* instead
|
|
*/
|
|
range(from, to, { foreignTable, referencedTable = foreignTable } = {}) {
|
|
const keyOffset = typeof referencedTable === "undefined" ? "offset" : `${referencedTable}.offset`;
|
|
const keyLimit = typeof referencedTable === "undefined" ? "limit" : `${referencedTable}.limit`;
|
|
this.url.searchParams.set(keyOffset, `${from}`);
|
|
this.url.searchParams.set(keyLimit, `${to - from + 1}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Set the AbortSignal for the fetch request.
|
|
*
|
|
* @param signal - The AbortSignal to use for the fetch request
|
|
*/
|
|
abortSignal(signal) {
|
|
this.signal = signal;
|
|
return this;
|
|
}
|
|
/**
|
|
* Return `data` as a single object instead of an array of objects.
|
|
*
|
|
* Query result must be one row (e.g. using `.limit(1)`), otherwise this
|
|
* returns an error.
|
|
*/
|
|
single() {
|
|
this.headers.set("Accept", "application/vnd.pgrst.object+json");
|
|
return this;
|
|
}
|
|
/**
|
|
* Return `data` as a single object instead of an array of objects.
|
|
*
|
|
* Query result must be zero or one row (e.g. using `.limit(1)`), otherwise
|
|
* this returns an error.
|
|
*/
|
|
maybeSingle() {
|
|
if (this.method === "GET") this.headers.set("Accept", "application/json");
|
|
else this.headers.set("Accept", "application/vnd.pgrst.object+json");
|
|
this.isMaybeSingle = true;
|
|
return this;
|
|
}
|
|
/**
|
|
* Return `data` as a string in CSV format.
|
|
*/
|
|
csv() {
|
|
this.headers.set("Accept", "text/csv");
|
|
return this;
|
|
}
|
|
/**
|
|
* Return `data` as an object in [GeoJSON](https://geojson.org) format.
|
|
*/
|
|
geojson() {
|
|
this.headers.set("Accept", "application/geo+json");
|
|
return this;
|
|
}
|
|
/**
|
|
* Return `data` as the EXPLAIN plan for the query.
|
|
*
|
|
* You need to enable the
|
|
* [db_plan_enabled](https://supabase.com/docs/guides/database/debugging-performance#enabling-explain)
|
|
* setting before using this method.
|
|
*
|
|
* @param options - Named parameters
|
|
*
|
|
* @param options.analyze - If `true`, the query will be executed and the
|
|
* actual run time will be returned
|
|
*
|
|
* @param options.verbose - If `true`, the query identifier will be returned
|
|
* and `data` will include the output columns of the query
|
|
*
|
|
* @param options.settings - If `true`, include information on configuration
|
|
* parameters that affect query planning
|
|
*
|
|
* @param options.buffers - If `true`, include information on buffer usage
|
|
*
|
|
* @param options.wal - If `true`, include information on WAL record generation
|
|
*
|
|
* @param options.format - The format of the output, can be `"text"` (default)
|
|
* or `"json"`
|
|
*/
|
|
explain({ analyze = false, verbose = false, settings = false, buffers = false, wal = false, format = "text" } = {}) {
|
|
var _this$headers$get;
|
|
const options = [
|
|
analyze ? "analyze" : null,
|
|
verbose ? "verbose" : null,
|
|
settings ? "settings" : null,
|
|
buffers ? "buffers" : null,
|
|
wal ? "wal" : null
|
|
].filter(Boolean).join("|");
|
|
const forMediatype = (_this$headers$get = this.headers.get("Accept")) !== null && _this$headers$get !== void 0 ? _this$headers$get : "application/json";
|
|
this.headers.set("Accept", `application/vnd.pgrst.plan+${format}; for="${forMediatype}"; options=${options};`);
|
|
if (format === "json") return this;
|
|
else return this;
|
|
}
|
|
/**
|
|
* Rollback the query.
|
|
*
|
|
* `data` will still be returned, but the query is not committed.
|
|
*/
|
|
rollback() {
|
|
this.headers.append("Prefer", "tx=rollback");
|
|
return this;
|
|
}
|
|
/**
|
|
* Override the type of the returned `data`.
|
|
*
|
|
* @typeParam NewResult - The new result type to override with
|
|
* @deprecated Use overrideTypes<yourType, { merge: false }>() method at the end of your call chain instead
|
|
*/
|
|
returns() {
|
|
return this;
|
|
}
|
|
/**
|
|
* Set the maximum number of rows that can be affected by the query.
|
|
* Only available in PostgREST v13+ and only works with PATCH and DELETE methods.
|
|
*
|
|
* @param value - The maximum number of rows that can be affected
|
|
*/
|
|
maxAffected(value) {
|
|
this.headers.append("Prefer", "handling=strict");
|
|
this.headers.append("Prefer", `max-affected=${value}`);
|
|
return this;
|
|
}
|
|
};
|
|
|
|
//#endregion
|
|
//#region src/PostgrestFilterBuilder.ts
|
|
const PostgrestReservedCharsRegexp = /* @__PURE__ */ new RegExp("[,()]");
|
|
var PostgrestFilterBuilder = class extends PostgrestTransformBuilder {
|
|
/**
|
|
* Match only rows where `column` is equal to `value`.
|
|
*
|
|
* To check if the value of `column` is NULL, you should use `.is()` instead.
|
|
*
|
|
* @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;
|
|
}
|
|
/**
|
|
* Match only rows where `column` is not equal to `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;
|
|
}
|
|
/**
|
|
* Match only rows where `column` is greater than `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;
|
|
}
|
|
/**
|
|
* Match only rows where `column` is greater than or equal to `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;
|
|
}
|
|
/**
|
|
* Match only rows where `column` is less than `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;
|
|
}
|
|
/**
|
|
* Match only rows where `column` is less than or equal to `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;
|
|
}
|
|
/**
|
|
* Match only rows where `column` matches `pattern` case-sensitively.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param pattern - The pattern to match with
|
|
*/
|
|
like(column, pattern) {
|
|
this.url.searchParams.append(column, `like.${pattern}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` matches all of `patterns` case-sensitively.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param patterns - The patterns to match with
|
|
*/
|
|
likeAllOf(column, patterns) {
|
|
this.url.searchParams.append(column, `like(all).{${patterns.join(",")}}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` matches any of `patterns` case-sensitively.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param patterns - The patterns to match with
|
|
*/
|
|
likeAnyOf(column, patterns) {
|
|
this.url.searchParams.append(column, `like(any).{${patterns.join(",")}}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` matches `pattern` case-insensitively.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param pattern - The pattern to match with
|
|
*/
|
|
ilike(column, pattern) {
|
|
this.url.searchParams.append(column, `ilike.${pattern}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` matches all of `patterns` case-insensitively.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param patterns - The patterns to match with
|
|
*/
|
|
ilikeAllOf(column, patterns) {
|
|
this.url.searchParams.append(column, `ilike(all).{${patterns.join(",")}}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` matches any of `patterns` case-insensitively.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param patterns - The patterns to match with
|
|
*/
|
|
ilikeAnyOf(column, patterns) {
|
|
this.url.searchParams.append(column, `ilike(any).{${patterns.join(",")}}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` matches the PostgreSQL regex `pattern`
|
|
* case-sensitively (using the `~` operator).
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param pattern - The PostgreSQL regular expression pattern to match with
|
|
*/
|
|
regexMatch(column, pattern) {
|
|
this.url.searchParams.append(column, `match.${pattern}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` matches the PostgreSQL regex `pattern`
|
|
* case-insensitively (using the `~*` operator).
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param pattern - The PostgreSQL regular expression pattern to match with
|
|
*/
|
|
regexIMatch(column, pattern) {
|
|
this.url.searchParams.append(column, `imatch.${pattern}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` IS `value`.
|
|
*
|
|
* For non-boolean columns, this is only relevant for checking if the value of
|
|
* `column` is NULL by setting `value` to `null`.
|
|
*
|
|
* For boolean columns, you can also set `value` to `true` or `false` and it
|
|
* will behave the same way as `.eq()`.
|
|
*
|
|
* @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;
|
|
}
|
|
/**
|
|
* Match only rows where `column` IS DISTINCT FROM `value`.
|
|
*
|
|
* Unlike `.neq()`, this treats `NULL` as a comparable value. Two `NULL` values
|
|
* are considered equal (not distinct), and comparing `NULL` with any non-NULL
|
|
* value returns true (distinct).
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param value - The value to filter with
|
|
*/
|
|
isDistinct(column, value) {
|
|
this.url.searchParams.append(column, `isdistinct.${value}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` is included in the `values` array.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param values - The values array to filter with
|
|
*/
|
|
in(column, values) {
|
|
const cleanedValues = Array.from(new Set(values)).map((s) => {
|
|
if (typeof s === "string" && PostgrestReservedCharsRegexp.test(s)) return `"${s}"`;
|
|
else return `${s}`;
|
|
}).join(",");
|
|
this.url.searchParams.append(column, `in.(${cleanedValues})`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where `column` is NOT included in the `values` array.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param values - The values array to filter with
|
|
*/
|
|
notIn(column, values) {
|
|
const cleanedValues = Array.from(new Set(values)).map((s) => {
|
|
if (typeof s === "string" && PostgrestReservedCharsRegexp.test(s)) return `"${s}"`;
|
|
else return `${s}`;
|
|
}).join(",");
|
|
this.url.searchParams.append(column, `not.in.(${cleanedValues})`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for jsonb, array, and range columns. Match only rows where
|
|
* `column` contains every element appearing in `value`.
|
|
*
|
|
* @param column - The jsonb, array, or range column to filter on
|
|
* @param value - The jsonb, array, or range value to filter with
|
|
*/
|
|
contains(column, value) {
|
|
if (typeof value === "string") this.url.searchParams.append(column, `cs.${value}`);
|
|
else if (Array.isArray(value)) this.url.searchParams.append(column, `cs.{${value.join(",")}}`);
|
|
else this.url.searchParams.append(column, `cs.${JSON.stringify(value)}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for jsonb, array, and range columns. Match only rows where
|
|
* every element appearing in `column` is contained by `value`.
|
|
*
|
|
* @param column - The jsonb, array, or range column to filter on
|
|
* @param value - The jsonb, array, or range value to filter with
|
|
*/
|
|
containedBy(column, value) {
|
|
if (typeof value === "string") this.url.searchParams.append(column, `cd.${value}`);
|
|
else if (Array.isArray(value)) this.url.searchParams.append(column, `cd.{${value.join(",")}}`);
|
|
else this.url.searchParams.append(column, `cd.${JSON.stringify(value)}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for range columns. Match only rows where every element in
|
|
* `column` is greater than any element in `range`.
|
|
*
|
|
* @param column - The range column to filter on
|
|
* @param range - The range to filter with
|
|
*/
|
|
rangeGt(column, range) {
|
|
this.url.searchParams.append(column, `sr.${range}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for range columns. Match only rows where every element in
|
|
* `column` is either contained in `range` or greater than any element in
|
|
* `range`.
|
|
*
|
|
* @param column - The range column to filter on
|
|
* @param range - The range to filter with
|
|
*/
|
|
rangeGte(column, range) {
|
|
this.url.searchParams.append(column, `nxl.${range}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for range columns. Match only rows where every element in
|
|
* `column` is less than any element in `range`.
|
|
*
|
|
* @param column - The range column to filter on
|
|
* @param range - The range to filter with
|
|
*/
|
|
rangeLt(column, range) {
|
|
this.url.searchParams.append(column, `sl.${range}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for range columns. Match only rows where every element in
|
|
* `column` is either contained in `range` or less than any element in
|
|
* `range`.
|
|
*
|
|
* @param column - The range column to filter on
|
|
* @param range - The range to filter with
|
|
*/
|
|
rangeLte(column, range) {
|
|
this.url.searchParams.append(column, `nxr.${range}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for range columns. Match only rows where `column` is
|
|
* mutually exclusive to `range` and there can be no element between the two
|
|
* ranges.
|
|
*
|
|
* @param column - The range column to filter on
|
|
* @param range - The range to filter with
|
|
*/
|
|
rangeAdjacent(column, range) {
|
|
this.url.searchParams.append(column, `adj.${range}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for array and range columns. Match only rows where
|
|
* `column` and `value` have an element in common.
|
|
*
|
|
* @param column - The array or range column to filter on
|
|
* @param value - The array or range value to filter with
|
|
*/
|
|
overlaps(column, value) {
|
|
if (typeof value === "string") this.url.searchParams.append(column, `ov.${value}`);
|
|
else this.url.searchParams.append(column, `ov.{${value.join(",")}}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Only relevant for text and tsvector columns. Match only rows where
|
|
* `column` matches the query string in `query`.
|
|
*
|
|
* @param column - The text or tsvector column to filter on
|
|
* @param query - The query text to match with
|
|
* @param options - Named parameters
|
|
* @param options.config - The text search configuration to use
|
|
* @param options.type - Change how the `query` text is interpreted
|
|
*/
|
|
textSearch(column, query, { config, type } = {}) {
|
|
let typePart = "";
|
|
if (type === "plain") typePart = "pl";
|
|
else if (type === "phrase") typePart = "ph";
|
|
else if (type === "websearch") typePart = "w";
|
|
const configPart = config === void 0 ? "" : `(${config})`;
|
|
this.url.searchParams.append(column, `${typePart}fts${configPart}.${query}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows where each column in `query` keys is equal to its
|
|
* associated value. Shorthand for multiple `.eq()`s.
|
|
*
|
|
* @param query - The object to filter with, with column names as keys mapped
|
|
* to their filter values
|
|
*/
|
|
match(query) {
|
|
Object.entries(query).forEach(([column, value]) => {
|
|
this.url.searchParams.append(column, `eq.${value}`);
|
|
});
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows which doesn't satisfy the filter.
|
|
*
|
|
* Unlike most filters, `opearator` and `value` are used as-is and need to
|
|
* follow [PostgREST
|
|
* syntax](https://postgrest.org/en/stable/api.html#operators). You also need
|
|
* to make sure they are properly sanitized.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param operator - The operator to be negated to filter with, following
|
|
* PostgREST syntax
|
|
* @param value - The value to filter with, following PostgREST syntax
|
|
*/
|
|
not(column, operator, value) {
|
|
this.url.searchParams.append(column, `not.${operator}.${value}`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows which satisfy at least one of the filters.
|
|
*
|
|
* Unlike most filters, `filters` is used as-is and needs to follow [PostgREST
|
|
* syntax](https://postgrest.org/en/stable/api.html#operators). You also need
|
|
* to make sure it's properly sanitized.
|
|
*
|
|
* It's currently not possible to do an `.or()` filter across multiple tables.
|
|
*
|
|
* @param filters - The filters to use, following PostgREST syntax
|
|
* @param options - Named parameters
|
|
* @param options.referencedTable - Set this to filter on referenced tables
|
|
* instead of the parent table
|
|
* @param options.foreignTable - Deprecated, use `referencedTable` instead
|
|
*/
|
|
or(filters, { foreignTable, referencedTable = foreignTable } = {}) {
|
|
const key = referencedTable ? `${referencedTable}.or` : "or";
|
|
this.url.searchParams.append(key, `(${filters})`);
|
|
return this;
|
|
}
|
|
/**
|
|
* Match only rows which satisfy the filter. This is an escape hatch - you
|
|
* should use the specific filter methods wherever possible.
|
|
*
|
|
* Unlike most filters, `opearator` and `value` are used as-is and need to
|
|
* follow [PostgREST
|
|
* syntax](https://postgrest.org/en/stable/api.html#operators). You also need
|
|
* to make sure they are properly sanitized.
|
|
*
|
|
* @param column - The column to filter on
|
|
* @param operator - The operator to filter with, following PostgREST syntax
|
|
* @param value - The value to filter with, following PostgREST syntax
|
|
*/
|
|
filter(column, operator, value) {
|
|
this.url.searchParams.append(column, `${operator}.${value}`);
|
|
return this;
|
|
}
|
|
};
|
|
|
|
//#endregion
|
|
//#region src/PostgrestQueryBuilder.ts
|
|
var PostgrestQueryBuilder = class {
|
|
/**
|
|
* Creates a query builder scoped to a Postgres table or view.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* import PostgrestQueryBuilder from '@supabase/postgrest-js'
|
|
*
|
|
* const query = new PostgrestQueryBuilder(
|
|
* new URL('https://xyzcompany.supabase.co/rest/v1/users'),
|
|
* { headers: { apikey: 'public-anon-key' } }
|
|
* )
|
|
* ```
|
|
*/
|
|
constructor(url, { headers = {}, schema, fetch: fetch$1, urlLengthLimit = 8e3 }) {
|
|
this.url = url;
|
|
this.headers = new Headers(headers);
|
|
this.schema = schema;
|
|
this.fetch = fetch$1;
|
|
this.urlLengthLimit = urlLengthLimit;
|
|
}
|
|
/**
|
|
* Clone URL and headers to prevent shared state between operations.
|
|
*/
|
|
cloneRequestState() {
|
|
return {
|
|
url: new URL(this.url.toString()),
|
|
headers: new Headers(this.headers)
|
|
};
|
|
}
|
|
/**
|
|
* Perform a SELECT query on the table or view.
|
|
*
|
|
* @param columns - The columns to retrieve, separated by commas. Columns can be renamed when returned with `customName:columnName`
|
|
*
|
|
* @param options - Named parameters
|
|
*
|
|
* @param options.head - When set to `true`, `data` will not be returned.
|
|
* Useful if you only need the count.
|
|
*
|
|
* @param options.count - Count algorithm to use to count rows in the table or view.
|
|
*
|
|
* `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the
|
|
* hood.
|
|
*
|
|
* `"planned"`: Approximated but fast count algorithm. Uses the Postgres
|
|
* statistics under the hood.
|
|
*
|
|
* `"estimated"`: Uses exact count for low numbers and planned count for high
|
|
* numbers.
|
|
*
|
|
* @remarks
|
|
* When using `count` with `.range()` or `.limit()`, the returned `count` is the total number of rows
|
|
* that match your filters, not the number of rows in the current page. Use this to build pagination UI.
|
|
*/
|
|
select(columns, options) {
|
|
const { head = false, count } = options !== null && options !== void 0 ? options : {};
|
|
const method = head ? "HEAD" : "GET";
|
|
let quoted = false;
|
|
const cleanedColumns = (columns !== null && columns !== void 0 ? columns : "*").split("").map((c) => {
|
|
if (/\s/.test(c) && !quoted) return "";
|
|
if (c === "\"") quoted = !quoted;
|
|
return c;
|
|
}).join("");
|
|
const { url, headers } = this.cloneRequestState();
|
|
url.searchParams.set("select", cleanedColumns);
|
|
if (count) headers.append("Prefer", `count=${count}`);
|
|
return new PostgrestFilterBuilder({
|
|
method,
|
|
url,
|
|
headers,
|
|
schema: this.schema,
|
|
fetch: this.fetch,
|
|
urlLengthLimit: this.urlLengthLimit
|
|
});
|
|
}
|
|
/**
|
|
* Perform an INSERT into the table or view.
|
|
*
|
|
* By default, inserted rows are not returned. To return it, chain the call
|
|
* with `.select()`.
|
|
*
|
|
* @param values - The values to insert. Pass an object to insert a single row
|
|
* or an array to insert multiple rows.
|
|
*
|
|
* @param options - Named parameters
|
|
*
|
|
* @param options.count - Count algorithm to use to count inserted rows.
|
|
*
|
|
* `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the
|
|
* hood.
|
|
*
|
|
* `"planned"`: Approximated but fast count algorithm. Uses the Postgres
|
|
* statistics under the hood.
|
|
*
|
|
* `"estimated"`: Uses exact count for low numbers and planned count for high
|
|
* numbers.
|
|
*
|
|
* @param options.defaultToNull - Make missing fields default to `null`.
|
|
* Otherwise, use the default value for the column. Only applies for bulk
|
|
* inserts.
|
|
*/
|
|
insert(values, { count, defaultToNull = true } = {}) {
|
|
var _this$fetch;
|
|
const method = "POST";
|
|
const { url, headers } = this.cloneRequestState();
|
|
if (count) headers.append("Prefer", `count=${count}`);
|
|
if (!defaultToNull) headers.append("Prefer", `missing=default`);
|
|
if (Array.isArray(values)) {
|
|
const columns = values.reduce((acc, x) => acc.concat(Object.keys(x)), []);
|
|
if (columns.length > 0) {
|
|
const uniqueColumns = [...new Set(columns)].map((column) => `"${column}"`);
|
|
url.searchParams.set("columns", uniqueColumns.join(","));
|
|
}
|
|
}
|
|
return new PostgrestFilterBuilder({
|
|
method,
|
|
url,
|
|
headers,
|
|
schema: this.schema,
|
|
body: values,
|
|
fetch: (_this$fetch = this.fetch) !== null && _this$fetch !== void 0 ? _this$fetch : fetch,
|
|
urlLengthLimit: this.urlLengthLimit
|
|
});
|
|
}
|
|
/**
|
|
* Perform an UPSERT on the table or view. Depending on the column(s) passed
|
|
* to `onConflict`, `.upsert()` allows you to perform the equivalent of
|
|
* `.insert()` if a row with the corresponding `onConflict` columns doesn't
|
|
* exist, or if it does exist, perform an alternative action depending on
|
|
* `ignoreDuplicates`.
|
|
*
|
|
* By default, upserted rows are not returned. To return it, chain the call
|
|
* with `.select()`.
|
|
*
|
|
* @param values - The values to upsert with. Pass an object to upsert a
|
|
* single row or an array to upsert multiple rows.
|
|
*
|
|
* @param options - Named parameters
|
|
*
|
|
* @param options.onConflict - Comma-separated UNIQUE column(s) to specify how
|
|
* duplicate rows are determined. Two rows are duplicates if all the
|
|
* `onConflict` columns are equal.
|
|
*
|
|
* @param options.ignoreDuplicates - If `true`, duplicate rows are ignored. If
|
|
* `false`, duplicate rows are merged with existing rows.
|
|
*
|
|
* @param options.count - Count algorithm to use to count upserted rows.
|
|
*
|
|
* `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the
|
|
* hood.
|
|
*
|
|
* `"planned"`: Approximated but fast count algorithm. Uses the Postgres
|
|
* statistics under the hood.
|
|
*
|
|
* `"estimated"`: Uses exact count for low numbers and planned count for high
|
|
* numbers.
|
|
*
|
|
* @param options.defaultToNull - Make missing fields default to `null`.
|
|
* Otherwise, use the default value for the column. This only applies when
|
|
* inserting new rows, not when merging with existing rows under
|
|
* `ignoreDuplicates: false`. This also only applies when doing bulk upserts.
|
|
*
|
|
* @example Upsert a single row using a unique key
|
|
* ```ts
|
|
* // Upserting a single row, overwriting based on the 'username' unique column
|
|
* const { data, error } = await supabase
|
|
* .from('users')
|
|
* .upsert({ username: 'supabot' }, { onConflict: 'username' })
|
|
*
|
|
* // Example response:
|
|
* // {
|
|
* // data: [
|
|
* // { id: 4, message: 'bar', username: 'supabot' }
|
|
* // ],
|
|
* // error: null
|
|
* // }
|
|
* ```
|
|
*
|
|
* @example Upsert with conflict resolution and exact row counting
|
|
* ```ts
|
|
* // Upserting and returning exact count
|
|
* const { data, error, count } = await supabase
|
|
* .from('users')
|
|
* .upsert(
|
|
* {
|
|
* id: 3,
|
|
* message: 'foo',
|
|
* username: 'supabot'
|
|
* },
|
|
* {
|
|
* onConflict: 'username',
|
|
* count: 'exact'
|
|
* }
|
|
* )
|
|
*
|
|
* // Example response:
|
|
* // {
|
|
* // data: [
|
|
* // {
|
|
* // id: 42,
|
|
* // handle: "saoirse",
|
|
* // display_name: "Saoirse"
|
|
* // }
|
|
* // ],
|
|
* // count: 1,
|
|
* // error: null
|
|
* // }
|
|
* ```
|
|
*/
|
|
upsert(values, { onConflict, ignoreDuplicates = false, count, defaultToNull = true } = {}) {
|
|
var _this$fetch2;
|
|
const method = "POST";
|
|
const { url, headers } = this.cloneRequestState();
|
|
headers.append("Prefer", `resolution=${ignoreDuplicates ? "ignore" : "merge"}-duplicates`);
|
|
if (onConflict !== void 0) url.searchParams.set("on_conflict", onConflict);
|
|
if (count) headers.append("Prefer", `count=${count}`);
|
|
if (!defaultToNull) headers.append("Prefer", "missing=default");
|
|
if (Array.isArray(values)) {
|
|
const columns = values.reduce((acc, x) => acc.concat(Object.keys(x)), []);
|
|
if (columns.length > 0) {
|
|
const uniqueColumns = [...new Set(columns)].map((column) => `"${column}"`);
|
|
url.searchParams.set("columns", uniqueColumns.join(","));
|
|
}
|
|
}
|
|
return new PostgrestFilterBuilder({
|
|
method,
|
|
url,
|
|
headers,
|
|
schema: this.schema,
|
|
body: values,
|
|
fetch: (_this$fetch2 = this.fetch) !== null && _this$fetch2 !== void 0 ? _this$fetch2 : fetch,
|
|
urlLengthLimit: this.urlLengthLimit
|
|
});
|
|
}
|
|
/**
|
|
* Perform an UPDATE on the table or view.
|
|
*
|
|
* By default, updated rows are not returned. To return it, chain the call
|
|
* with `.select()` after filters.
|
|
*
|
|
* @param values - The values to update with
|
|
*
|
|
* @param options - Named parameters
|
|
*
|
|
* @param options.count - Count algorithm to use to count updated rows.
|
|
*
|
|
* `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the
|
|
* hood.
|
|
*
|
|
* `"planned"`: Approximated but fast count algorithm. Uses the Postgres
|
|
* statistics under the hood.
|
|
*
|
|
* `"estimated"`: Uses exact count for low numbers and planned count for high
|
|
* numbers.
|
|
*/
|
|
update(values, { count } = {}) {
|
|
var _this$fetch3;
|
|
const method = "PATCH";
|
|
const { url, headers } = this.cloneRequestState();
|
|
if (count) headers.append("Prefer", `count=${count}`);
|
|
return new PostgrestFilterBuilder({
|
|
method,
|
|
url,
|
|
headers,
|
|
schema: this.schema,
|
|
body: values,
|
|
fetch: (_this$fetch3 = this.fetch) !== null && _this$fetch3 !== void 0 ? _this$fetch3 : fetch,
|
|
urlLengthLimit: this.urlLengthLimit
|
|
});
|
|
}
|
|
/**
|
|
* Perform a DELETE on the table or view.
|
|
*
|
|
* By default, deleted rows are not returned. To return it, chain the call
|
|
* with `.select()` after filters.
|
|
*
|
|
* @param options - Named parameters
|
|
*
|
|
* @param options.count - Count algorithm to use to count deleted rows.
|
|
*
|
|
* `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the
|
|
* hood.
|
|
*
|
|
* `"planned"`: Approximated but fast count algorithm. Uses the Postgres
|
|
* statistics under the hood.
|
|
*
|
|
* `"estimated"`: Uses exact count for low numbers and planned count for high
|
|
* numbers.
|
|
*/
|
|
delete({ count } = {}) {
|
|
var _this$fetch4;
|
|
const method = "DELETE";
|
|
const { url, headers } = this.cloneRequestState();
|
|
if (count) headers.append("Prefer", `count=${count}`);
|
|
return new PostgrestFilterBuilder({
|
|
method,
|
|
url,
|
|
headers,
|
|
schema: this.schema,
|
|
fetch: (_this$fetch4 = this.fetch) !== null && _this$fetch4 !== void 0 ? _this$fetch4 : fetch,
|
|
urlLengthLimit: this.urlLengthLimit
|
|
});
|
|
}
|
|
};
|
|
|
|
//#endregion
|
|
//#region \0@oxc-project+runtime@0.101.0/helpers/typeof.js
|
|
function _typeof(o) {
|
|
"@babel/helpers - typeof";
|
|
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
|
|
return typeof o$1;
|
|
} : function(o$1) {
|
|
return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
|
|
}, _typeof(o);
|
|
}
|
|
|
|
//#endregion
|
|
//#region \0@oxc-project+runtime@0.101.0/helpers/toPrimitive.js
|
|
function toPrimitive(t, r) {
|
|
if ("object" != _typeof(t) || !t) return t;
|
|
var e = t[Symbol.toPrimitive];
|
|
if (void 0 !== e) {
|
|
var i = e.call(t, r || "default");
|
|
if ("object" != _typeof(i)) return i;
|
|
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
}
|
|
return ("string" === r ? String : Number)(t);
|
|
}
|
|
|
|
//#endregion
|
|
//#region \0@oxc-project+runtime@0.101.0/helpers/toPropertyKey.js
|
|
function toPropertyKey(t) {
|
|
var i = toPrimitive(t, "string");
|
|
return "symbol" == _typeof(i) ? i : i + "";
|
|
}
|
|
|
|
//#endregion
|
|
//#region \0@oxc-project+runtime@0.101.0/helpers/defineProperty.js
|
|
function _defineProperty(e, r, t) {
|
|
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
value: t,
|
|
enumerable: !0,
|
|
configurable: !0,
|
|
writable: !0
|
|
}) : e[r] = t, e;
|
|
}
|
|
|
|
//#endregion
|
|
//#region \0@oxc-project+runtime@0.101.0/helpers/objectSpread2.js
|
|
function ownKeys(e, r) {
|
|
var t = Object.keys(e);
|
|
if (Object.getOwnPropertySymbols) {
|
|
var o = Object.getOwnPropertySymbols(e);
|
|
r && (o = o.filter(function(r$1) {
|
|
return Object.getOwnPropertyDescriptor(e, r$1).enumerable;
|
|
})), t.push.apply(t, o);
|
|
}
|
|
return t;
|
|
}
|
|
function _objectSpread2(e) {
|
|
for (var r = 1; r < arguments.length; r++) {
|
|
var t = null != arguments[r] ? arguments[r] : {};
|
|
r % 2 ? ownKeys(Object(t), !0).forEach(function(r$1) {
|
|
_defineProperty(e, r$1, t[r$1]);
|
|
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r$1) {
|
|
Object.defineProperty(e, r$1, Object.getOwnPropertyDescriptor(t, r$1));
|
|
});
|
|
}
|
|
return e;
|
|
}
|
|
|
|
//#endregion
|
|
//#region src/PostgrestClient.ts
|
|
/**
|
|
* PostgREST client.
|
|
*
|
|
* @typeParam Database - Types for the schema from the [type
|
|
* generator](https://supabase.com/docs/reference/javascript/next/typescript-support)
|
|
*
|
|
* @typeParam SchemaName - Postgres schema to switch to. Must be a string
|
|
* literal, the same one passed to the constructor. If the schema is not
|
|
* `"public"`, this must be supplied manually.
|
|
*/
|
|
var PostgrestClient = class PostgrestClient {
|
|
/**
|
|
* Creates a PostgREST client.
|
|
*
|
|
* @param url - URL of the PostgREST endpoint
|
|
* @param options - Named parameters
|
|
* @param options.headers - Custom headers
|
|
* @param options.schema - Postgres schema to switch to
|
|
* @param options.fetch - Custom fetch
|
|
* @param options.timeout - Optional timeout in milliseconds for all requests. When set, requests will automatically abort after this duration to prevent indefinite hangs.
|
|
* @param options.urlLengthLimit - Maximum URL length in characters before warnings/errors are triggered. Defaults to 8000.
|
|
* @example
|
|
* ```ts
|
|
* import PostgrestClient from '@supabase/postgrest-js'
|
|
*
|
|
* const postgrest = new PostgrestClient('https://xyzcompany.supabase.co/rest/v1', {
|
|
* headers: { apikey: 'public-anon-key' },
|
|
* schema: 'public',
|
|
* timeout: 30000, // 30 second timeout
|
|
* })
|
|
* ```
|
|
*/
|
|
constructor(url, { headers = {}, schema, fetch: fetch$1, timeout, urlLengthLimit = 8e3 } = {}) {
|
|
this.url = url;
|
|
this.headers = new Headers(headers);
|
|
this.schemaName = schema;
|
|
this.urlLengthLimit = urlLengthLimit;
|
|
const originalFetch = fetch$1 !== null && fetch$1 !== void 0 ? fetch$1 : globalThis.fetch;
|
|
if (timeout !== void 0 && timeout > 0) this.fetch = (input, init) => {
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
const existingSignal = init === null || init === void 0 ? void 0 : init.signal;
|
|
if (existingSignal) {
|
|
if (existingSignal.aborted) {
|
|
clearTimeout(timeoutId);
|
|
return originalFetch(input, init);
|
|
}
|
|
const abortHandler = () => {
|
|
clearTimeout(timeoutId);
|
|
controller.abort();
|
|
};
|
|
existingSignal.addEventListener("abort", abortHandler, { once: true });
|
|
return originalFetch(input, _objectSpread2(_objectSpread2({}, init), {}, { signal: controller.signal })).finally(() => {
|
|
clearTimeout(timeoutId);
|
|
existingSignal.removeEventListener("abort", abortHandler);
|
|
});
|
|
}
|
|
return originalFetch(input, _objectSpread2(_objectSpread2({}, init), {}, { signal: controller.signal })).finally(() => clearTimeout(timeoutId));
|
|
};
|
|
else this.fetch = originalFetch;
|
|
}
|
|
/**
|
|
* Perform a query on a table or a view.
|
|
*
|
|
* @param relation - The table or view name to query
|
|
*/
|
|
from(relation) {
|
|
if (!relation || typeof relation !== "string" || relation.trim() === "") throw new Error("Invalid relation name: relation must be a non-empty string.");
|
|
return new PostgrestQueryBuilder(new URL(`${this.url}/${relation}`), {
|
|
headers: new Headers(this.headers),
|
|
schema: this.schemaName,
|
|
fetch: this.fetch,
|
|
urlLengthLimit: this.urlLengthLimit
|
|
});
|
|
}
|
|
/**
|
|
* Select a schema to query or perform an function (rpc) call.
|
|
*
|
|
* The schema needs to be on the list of exposed schemas inside Supabase.
|
|
*
|
|
* @param schema - The schema to query
|
|
*/
|
|
schema(schema) {
|
|
return new PostgrestClient(this.url, {
|
|
headers: this.headers,
|
|
schema,
|
|
fetch: this.fetch,
|
|
urlLengthLimit: this.urlLengthLimit
|
|
});
|
|
}
|
|
/**
|
|
* Perform a function call.
|
|
*
|
|
* @param fn - The function name to call
|
|
* @param args - The arguments to pass to the function call
|
|
* @param options - Named parameters
|
|
* @param options.head - When set to `true`, `data` will not be returned.
|
|
* Useful if you only need the count.
|
|
* @param options.get - When set to `true`, the function will be called with
|
|
* read-only access mode.
|
|
* @param options.count - Count algorithm to use to count rows returned by the
|
|
* function. Only applicable for [set-returning
|
|
* functions](https://www.postgresql.org/docs/current/functions-srf.html).
|
|
*
|
|
* `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the
|
|
* hood.
|
|
*
|
|
* `"planned"`: Approximated but fast count algorithm. Uses the Postgres
|
|
* statistics under the hood.
|
|
*
|
|
* `"estimated"`: Uses exact count for low numbers and planned count for high
|
|
* numbers.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* // For cross-schema functions where type inference fails, use overrideTypes:
|
|
* const { data } = await supabase
|
|
* .schema('schema_b')
|
|
* .rpc('function_a', {})
|
|
* .overrideTypes<{ id: string; user_id: string }[]>()
|
|
* ```
|
|
*/
|
|
rpc(fn, args = {}, { head = false, get = false, count } = {}) {
|
|
var _this$fetch;
|
|
let method;
|
|
const url = new URL(`${this.url}/rpc/${fn}`);
|
|
let body;
|
|
const _isObject = (v) => v !== null && typeof v === "object" && (!Array.isArray(v) || v.some(_isObject));
|
|
const _hasObjectArg = head && Object.values(args).some(_isObject);
|
|
if (_hasObjectArg) {
|
|
method = "POST";
|
|
body = args;
|
|
} else if (head || get) {
|
|
method = head ? "HEAD" : "GET";
|
|
Object.entries(args).filter(([_, value]) => value !== void 0).map(([name, value]) => [name, Array.isArray(value) ? `{${value.join(",")}}` : `${value}`]).forEach(([name, value]) => {
|
|
url.searchParams.append(name, value);
|
|
});
|
|
} else {
|
|
method = "POST";
|
|
body = args;
|
|
}
|
|
const headers = new Headers(this.headers);
|
|
if (_hasObjectArg) headers.set("Prefer", count ? `count=${count},return=minimal` : "return=minimal");
|
|
else if (count) headers.set("Prefer", `count=${count}`);
|
|
return new PostgrestFilterBuilder({
|
|
method,
|
|
url,
|
|
headers,
|
|
schema: this.schemaName,
|
|
body,
|
|
fetch: (_this$fetch = this.fetch) !== null && _this$fetch !== void 0 ? _this$fetch : fetch,
|
|
urlLengthLimit: this.urlLengthLimit
|
|
});
|
|
}
|
|
};
|
|
|
|
//#endregion
|
|
//#region src/index.ts
|
|
var src_default = {
|
|
PostgrestClient,
|
|
PostgrestQueryBuilder,
|
|
PostgrestFilterBuilder,
|
|
PostgrestTransformBuilder,
|
|
PostgrestBuilder,
|
|
PostgrestError
|
|
};
|
|
|
|
//#endregion
|
|
export { PostgrestBuilder, PostgrestClient, PostgrestError, PostgrestFilterBuilder, PostgrestQueryBuilder, PostgrestTransformBuilder, src_default as default };
|
|
//# sourceMappingURL=index.mjs.map
|