first build

This commit is contained in:
2026-01-27 16:02:45 +03:30
parent f3a14141c7
commit a29cf38e4d
4891 changed files with 82192 additions and 426764 deletions
@@ -1,9 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const GoTrueAdminApi_1 = __importDefault(require("./GoTrueAdminApi"));
const AuthAdminApi = GoTrueAdminApi_1.default;
exports.default = AuthAdminApi;
//# sourceMappingURL=AuthAdminApi.js.map
@@ -1,9 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const GoTrueClient_1 = __importDefault(require("./GoTrueClient"));
const AuthClient = GoTrueClient_1.default;
exports.default = AuthClient;
//# sourceMappingURL=AuthClient.js.map
@@ -1,278 +0,0 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fetch_1 = require("./lib/fetch");
const helpers_1 = require("./lib/helpers");
const types_1 = require("./lib/types");
const errors_1 = require("./lib/errors");
class GoTrueAdminApi {
constructor({ url = '', headers = {}, fetch, }) {
this.url = url;
this.headers = headers;
this.fetch = (0, helpers_1.resolveFetch)(fetch);
this.mfa = {
listFactors: this._listFactors.bind(this),
deleteFactor: this._deleteFactor.bind(this),
};
}
/**
* Removes a logged-in session.
* @param jwt A valid, logged-in JWT.
* @param scope The logout sope.
*/
async signOut(jwt, scope = types_1.SIGN_OUT_SCOPES[0]) {
if (types_1.SIGN_OUT_SCOPES.indexOf(scope) < 0) {
throw new Error(`@supabase/auth-js: Parameter scope must be one of ${types_1.SIGN_OUT_SCOPES.join(', ')}`);
}
try {
await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/logout?scope=${scope}`, {
headers: this.headers,
jwt,
noResolveJson: true,
});
return { data: null, error: null };
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: null, error };
}
throw error;
}
}
/**
* Sends an invite link to an email address.
* @param email The email address of the user.
* @param options Additional options to be included when inviting.
*/
async inviteUserByEmail(email, options = {}) {
try {
return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/invite`, {
body: { email, data: options.data },
headers: this.headers,
redirectTo: options.redirectTo,
xform: fetch_1._userResponse,
});
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: { user: null }, error };
}
throw error;
}
}
/**
* Generates email links and OTPs to be sent via a custom email provider.
* @param email The user's email.
* @param options.password User password. For signup only.
* @param options.data Optional user metadata. For signup only.
* @param options.redirectTo The redirect url which should be appended to the generated link
*/
async generateLink(params) {
try {
const { options } = params, rest = __rest(params, ["options"]);
const body = Object.assign(Object.assign({}, rest), options);
if ('newEmail' in rest) {
// replace newEmail with new_email in request body
body.new_email = rest === null || rest === void 0 ? void 0 : rest.newEmail;
delete body['newEmail'];
}
return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/admin/generate_link`, {
body: body,
headers: this.headers,
xform: fetch_1._generateLinkResponse,
redirectTo: options === null || options === void 0 ? void 0 : options.redirectTo,
});
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return {
data: {
properties: null,
user: null,
},
error,
};
}
throw error;
}
}
// User Admin API
/**
* Creates a new user.
* This function should only be called on a server. Never expose your `service_role` key in the browser.
*/
async createUser(attributes) {
try {
return await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/admin/users`, {
body: attributes,
headers: this.headers,
xform: fetch_1._userResponse,
});
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: { user: null }, error };
}
throw error;
}
}
/**
* Get a list of users.
*
* This function should only be called on a server. Never expose your `service_role` key in the browser.
* @param params An object which supports `page` and `perPage` as numbers, to alter the paginated results.
*/
async listUsers(params) {
var _a, _b, _c, _d, _e, _f, _g;
try {
const pagination = { nextPage: null, lastPage: 0, total: 0 };
const response = await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/admin/users`, {
headers: this.headers,
noResolveJson: true,
query: {
page: (_b = (_a = params === null || params === void 0 ? void 0 : params.page) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '',
per_page: (_d = (_c = params === null || params === void 0 ? void 0 : params.perPage) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '',
},
xform: fetch_1._noResolveJsonResponse,
});
if (response.error)
throw response.error;
const users = await response.json();
const total = (_e = response.headers.get('x-total-count')) !== null && _e !== void 0 ? _e : 0;
const links = (_g = (_f = response.headers.get('link')) === null || _f === void 0 ? void 0 : _f.split(',')) !== null && _g !== void 0 ? _g : [];
if (links.length > 0) {
links.forEach((link) => {
const page = parseInt(link.split(';')[0].split('=')[1].substring(0, 1));
const rel = JSON.parse(link.split(';')[1].split('=')[1]);
pagination[`${rel}Page`] = page;
});
pagination.total = parseInt(total);
}
return { data: Object.assign(Object.assign({}, users), pagination), error: null };
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: { users: [] }, error };
}
throw error;
}
}
/**
* Get user by id.
*
* @param uid The user's unique identifier
*
* This function should only be called on a server. Never expose your `service_role` key in the browser.
*/
async getUserById(uid) {
(0, helpers_1.validateUUID)(uid);
try {
return await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/admin/users/${uid}`, {
headers: this.headers,
xform: fetch_1._userResponse,
});
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: { user: null }, error };
}
throw error;
}
}
/**
* Updates the user data.
*
* @param attributes The data you want to update.
*
* This function should only be called on a server. Never expose your `service_role` key in the browser.
*/
async updateUserById(uid, attributes) {
(0, helpers_1.validateUUID)(uid);
try {
return await (0, fetch_1._request)(this.fetch, 'PUT', `${this.url}/admin/users/${uid}`, {
body: attributes,
headers: this.headers,
xform: fetch_1._userResponse,
});
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: { user: null }, error };
}
throw error;
}
}
/**
* Delete a user. Requires a `service_role` key.
*
* @param id The user id you want to remove.
* @param shouldSoftDelete If true, then the user will be soft-deleted from the auth schema. Soft deletion allows user identification from the hashed user ID but is not reversible.
* Defaults to false for backward compatibility.
*
* This function should only be called on a server. Never expose your `service_role` key in the browser.
*/
async deleteUser(id, shouldSoftDelete = false) {
(0, helpers_1.validateUUID)(id);
try {
return await (0, fetch_1._request)(this.fetch, 'DELETE', `${this.url}/admin/users/${id}`, {
headers: this.headers,
body: {
should_soft_delete: shouldSoftDelete,
},
xform: fetch_1._userResponse,
});
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: { user: null }, error };
}
throw error;
}
}
async _listFactors(params) {
(0, helpers_1.validateUUID)(params.userId);
try {
const { data, error } = await (0, fetch_1._request)(this.fetch, 'GET', `${this.url}/admin/users/${params.userId}/factors`, {
headers: this.headers,
xform: (factors) => {
return { data: { factors }, error: null };
},
});
return { data, error };
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: null, error };
}
throw error;
}
}
async _deleteFactor(params) {
(0, helpers_1.validateUUID)(params.userId);
(0, helpers_1.validateUUID)(params.id);
try {
const data = await (0, fetch_1._request)(this.fetch, 'DELETE', `${this.url}/admin/users/${params.userId}/factors/${params.id}`, {
headers: this.headers,
});
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isAuthError)(error)) {
return { data: null, error };
}
throw error;
}
}
}
exports.default = GoTrueAdminApi;
//# sourceMappingURL=GoTrueAdminApi.js.map
File diff suppressed because it is too large Load Diff
-36
View File
@@ -1,36 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processLock = exports.lockInternals = exports.NavigatorLockAcquireTimeoutError = exports.navigatorLock = exports.AuthClient = exports.AuthAdminApi = exports.GoTrueClient = exports.GoTrueAdminApi = void 0;
const GoTrueAdminApi_1 = __importDefault(require("./GoTrueAdminApi"));
exports.GoTrueAdminApi = GoTrueAdminApi_1.default;
const GoTrueClient_1 = __importDefault(require("./GoTrueClient"));
exports.GoTrueClient = GoTrueClient_1.default;
const AuthAdminApi_1 = __importDefault(require("./AuthAdminApi"));
exports.AuthAdminApi = AuthAdminApi_1.default;
const AuthClient_1 = __importDefault(require("./AuthClient"));
exports.AuthClient = AuthClient_1.default;
__exportStar(require("./lib/types"), exports);
__exportStar(require("./lib/errors"), exports);
var locks_1 = require("./lib/locks");
Object.defineProperty(exports, "navigatorLock", { enumerable: true, get: function () { return locks_1.navigatorLock; } });
Object.defineProperty(exports, "NavigatorLockAcquireTimeoutError", { enumerable: true, get: function () { return locks_1.NavigatorLockAcquireTimeoutError; } });
Object.defineProperty(exports, "lockInternals", { enumerable: true, get: function () { return locks_1.internals; } });
Object.defineProperty(exports, "processLock", { enumerable: true, get: function () { return locks_1.processLock; } });
//# sourceMappingURL=index.js.map
@@ -1,270 +0,0 @@
"use strict";
/**
* Avoid modifying this file. It's part of
* https://github.com/supabase-community/base64url-js. Submit all fixes on
* that repo!
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.bytesToBase64URL = exports.stringToUint8Array = exports.base64UrlToUint8Array = exports.stringFromUTF8 = exports.stringToUTF8 = exports.codepointToUTF8 = exports.stringFromBase64URL = exports.stringToBase64URL = exports.byteFromBase64URL = exports.byteToBase64URL = void 0;
/**
* An array of characters that encode 6 bits into a Base64-URL alphabet
* character.
*/
const TO_BASE64URL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'.split('');
/**
* An array of characters that can appear in a Base64-URL encoded string but
* should be ignored.
*/
const IGNORE_BASE64URL = ' \t\n\r='.split('');
/**
* An array of 128 numbers that map a Base64-URL character to 6 bits, or if -2
* used to skip the character, or if -1 used to error out.
*/
const FROM_BASE64URL = (() => {
const charMap = new Array(128);
for (let i = 0; i < charMap.length; i += 1) {
charMap[i] = -1;
}
for (let i = 0; i < IGNORE_BASE64URL.length; i += 1) {
charMap[IGNORE_BASE64URL[i].charCodeAt(0)] = -2;
}
for (let i = 0; i < TO_BASE64URL.length; i += 1) {
charMap[TO_BASE64URL[i].charCodeAt(0)] = i;
}
return charMap;
})();
/**
* Converts a byte to a Base64-URL string.
*
* @param byte The byte to convert, or null to flush at the end of the byte sequence.
* @param state The Base64 conversion state. Pass an initial value of `{ queue: 0, queuedBits: 0 }`.
* @param emit A function called with the next Base64 character when ready.
*/
function byteToBase64URL(byte, state, emit) {
if (byte !== null) {
state.queue = (state.queue << 8) | byte;
state.queuedBits += 8;
while (state.queuedBits >= 6) {
const pos = (state.queue >> (state.queuedBits - 6)) & 63;
emit(TO_BASE64URL[pos]);
state.queuedBits -= 6;
}
}
else if (state.queuedBits > 0) {
state.queue = state.queue << (6 - state.queuedBits);
state.queuedBits = 6;
while (state.queuedBits >= 6) {
const pos = (state.queue >> (state.queuedBits - 6)) & 63;
emit(TO_BASE64URL[pos]);
state.queuedBits -= 6;
}
}
}
exports.byteToBase64URL = byteToBase64URL;
/**
* Converts a String char code (extracted using `string.charCodeAt(position)`) to a sequence of Base64-URL characters.
*
* @param charCode The char code of the JavaScript string.
* @param state The Base64 state. Pass an initial value of `{ queue: 0, queuedBits: 0 }`.
* @param emit A function called with the next byte.
*/
function byteFromBase64URL(charCode, state, emit) {
const bits = FROM_BASE64URL[charCode];
if (bits > -1) {
// valid Base64-URL character
state.queue = (state.queue << 6) | bits;
state.queuedBits += 6;
while (state.queuedBits >= 8) {
emit((state.queue >> (state.queuedBits - 8)) & 0xff);
state.queuedBits -= 8;
}
}
else if (bits === -2) {
// ignore spaces, tabs, newlines, =
return;
}
else {
throw new Error(`Invalid Base64-URL character "${String.fromCharCode(charCode)}"`);
}
}
exports.byteFromBase64URL = byteFromBase64URL;
/**
* Converts a JavaScript string (which may include any valid character) into a
* Base64-URL encoded string. The string is first encoded in UTF-8 which is
* then encoded as Base64-URL.
*
* @param str The string to convert.
*/
function stringToBase64URL(str) {
const base64 = [];
const emitter = (char) => {
base64.push(char);
};
const state = { queue: 0, queuedBits: 0 };
stringToUTF8(str, (byte) => {
byteToBase64URL(byte, state, emitter);
});
byteToBase64URL(null, state, emitter);
return base64.join('');
}
exports.stringToBase64URL = stringToBase64URL;
/**
* Converts a Base64-URL encoded string into a JavaScript string. It is assumed
* that the underlying string has been encoded as UTF-8.
*
* @param str The Base64-URL encoded string.
*/
function stringFromBase64URL(str) {
const conv = [];
const utf8Emit = (codepoint) => {
conv.push(String.fromCodePoint(codepoint));
};
const utf8State = {
utf8seq: 0,
codepoint: 0,
};
const b64State = { queue: 0, queuedBits: 0 };
const byteEmit = (byte) => {
stringFromUTF8(byte, utf8State, utf8Emit);
};
for (let i = 0; i < str.length; i += 1) {
byteFromBase64URL(str.charCodeAt(i), b64State, byteEmit);
}
return conv.join('');
}
exports.stringFromBase64URL = stringFromBase64URL;
/**
* Converts a Unicode codepoint to a multi-byte UTF-8 sequence.
*
* @param codepoint The Unicode codepoint.
* @param emit Function which will be called for each UTF-8 byte that represents the codepoint.
*/
function codepointToUTF8(codepoint, emit) {
if (codepoint <= 0x7f) {
emit(codepoint);
return;
}
else if (codepoint <= 0x7ff) {
emit(0xc0 | (codepoint >> 6));
emit(0x80 | (codepoint & 0x3f));
return;
}
else if (codepoint <= 0xffff) {
emit(0xe0 | (codepoint >> 12));
emit(0x80 | ((codepoint >> 6) & 0x3f));
emit(0x80 | (codepoint & 0x3f));
return;
}
else if (codepoint <= 0x10ffff) {
emit(0xf0 | (codepoint >> 18));
emit(0x80 | ((codepoint >> 12) & 0x3f));
emit(0x80 | ((codepoint >> 6) & 0x3f));
emit(0x80 | (codepoint & 0x3f));
return;
}
throw new Error(`Unrecognized Unicode codepoint: ${codepoint.toString(16)}`);
}
exports.codepointToUTF8 = codepointToUTF8;
/**
* Converts a JavaScript string to a sequence of UTF-8 bytes.
*
* @param str The string to convert to UTF-8.
* @param emit Function which will be called for each UTF-8 byte of the string.
*/
function stringToUTF8(str, emit) {
for (let i = 0; i < str.length; i += 1) {
let codepoint = str.charCodeAt(i);
if (codepoint > 0xd7ff && codepoint <= 0xdbff) {
// most UTF-16 codepoints are Unicode codepoints, except values in this
// range where the next UTF-16 codepoint needs to be combined with the
// current one to get the Unicode codepoint
const highSurrogate = ((codepoint - 0xd800) * 0x400) & 0xffff;
const lowSurrogate = (str.charCodeAt(i + 1) - 0xdc00) & 0xffff;
codepoint = (lowSurrogate | highSurrogate) + 0x10000;
i += 1;
}
codepointToUTF8(codepoint, emit);
}
}
exports.stringToUTF8 = stringToUTF8;
/**
* Converts a UTF-8 byte to a Unicode codepoint.
*
* @param byte The UTF-8 byte next in the sequence.
* @param state The shared state between consecutive UTF-8 bytes in the
* sequence, an object with the shape `{ utf8seq: 0, codepoint: 0 }`.
* @param emit Function which will be called for each codepoint.
*/
function stringFromUTF8(byte, state, emit) {
if (state.utf8seq === 0) {
if (byte <= 0x7f) {
emit(byte);
return;
}
// count the number of 1 leading bits until you reach 0
for (let leadingBit = 1; leadingBit < 6; leadingBit += 1) {
if (((byte >> (7 - leadingBit)) & 1) === 0) {
state.utf8seq = leadingBit;
break;
}
}
if (state.utf8seq === 2) {
state.codepoint = byte & 31;
}
else if (state.utf8seq === 3) {
state.codepoint = byte & 15;
}
else if (state.utf8seq === 4) {
state.codepoint = byte & 7;
}
else {
throw new Error('Invalid UTF-8 sequence');
}
state.utf8seq -= 1;
}
else if (state.utf8seq > 0) {
if (byte <= 0x7f) {
throw new Error('Invalid UTF-8 sequence');
}
state.codepoint = (state.codepoint << 6) | (byte & 63);
state.utf8seq -= 1;
if (state.utf8seq === 0) {
emit(state.codepoint);
}
}
}
exports.stringFromUTF8 = stringFromUTF8;
/**
* Helper functions to convert different types of strings to Uint8Array
*/
function base64UrlToUint8Array(str) {
const result = [];
const state = { queue: 0, queuedBits: 0 };
const onByte = (byte) => {
result.push(byte);
};
for (let i = 0; i < str.length; i += 1) {
byteFromBase64URL(str.charCodeAt(i), state, onByte);
}
return new Uint8Array(result);
}
exports.base64UrlToUint8Array = base64UrlToUint8Array;
function stringToUint8Array(str) {
const result = [];
stringToUTF8(str, (byte) => result.push(byte));
return new Uint8Array(result);
}
exports.stringToUint8Array = stringToUint8Array;
function bytesToBase64URL(bytes) {
const result = [];
const state = { queue: 0, queuedBits: 0 };
const onChar = (char) => {
result.push(char);
};
bytes.forEach((byte) => byteToBase64URL(byte, state, onChar));
// always call with `null` after processing all bytes
byteToBase64URL(null, state, onChar);
return result.join('');
}
exports.bytesToBase64URL = bytesToBase64URL;
//# sourceMappingURL=base64url.js.map
@@ -1,31 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.JWKS_TTL = exports.BASE64URL_REGEX = exports.API_VERSIONS = exports.API_VERSION_HEADER_NAME = exports.NETWORK_FAILURE = exports.DEFAULT_HEADERS = exports.AUDIENCE = exports.STORAGE_KEY = exports.GOTRUE_URL = exports.EXPIRY_MARGIN_MS = exports.AUTO_REFRESH_TICK_THRESHOLD = exports.AUTO_REFRESH_TICK_DURATION_MS = void 0;
const version_1 = require("./version");
/** Current session will be checked for refresh at this interval. */
exports.AUTO_REFRESH_TICK_DURATION_MS = 30 * 1000;
/**
* A token refresh will be attempted this many ticks before the current session expires. */
exports.AUTO_REFRESH_TICK_THRESHOLD = 3;
/*
* Earliest time before an access token expires that the session should be refreshed.
*/
exports.EXPIRY_MARGIN_MS = exports.AUTO_REFRESH_TICK_THRESHOLD * exports.AUTO_REFRESH_TICK_DURATION_MS;
exports.GOTRUE_URL = 'http://localhost:9999';
exports.STORAGE_KEY = 'supabase.auth.token';
exports.AUDIENCE = '';
exports.DEFAULT_HEADERS = { 'X-Client-Info': `gotrue-js/${version_1.version}` };
exports.NETWORK_FAILURE = {
MAX_RETRIES: 10,
RETRY_INTERVAL: 2, // in deciseconds
};
exports.API_VERSION_HEADER_NAME = 'X-Supabase-Api-Version';
exports.API_VERSIONS = {
'2024-01-01': {
timestamp: Date.parse('2024-01-01T00:00:00.0Z'),
name: '2024-01-01',
},
};
exports.BASE64URL_REGEX = /^([a-z0-9_-]{4})*($|[a-z0-9_-]{3}$|[a-z0-9_-]{2}$)$/i;
exports.JWKS_TTL = 10 * 60 * 1000; // 10 minutes
//# sourceMappingURL=constants.js.map
-137
View File
@@ -1,137 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthInvalidJwtError = exports.isAuthWeakPasswordError = exports.AuthWeakPasswordError = exports.isAuthRetryableFetchError = exports.AuthRetryableFetchError = exports.AuthPKCEGrantCodeExchangeError = exports.isAuthImplicitGrantRedirectError = exports.AuthImplicitGrantRedirectError = exports.AuthInvalidCredentialsError = exports.AuthInvalidTokenResponseError = exports.isAuthSessionMissingError = exports.AuthSessionMissingError = exports.CustomAuthError = exports.AuthUnknownError = exports.isAuthApiError = exports.AuthApiError = exports.isAuthError = exports.AuthError = void 0;
class AuthError extends Error {
constructor(message, status, code) {
super(message);
this.__isAuthError = true;
this.name = 'AuthError';
this.status = status;
this.code = code;
}
}
exports.AuthError = AuthError;
function isAuthError(error) {
return typeof error === 'object' && error !== null && '__isAuthError' in error;
}
exports.isAuthError = isAuthError;
class AuthApiError extends AuthError {
constructor(message, status, code) {
super(message, status, code);
this.name = 'AuthApiError';
this.status = status;
this.code = code;
}
}
exports.AuthApiError = AuthApiError;
function isAuthApiError(error) {
return isAuthError(error) && error.name === 'AuthApiError';
}
exports.isAuthApiError = isAuthApiError;
class AuthUnknownError extends AuthError {
constructor(message, originalError) {
super(message);
this.name = 'AuthUnknownError';
this.originalError = originalError;
}
}
exports.AuthUnknownError = AuthUnknownError;
class CustomAuthError extends AuthError {
constructor(message, name, status, code) {
super(message, status, code);
this.name = name;
this.status = status;
}
}
exports.CustomAuthError = CustomAuthError;
class AuthSessionMissingError extends CustomAuthError {
constructor() {
super('Auth session missing!', 'AuthSessionMissingError', 400, undefined);
}
}
exports.AuthSessionMissingError = AuthSessionMissingError;
function isAuthSessionMissingError(error) {
return isAuthError(error) && error.name === 'AuthSessionMissingError';
}
exports.isAuthSessionMissingError = isAuthSessionMissingError;
class AuthInvalidTokenResponseError extends CustomAuthError {
constructor() {
super('Auth session or user missing', 'AuthInvalidTokenResponseError', 500, undefined);
}
}
exports.AuthInvalidTokenResponseError = AuthInvalidTokenResponseError;
class AuthInvalidCredentialsError extends CustomAuthError {
constructor(message) {
super(message, 'AuthInvalidCredentialsError', 400, undefined);
}
}
exports.AuthInvalidCredentialsError = AuthInvalidCredentialsError;
class AuthImplicitGrantRedirectError extends CustomAuthError {
constructor(message, details = null) {
super(message, 'AuthImplicitGrantRedirectError', 500, undefined);
this.details = null;
this.details = details;
}
toJSON() {
return {
name: this.name,
message: this.message,
status: this.status,
details: this.details,
};
}
}
exports.AuthImplicitGrantRedirectError = AuthImplicitGrantRedirectError;
function isAuthImplicitGrantRedirectError(error) {
return isAuthError(error) && error.name === 'AuthImplicitGrantRedirectError';
}
exports.isAuthImplicitGrantRedirectError = isAuthImplicitGrantRedirectError;
class AuthPKCEGrantCodeExchangeError extends CustomAuthError {
constructor(message, details = null) {
super(message, 'AuthPKCEGrantCodeExchangeError', 500, undefined);
this.details = null;
this.details = details;
}
toJSON() {
return {
name: this.name,
message: this.message,
status: this.status,
details: this.details,
};
}
}
exports.AuthPKCEGrantCodeExchangeError = AuthPKCEGrantCodeExchangeError;
class AuthRetryableFetchError extends CustomAuthError {
constructor(message, status) {
super(message, 'AuthRetryableFetchError', status, undefined);
}
}
exports.AuthRetryableFetchError = AuthRetryableFetchError;
function isAuthRetryableFetchError(error) {
return isAuthError(error) && error.name === 'AuthRetryableFetchError';
}
exports.isAuthRetryableFetchError = isAuthRetryableFetchError;
/**
* This error is thrown on certain methods when the password used is deemed
* weak. Inspect the reasons to identify what password strength rules are
* inadequate.
*/
class AuthWeakPasswordError extends CustomAuthError {
constructor(message, status, reasons) {
super(message, 'AuthWeakPasswordError', status, 'weak_password');
this.reasons = reasons;
}
}
exports.AuthWeakPasswordError = AuthWeakPasswordError;
function isAuthWeakPasswordError(error) {
return isAuthError(error) && error.name === 'AuthWeakPasswordError';
}
exports.isAuthWeakPasswordError = isAuthWeakPasswordError;
class AuthInvalidJwtError extends CustomAuthError {
constructor(message) {
super(message, 'AuthInvalidJwtError', 400, 'invalid_jwt');
}
}
exports.AuthInvalidJwtError = AuthInvalidJwtError;
//# sourceMappingURL=errors.js.map
-195
View File
@@ -1,195 +0,0 @@
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports._noResolveJsonResponse = exports._generateLinkResponse = exports._ssoResponse = exports._userResponse = exports._sessionResponsePassword = exports._sessionResponse = exports._request = exports.handleError = void 0;
const constants_1 = require("./constants");
const helpers_1 = require("./helpers");
const errors_1 = require("./errors");
const _getErrorMessage = (err) => err.msg || err.message || err.error_description || err.error || JSON.stringify(err);
const NETWORK_ERROR_CODES = [502, 503, 504];
async function handleError(error) {
var _a;
if (!(0, helpers_1.looksLikeFetchResponse)(error)) {
throw new errors_1.AuthRetryableFetchError(_getErrorMessage(error), 0);
}
if (NETWORK_ERROR_CODES.includes(error.status)) {
// status in 500...599 range - server had an error, request might be retryed.
throw new errors_1.AuthRetryableFetchError(_getErrorMessage(error), error.status);
}
let data;
try {
data = await error.json();
}
catch (e) {
throw new errors_1.AuthUnknownError(_getErrorMessage(e), e);
}
let errorCode = undefined;
const responseAPIVersion = (0, helpers_1.parseResponseAPIVersion)(error);
if (responseAPIVersion &&
responseAPIVersion.getTime() >= constants_1.API_VERSIONS['2024-01-01'].timestamp &&
typeof data === 'object' &&
data &&
typeof data.code === 'string') {
errorCode = data.code;
}
else if (typeof data === 'object' && data && typeof data.error_code === 'string') {
errorCode = data.error_code;
}
if (!errorCode) {
// Legacy support for weak password errors, when there were no error codes
if (typeof data === 'object' &&
data &&
typeof data.weak_password === 'object' &&
data.weak_password &&
Array.isArray(data.weak_password.reasons) &&
data.weak_password.reasons.length &&
data.weak_password.reasons.reduce((a, i) => a && typeof i === 'string', true)) {
throw new errors_1.AuthWeakPasswordError(_getErrorMessage(data), error.status, data.weak_password.reasons);
}
}
else if (errorCode === 'weak_password') {
throw new errors_1.AuthWeakPasswordError(_getErrorMessage(data), error.status, ((_a = data.weak_password) === null || _a === void 0 ? void 0 : _a.reasons) || []);
}
else if (errorCode === 'session_not_found') {
// The `session_id` inside the JWT does not correspond to a row in the
// `sessions` table. This usually means the user has signed out, has been
// deleted, or their session has somehow been terminated.
throw new errors_1.AuthSessionMissingError();
}
throw new errors_1.AuthApiError(_getErrorMessage(data), error.status || 500, errorCode);
}
exports.handleError = handleError;
const _getRequestParams = (method, options, parameters, body) => {
const params = { method, headers: (options === null || options === void 0 ? void 0 : options.headers) || {} };
if (method === 'GET') {
return params;
}
params.headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8' }, options === null || options === void 0 ? void 0 : options.headers);
params.body = JSON.stringify(body);
return Object.assign(Object.assign({}, params), parameters);
};
async function _request(fetcher, method, url, options) {
var _a;
const headers = Object.assign({}, options === null || options === void 0 ? void 0 : options.headers);
if (!headers[constants_1.API_VERSION_HEADER_NAME]) {
headers[constants_1.API_VERSION_HEADER_NAME] = constants_1.API_VERSIONS['2024-01-01'].name;
}
if (options === null || options === void 0 ? void 0 : options.jwt) {
headers['Authorization'] = `Bearer ${options.jwt}`;
}
const qs = (_a = options === null || options === void 0 ? void 0 : options.query) !== null && _a !== void 0 ? _a : {};
if (options === null || options === void 0 ? void 0 : options.redirectTo) {
qs['redirect_to'] = options.redirectTo;
}
const queryString = Object.keys(qs).length ? '?' + new URLSearchParams(qs).toString() : '';
const data = await _handleRequest(fetcher, method, url + queryString, {
headers,
noResolveJson: options === null || options === void 0 ? void 0 : options.noResolveJson,
}, {}, options === null || options === void 0 ? void 0 : options.body);
return (options === null || options === void 0 ? void 0 : options.xform) ? options === null || options === void 0 ? void 0 : options.xform(data) : { data: Object.assign({}, data), error: null };
}
exports._request = _request;
async function _handleRequest(fetcher, method, url, options, parameters, body) {
const requestParams = _getRequestParams(method, options, parameters, body);
let result;
try {
result = await fetcher(url, Object.assign({}, requestParams));
}
catch (e) {
console.error(e);
// fetch failed, likely due to a network or CORS error
throw new errors_1.AuthRetryableFetchError(_getErrorMessage(e), 0);
}
if (!result.ok) {
await handleError(result);
}
if (options === null || options === void 0 ? void 0 : options.noResolveJson) {
return result;
}
try {
return await result.json();
}
catch (e) {
await handleError(e);
}
}
function _sessionResponse(data) {
var _a;
let session = null;
if (hasSession(data)) {
session = Object.assign({}, data);
if (!data.expires_at) {
session.expires_at = (0, helpers_1.expiresAt)(data.expires_in);
}
}
const user = (_a = data.user) !== null && _a !== void 0 ? _a : data;
return { data: { session, user }, error: null };
}
exports._sessionResponse = _sessionResponse;
function _sessionResponsePassword(data) {
const response = _sessionResponse(data);
if (!response.error &&
data.weak_password &&
typeof data.weak_password === 'object' &&
Array.isArray(data.weak_password.reasons) &&
data.weak_password.reasons.length &&
data.weak_password.message &&
typeof data.weak_password.message === 'string' &&
data.weak_password.reasons.reduce((a, i) => a && typeof i === 'string', true)) {
response.data.weak_password = data.weak_password;
}
return response;
}
exports._sessionResponsePassword = _sessionResponsePassword;
function _userResponse(data) {
var _a;
const user = (_a = data.user) !== null && _a !== void 0 ? _a : data;
return { data: { user }, error: null };
}
exports._userResponse = _userResponse;
function _ssoResponse(data) {
return { data, error: null };
}
exports._ssoResponse = _ssoResponse;
function _generateLinkResponse(data) {
const { action_link, email_otp, hashed_token, redirect_to, verification_type } = data, rest = __rest(data, ["action_link", "email_otp", "hashed_token", "redirect_to", "verification_type"]);
const properties = {
action_link,
email_otp,
hashed_token,
redirect_to,
verification_type,
};
const user = Object.assign({}, rest);
return {
data: {
properties,
user,
},
error: null,
};
}
exports._generateLinkResponse = _generateLinkResponse;
function _noResolveJsonResponse(data) {
return data;
}
exports._noResolveJsonResponse = _noResolveJsonResponse;
/**
* hasSession checks if the response object contains a valid session
* @param data A response object
* @returns true if a session is in the response
*/
function hasSession(data) {
return data.access_token && data.refresh_token && data.expires_in;
}
//# sourceMappingURL=fetch.js.map
-378
View File
@@ -1,378 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.deepClone = exports.userNotAvailableProxy = exports.validateUUID = exports.getAlgorithm = exports.validateExp = exports.parseResponseAPIVersion = exports.getCodeChallengeAndMethod = exports.generatePKCEChallenge = exports.generatePKCEVerifier = exports.retryable = exports.sleep = exports.decodeJWT = exports.Deferred = exports.removeItemAsync = exports.getItemAsync = exports.setItemAsync = exports.looksLikeFetchResponse = exports.resolveFetch = exports.parseParametersFromURL = exports.supportsLocalStorage = exports.isBrowser = exports.uuid = exports.expiresAt = void 0;
const constants_1 = require("./constants");
const errors_1 = require("./errors");
const base64url_1 = require("./base64url");
function expiresAt(expiresIn) {
const timeNow = Math.round(Date.now() / 1000);
return timeNow + expiresIn;
}
exports.expiresAt = expiresAt;
function uuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
exports.uuid = uuid;
const isBrowser = () => typeof window !== 'undefined' && typeof document !== 'undefined';
exports.isBrowser = isBrowser;
const localStorageWriteTests = {
tested: false,
writable: false,
};
/**
* Checks whether localStorage is supported on this browser.
*/
const supportsLocalStorage = () => {
if (!(0, exports.isBrowser)()) {
return false;
}
try {
if (typeof globalThis.localStorage !== 'object') {
return false;
}
}
catch (e) {
// DOM exception when accessing `localStorage`
return false;
}
if (localStorageWriteTests.tested) {
return localStorageWriteTests.writable;
}
const randomKey = `lswt-${Math.random()}${Math.random()}`;
try {
globalThis.localStorage.setItem(randomKey, randomKey);
globalThis.localStorage.removeItem(randomKey);
localStorageWriteTests.tested = true;
localStorageWriteTests.writable = true;
}
catch (e) {
// localStorage can't be written to
// https://www.chromium.org/for-testers/bug-reporting-guidelines/uncaught-securityerror-failed-to-read-the-localstorage-property-from-window-access-is-denied-for-this-document
localStorageWriteTests.tested = true;
localStorageWriteTests.writable = false;
}
return localStorageWriteTests.writable;
};
exports.supportsLocalStorage = supportsLocalStorage;
/**
* Extracts parameters encoded in the URL both in the query and fragment.
*/
function parseParametersFromURL(href) {
const result = {};
const url = new URL(href);
if (url.hash && url.hash[0] === '#') {
try {
const hashSearchParams = new URLSearchParams(url.hash.substring(1));
hashSearchParams.forEach((value, key) => {
result[key] = value;
});
}
catch (e) {
// hash is not a query string
}
}
// search parameters take precedence over hash parameters
url.searchParams.forEach((value, key) => {
result[key] = value;
});
return result;
}
exports.parseParametersFromURL = parseParametersFromURL;
const resolveFetch = (customFetch) => {
let _fetch;
if (customFetch) {
_fetch = customFetch;
}
else if (typeof fetch === 'undefined') {
_fetch = (...args) => Promise.resolve().then(() => __importStar(require('@supabase/node-fetch'))).then(({ default: fetch }) => fetch(...args));
}
else {
_fetch = fetch;
}
return (...args) => _fetch(...args);
};
exports.resolveFetch = resolveFetch;
const looksLikeFetchResponse = (maybeResponse) => {
return (typeof maybeResponse === 'object' &&
maybeResponse !== null &&
'status' in maybeResponse &&
'ok' in maybeResponse &&
'json' in maybeResponse &&
typeof maybeResponse.json === 'function');
};
exports.looksLikeFetchResponse = looksLikeFetchResponse;
// Storage helpers
const setItemAsync = async (storage, key, data) => {
await storage.setItem(key, JSON.stringify(data));
};
exports.setItemAsync = setItemAsync;
const getItemAsync = async (storage, key) => {
const value = await storage.getItem(key);
if (!value) {
return null;
}
try {
return JSON.parse(value);
}
catch (_a) {
return value;
}
};
exports.getItemAsync = getItemAsync;
const removeItemAsync = async (storage, key) => {
await storage.removeItem(key);
};
exports.removeItemAsync = removeItemAsync;
/**
* A deferred represents some asynchronous work that is not yet finished, which
* may or may not culminate in a value.
* Taken from: https://github.com/mike-north/types/blob/master/src/async.ts
*/
class Deferred {
constructor() {
// eslint-disable-next-line @typescript-eslint/no-extra-semi
;
this.promise = new Deferred.promiseConstructor((res, rej) => {
// eslint-disable-next-line @typescript-eslint/no-extra-semi
;
this.resolve = res;
this.reject = rej;
});
}
}
exports.Deferred = Deferred;
Deferred.promiseConstructor = Promise;
function decodeJWT(token) {
const parts = token.split('.');
if (parts.length !== 3) {
throw new errors_1.AuthInvalidJwtError('Invalid JWT structure');
}
// Regex checks for base64url format
for (let i = 0; i < parts.length; i++) {
if (!constants_1.BASE64URL_REGEX.test(parts[i])) {
throw new errors_1.AuthInvalidJwtError('JWT not in base64url format');
}
}
const data = {
// using base64url lib
header: JSON.parse((0, base64url_1.stringFromBase64URL)(parts[0])),
payload: JSON.parse((0, base64url_1.stringFromBase64URL)(parts[1])),
signature: (0, base64url_1.base64UrlToUint8Array)(parts[2]),
raw: {
header: parts[0],
payload: parts[1],
},
};
return data;
}
exports.decodeJWT = decodeJWT;
/**
* Creates a promise that resolves to null after some time.
*/
async function sleep(time) {
return await new Promise((accept) => {
setTimeout(() => accept(null), time);
});
}
exports.sleep = sleep;
/**
* Converts the provided async function into a retryable function. Each result
* or thrown error is sent to the isRetryable function which should return true
* if the function should run again.
*/
function retryable(fn, isRetryable) {
const promise = new Promise((accept, reject) => {
// eslint-disable-next-line @typescript-eslint/no-extra-semi
;
(async () => {
for (let attempt = 0; attempt < Infinity; attempt++) {
try {
const result = await fn(attempt);
if (!isRetryable(attempt, null, result)) {
accept(result);
return;
}
}
catch (e) {
if (!isRetryable(attempt, e)) {
reject(e);
return;
}
}
}
})();
});
return promise;
}
exports.retryable = retryable;
function dec2hex(dec) {
return ('0' + dec.toString(16)).substr(-2);
}
// Functions below taken from: https://stackoverflow.com/questions/63309409/creating-a-code-verifier-and-challenge-for-pkce-auth-on-spotify-api-in-reactjs
function generatePKCEVerifier() {
const verifierLength = 56;
const array = new Uint32Array(verifierLength);
if (typeof crypto === 'undefined') {
const charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
const charSetLen = charSet.length;
let verifier = '';
for (let i = 0; i < verifierLength; i++) {
verifier += charSet.charAt(Math.floor(Math.random() * charSetLen));
}
return verifier;
}
crypto.getRandomValues(array);
return Array.from(array, dec2hex).join('');
}
exports.generatePKCEVerifier = generatePKCEVerifier;
async function sha256(randomString) {
const encoder = new TextEncoder();
const encodedData = encoder.encode(randomString);
const hash = await crypto.subtle.digest('SHA-256', encodedData);
const bytes = new Uint8Array(hash);
return Array.from(bytes)
.map((c) => String.fromCharCode(c))
.join('');
}
async function generatePKCEChallenge(verifier) {
const hasCryptoSupport = typeof crypto !== 'undefined' &&
typeof crypto.subtle !== 'undefined' &&
typeof TextEncoder !== 'undefined';
if (!hasCryptoSupport) {
console.warn('WebCrypto API is not supported. Code challenge method will default to use plain instead of sha256.');
return verifier;
}
const hashed = await sha256(verifier);
return btoa(hashed).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
exports.generatePKCEChallenge = generatePKCEChallenge;
async function getCodeChallengeAndMethod(storage, storageKey, isPasswordRecovery = false) {
const codeVerifier = generatePKCEVerifier();
let storedCodeVerifier = codeVerifier;
if (isPasswordRecovery) {
storedCodeVerifier += '/PASSWORD_RECOVERY';
}
await (0, exports.setItemAsync)(storage, `${storageKey}-code-verifier`, storedCodeVerifier);
const codeChallenge = await generatePKCEChallenge(codeVerifier);
const codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256';
return [codeChallenge, codeChallengeMethod];
}
exports.getCodeChallengeAndMethod = getCodeChallengeAndMethod;
/** Parses the API version which is 2YYY-MM-DD. */
const API_VERSION_REGEX = /^2[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])$/i;
function parseResponseAPIVersion(response) {
const apiVersion = response.headers.get(constants_1.API_VERSION_HEADER_NAME);
if (!apiVersion) {
return null;
}
if (!apiVersion.match(API_VERSION_REGEX)) {
return null;
}
try {
const date = new Date(`${apiVersion}T00:00:00.0Z`);
return date;
}
catch (e) {
return null;
}
}
exports.parseResponseAPIVersion = parseResponseAPIVersion;
function validateExp(exp) {
if (!exp) {
throw new Error('Missing exp claim');
}
const timeNow = Math.floor(Date.now() / 1000);
if (exp <= timeNow) {
throw new Error('JWT has expired');
}
}
exports.validateExp = validateExp;
function getAlgorithm(alg) {
switch (alg) {
case 'RS256':
return {
name: 'RSASSA-PKCS1-v1_5',
hash: { name: 'SHA-256' },
};
case 'ES256':
return {
name: 'ECDSA',
namedCurve: 'P-256',
hash: { name: 'SHA-256' },
};
default:
throw new Error('Invalid alg claim');
}
}
exports.getAlgorithm = getAlgorithm;
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
function validateUUID(str) {
if (!UUID_REGEX.test(str)) {
throw new Error('@supabase/auth-js: Expected parameter to be UUID but is not');
}
}
exports.validateUUID = validateUUID;
function userNotAvailableProxy() {
const proxyTarget = {};
return new Proxy(proxyTarget, {
get: (target, prop) => {
if (prop === '__isUserNotAvailableProxy') {
return true;
}
// Preventative check for common problematic symbols during cloning/inspection
// These symbols might be accessed by structuredClone or other internal mechanisms.
if (typeof prop === 'symbol') {
const sProp = prop.toString();
if (sProp === 'Symbol(Symbol.toPrimitive)' ||
sProp === 'Symbol(Symbol.toStringTag)' ||
sProp === 'Symbol(util.inspect.custom)') {
// Node.js util.inspect
return undefined;
}
}
throw new Error(`@supabase/auth-js: client was created with userStorage option and there was no user stored in the user storage. Accessing the "${prop}" property of the session object is not supported. Please use getUser() instead.`);
},
set: (_target, prop) => {
throw new Error(`@supabase/auth-js: client was created with userStorage option and there was no user stored in the user storage. Setting the "${prop}" property of the session object is not supported. Please use getUser() to fetch a user object you can manipulate.`);
},
deleteProperty: (_target, prop) => {
throw new Error(`@supabase/auth-js: client was created with userStorage option and there was no user stored in the user storage. Deleting the "${prop}" property of the session object is not supported. Please use getUser() to fetch a user object you can manipulate.`);
},
});
}
exports.userNotAvailableProxy = userNotAvailableProxy;
/**
* Deep clones a JSON-serializable object using JSON.parse(JSON.stringify(obj)).
* Note: Only works for JSON-safe data.
*/
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
exports.deepClone = deepClone;
//# sourceMappingURL=helpers.js.map
@@ -1,22 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.memoryLocalStorageAdapter = void 0;
/**
* Returns a localStorage-like object that stores the key-value pairs in
* memory.
*/
function memoryLocalStorageAdapter(store = {}) {
return {
getItem: (key) => {
return store[key] || null;
},
setItem: (key, value) => {
store[key] = value;
},
removeItem: (key) => {
delete store[key];
},
};
}
exports.memoryLocalStorageAdapter = memoryLocalStorageAdapter;
//# sourceMappingURL=local-storage.js.map
-187
View File
@@ -1,187 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processLock = exports.navigatorLock = exports.ProcessLockAcquireTimeoutError = exports.NavigatorLockAcquireTimeoutError = exports.LockAcquireTimeoutError = exports.internals = void 0;
const helpers_1 = require("./helpers");
/**
* @experimental
*/
exports.internals = {
/**
* @experimental
*/
debug: !!(globalThis &&
(0, helpers_1.supportsLocalStorage)() &&
globalThis.localStorage &&
globalThis.localStorage.getItem('supabase.gotrue-js.locks.debug') === 'true'),
};
/**
* An error thrown when a lock cannot be acquired after some amount of time.
*
* Use the {@link #isAcquireTimeout} property instead of checking with `instanceof`.
*/
class LockAcquireTimeoutError extends Error {
constructor(message) {
super(message);
this.isAcquireTimeout = true;
}
}
exports.LockAcquireTimeoutError = LockAcquireTimeoutError;
class NavigatorLockAcquireTimeoutError extends LockAcquireTimeoutError {
}
exports.NavigatorLockAcquireTimeoutError = NavigatorLockAcquireTimeoutError;
class ProcessLockAcquireTimeoutError extends LockAcquireTimeoutError {
}
exports.ProcessLockAcquireTimeoutError = ProcessLockAcquireTimeoutError;
/**
* Implements a global exclusive lock using the Navigator LockManager API. It
* is available on all browsers released after 2022-03-15 with Safari being the
* last one to release support. If the API is not available, this function will
* throw. Make sure you check availablility before configuring {@link
* GoTrueClient}.
*
* You can turn on debugging by setting the `supabase.gotrue-js.locks.debug`
* local storage item to `true`.
*
* Internals:
*
* Since the LockManager API does not preserve stack traces for the async
* function passed in the `request` method, a trick is used where acquiring the
* lock releases a previously started promise to run the operation in the `fn`
* function. The lock waits for that promise to finish (with or without error),
* while the function will finally wait for the result anyway.
*
* @param name Name of the lock to be acquired.
* @param acquireTimeout If negative, no timeout. If 0 an error is thrown if
* the lock can't be acquired without waiting. If positive, the lock acquire
* will time out after so many milliseconds. An error is
* a timeout if it has `isAcquireTimeout` set to true.
* @param fn The operation to run once the lock is acquired.
*/
async function navigatorLock(name, acquireTimeout, fn) {
if (exports.internals.debug) {
console.log('@supabase/gotrue-js: navigatorLock: acquire lock', name, acquireTimeout);
}
const abortController = new globalThis.AbortController();
if (acquireTimeout > 0) {
setTimeout(() => {
abortController.abort();
if (exports.internals.debug) {
console.log('@supabase/gotrue-js: navigatorLock acquire timed out', name);
}
}, acquireTimeout);
}
// MDN article: https://developer.mozilla.org/en-US/docs/Web/API/LockManager/request
// Wrapping navigator.locks.request() with a plain Promise is done as some
// libraries like zone.js patch the Promise object to track the execution
// context. However, it appears that most browsers use an internal promise
// implementation when using the navigator.locks.request() API causing them
// to lose context and emit confusing log messages or break certain features.
// This wrapping is believed to help zone.js track the execution context
// better.
return await Promise.resolve().then(() => globalThis.navigator.locks.request(name, acquireTimeout === 0
? {
mode: 'exclusive',
ifAvailable: true,
}
: {
mode: 'exclusive',
signal: abortController.signal,
}, async (lock) => {
if (lock) {
if (exports.internals.debug) {
console.log('@supabase/gotrue-js: navigatorLock: acquired', name, lock.name);
}
try {
return await fn();
}
finally {
if (exports.internals.debug) {
console.log('@supabase/gotrue-js: navigatorLock: released', name, lock.name);
}
}
}
else {
if (acquireTimeout === 0) {
if (exports.internals.debug) {
console.log('@supabase/gotrue-js: navigatorLock: not immediately available', name);
}
throw new NavigatorLockAcquireTimeoutError(`Acquiring an exclusive Navigator LockManager lock "${name}" immediately failed`);
}
else {
if (exports.internals.debug) {
try {
const result = await globalThis.navigator.locks.query();
console.log('@supabase/gotrue-js: Navigator LockManager state', JSON.stringify(result, null, ' '));
}
catch (e) {
console.warn('@supabase/gotrue-js: Error when querying Navigator LockManager state', e);
}
}
// Browser is not following the Navigator LockManager spec, it
// returned a null lock when we didn't use ifAvailable. So we can
// pretend the lock is acquired in the name of backward compatibility
// and user experience and just run the function.
console.warn('@supabase/gotrue-js: Navigator LockManager returned a null lock when using #request without ifAvailable set to true, it appears this browser is not following the LockManager spec https://developer.mozilla.org/en-US/docs/Web/API/LockManager/request');
return await fn();
}
}
}));
}
exports.navigatorLock = navigatorLock;
const PROCESS_LOCKS = {};
/**
* Implements a global exclusive lock that works only in the current process.
* Useful for environments like React Native or other non-browser
* single-process (i.e. no concept of "tabs") environments.
*
* Use {@link #navigatorLock} in browser environments.
*
* @param name Name of the lock to be acquired.
* @param acquireTimeout If negative, no timeout. If 0 an error is thrown if
* the lock can't be acquired without waiting. If positive, the lock acquire
* will time out after so many milliseconds. An error is
* a timeout if it has `isAcquireTimeout` set to true.
* @param fn The operation to run once the lock is acquired.
*/
async function processLock(name, acquireTimeout, fn) {
var _a;
const previousOperation = (_a = PROCESS_LOCKS[name]) !== null && _a !== void 0 ? _a : Promise.resolve();
const currentOperation = Promise.race([
previousOperation.catch(() => {
// ignore error of previous operation that we're waiting to finish
return null;
}),
acquireTimeout >= 0
? new Promise((_, reject) => {
setTimeout(() => {
reject(new ProcessLockAcquireTimeoutError(`Acquring process lock with name "${name}" timed out`));
}, acquireTimeout);
})
: null,
].filter((x) => x))
.catch((e) => {
if (e && e.isAcquireTimeout) {
throw e;
}
return null;
})
.then(async () => {
// previous operations finished and we didn't get a race on the acquire
// timeout, so the current operation can finally start
return await fn();
});
PROCESS_LOCKS[name] = currentOperation.catch(async (e) => {
if (e && e.isAcquireTimeout) {
// if the current operation timed out, it doesn't mean that the previous
// operation finished, so we need contnue waiting for it to finish
await previousOperation;
return null;
}
throw e;
});
// finally wait for the current operation to finish successfully, with an
// error or with an acquire timeout error
return await currentOperation;
}
exports.processLock = processLock;
//# sourceMappingURL=locks.js.map
@@ -1,30 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.polyfillGlobalThis = void 0;
/**
* https://mathiasbynens.be/notes/globalthis
*/
function polyfillGlobalThis() {
if (typeof globalThis === 'object')
return;
try {
Object.defineProperty(Object.prototype, '__magic__', {
get: function () {
return this;
},
configurable: true,
});
// @ts-expect-error 'Allow access to magic'
__magic__.globalThis = __magic__;
// @ts-expect-error 'Allow access to magic'
delete Object.prototype.__magic__;
}
catch (e) {
if (typeof self !== 'undefined') {
// @ts-expect-error 'Allow access to globals'
self.globalThis = self;
}
}
}
exports.polyfillGlobalThis = polyfillGlobalThis;
//# sourceMappingURL=polyfills.js.map
-5
View File
@@ -1,5 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SIGN_OUT_SCOPES = void 0;
exports.SIGN_OUT_SCOPES = ['global', 'local', 'others'];
//# sourceMappingURL=types.js.map
@@ -1,5 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = void 0;
exports.version = '2.71.1';
//# sourceMappingURL=version.js.map
-69
View File
@@ -1,69 +0,0 @@
{
"name": "@supabase/auth-js",
"version": "2.71.1",
"private": false,
"description": "Official client library for Supabase Auth",
"keywords": [
"auth",
"supabase",
"auth",
"authentication"
],
"homepage": "https://github.com/supabase/auth-js",
"bugs": "https://github.com/supabase/auth-js/issues",
"license": "MIT",
"author": "Supabase",
"files": [
"dist",
"src"
],
"main": "dist/main/index.js",
"module": "dist/module/index.js",
"types": "dist/module/index.d.ts",
"repository": "github:supabase/auth-js",
"scripts": {
"clean": "rimraf dist docs",
"coverage": "echo \"run npm test\"",
"format": "prettier --write \"{src,test}/**/*.ts\"",
"build": "genversion src/lib/version.ts --es6 && run-s clean format build:* && run-s lint",
"build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json",
"lint": "eslint ./src/**/* test/**/*.test.ts",
"test": "run-s test:clean test:infra test:suite test:clean",
"test:suite": "npm --prefix ./test run test",
"test:infra": "cd infra && docker compose down && docker compose pull && docker compose up -d && sleep 30",
"test:clean": "cd infra && docker compose down",
"docs": "typedoc src/index.ts --out docs/v2 --excludePrivate --excludeProtected",
"docs:json": "typedoc --json docs/v2/spec.json --excludeExternals --excludePrivate --excludeProtected src/index.ts"
},
"dependencies": {
"@supabase/node-fetch": "^2.6.14"
},
"devDependencies": {
"@types/faker": "^5.1.6",
"@types/jest": "^28.1.6",
"@types/jsonwebtoken": "^8.5.6",
"@types/node": "^18.16.19",
"@types/node-fetch": "^2.6.4",
"@typescript-eslint/eslint-plugin": "^5.30.7",
"@typescript-eslint/parser": "^5.30.7",
"eslint": "^8.20.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0",
"faker": "^5.3.1",
"genversion": "^3.1.1",
"jest": "^28.1.3",
"jest-mock-server": "^0.1.0",
"jsonwebtoken": "^9.0.0",
"npm-run-all": "^4.1.5",
"prettier": "2.7.1",
"rimraf": "^3.0.2",
"semantic-release-plugin-update-version-in-files": "^1.1.0",
"ts-jest": "^28.0.7",
"typedoc": "^0.22.16",
"typescript": "^4.7.4"
}
}
@@ -1,127 +0,0 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FunctionsClient = void 0;
const helper_1 = require("./helper");
const types_1 = require("./types");
class FunctionsClient {
constructor(url, { headers = {}, customFetch, region = types_1.FunctionRegion.Any, } = {}) {
this.url = url;
this.headers = headers;
this.region = region;
this.fetch = (0, helper_1.resolveFetch)(customFetch);
}
/**
* Updates the authorization header
* @param token - the new jwt token sent in the authorisation header
*/
setAuth(token) {
this.headers.Authorization = `Bearer ${token}`;
}
/**
* Invokes a function
* @param functionName - The name of the Function to invoke.
* @param options - Options for invoking the Function.
*/
invoke(functionName, options = {}) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
try {
const { headers, method, body: functionArgs } = options;
let _headers = {};
let { region } = options;
if (!region) {
region = this.region;
}
// Add region as query parameter using URL API
const url = new URL(`${this.url}/${functionName}`);
if (region && region !== 'any') {
_headers['x-region'] = region;
url.searchParams.set('forceFunctionRegion', region);
}
let body;
if (functionArgs &&
((headers && !Object.prototype.hasOwnProperty.call(headers, 'Content-Type')) || !headers)) {
if ((typeof Blob !== 'undefined' && functionArgs instanceof Blob) ||
functionArgs instanceof ArrayBuffer) {
// will work for File as File inherits Blob
// also works for ArrayBuffer as it is the same underlying structure as a Blob
_headers['Content-Type'] = 'application/octet-stream';
body = functionArgs;
}
else if (typeof functionArgs === 'string') {
// plain string
_headers['Content-Type'] = 'text/plain';
body = functionArgs;
}
else if (typeof FormData !== 'undefined' && functionArgs instanceof FormData) {
// don't set content-type headers
// Request will automatically add the right boundary value
body = functionArgs;
}
else {
// default, assume this is JSON
_headers['Content-Type'] = 'application/json';
body = JSON.stringify(functionArgs);
}
}
const response = yield this.fetch(url.toString(), {
method: method || 'POST',
// headers priority is (high to low):
// 1. invoke-level headers
// 2. client-level headers
// 3. default Content-Type header
headers: Object.assign(Object.assign(Object.assign({}, _headers), this.headers), headers),
body,
}).catch((fetchError) => {
throw new types_1.FunctionsFetchError(fetchError);
});
const isRelayError = response.headers.get('x-relay-error');
if (isRelayError && isRelayError === 'true') {
throw new types_1.FunctionsRelayError(response);
}
if (!response.ok) {
throw new types_1.FunctionsHttpError(response);
}
let responseType = ((_a = response.headers.get('Content-Type')) !== null && _a !== void 0 ? _a : 'text/plain').split(';')[0].trim();
let data;
if (responseType === 'application/json') {
data = yield response.json();
}
else if (responseType === 'application/octet-stream') {
data = yield response.blob();
}
else if (responseType === 'text/event-stream') {
data = response;
}
else if (responseType === 'multipart/form-data') {
data = yield response.formData();
}
else {
// default to text
data = yield response.text();
}
return { data, error: null, response };
}
catch (error) {
return {
data: null,
error,
response: error instanceof types_1.FunctionsHttpError || error instanceof types_1.FunctionsRelayError
? error.context
: undefined,
};
}
});
}
}
exports.FunctionsClient = FunctionsClient;
//# sourceMappingURL=FunctionsClient.js.map
-41
View File
@@ -1,41 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveFetch = void 0;
const resolveFetch = (customFetch) => {
let _fetch;
if (customFetch) {
_fetch = customFetch;
}
else if (typeof fetch === 'undefined') {
_fetch = (...args) => Promise.resolve().then(() => __importStar(require('@supabase/node-fetch'))).then(({ default: fetch }) => fetch(...args));
}
else {
_fetch = fetch;
}
return (...args) => _fetch(...args);
};
exports.resolveFetch = resolveFetch;
//# sourceMappingURL=helper.js.map
-12
View File
@@ -1,12 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FunctionRegion = exports.FunctionsRelayError = exports.FunctionsHttpError = exports.FunctionsFetchError = exports.FunctionsError = exports.FunctionsClient = void 0;
var FunctionsClient_1 = require("./FunctionsClient");
Object.defineProperty(exports, "FunctionsClient", { enumerable: true, get: function () { return FunctionsClient_1.FunctionsClient; } });
var types_1 = require("./types");
Object.defineProperty(exports, "FunctionsError", { enumerable: true, get: function () { return types_1.FunctionsError; } });
Object.defineProperty(exports, "FunctionsFetchError", { enumerable: true, get: function () { return types_1.FunctionsFetchError; } });
Object.defineProperty(exports, "FunctionsHttpError", { enumerable: true, get: function () { return types_1.FunctionsHttpError; } });
Object.defineProperty(exports, "FunctionsRelayError", { enumerable: true, get: function () { return types_1.FunctionsRelayError; } });
Object.defineProperty(exports, "FunctionRegion", { enumerable: true, get: function () { return types_1.FunctionRegion; } });
//# sourceMappingURL=index.js.map
-49
View File
@@ -1,49 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FunctionRegion = exports.FunctionsHttpError = exports.FunctionsRelayError = exports.FunctionsFetchError = exports.FunctionsError = void 0;
class FunctionsError extends Error {
constructor(message, name = 'FunctionsError', context) {
super(message);
this.name = name;
this.context = context;
}
}
exports.FunctionsError = FunctionsError;
class FunctionsFetchError extends FunctionsError {
constructor(context) {
super('Failed to send a request to the Edge Function', 'FunctionsFetchError', context);
}
}
exports.FunctionsFetchError = FunctionsFetchError;
class FunctionsRelayError extends FunctionsError {
constructor(context) {
super('Relay Error invoking the Edge Function', 'FunctionsRelayError', context);
}
}
exports.FunctionsRelayError = FunctionsRelayError;
class FunctionsHttpError extends FunctionsError {
constructor(context) {
super('Edge Function returned a non-2xx status code', 'FunctionsHttpError', context);
}
}
exports.FunctionsHttpError = FunctionsHttpError;
// Define the enum for the 'region' property
var FunctionRegion;
(function (FunctionRegion) {
FunctionRegion["Any"] = "any";
FunctionRegion["ApNortheast1"] = "ap-northeast-1";
FunctionRegion["ApNortheast2"] = "ap-northeast-2";
FunctionRegion["ApSouth1"] = "ap-south-1";
FunctionRegion["ApSoutheast1"] = "ap-southeast-1";
FunctionRegion["ApSoutheast2"] = "ap-southeast-2";
FunctionRegion["CaCentral1"] = "ca-central-1";
FunctionRegion["EuCentral1"] = "eu-central-1";
FunctionRegion["EuWest1"] = "eu-west-1";
FunctionRegion["EuWest2"] = "eu-west-2";
FunctionRegion["EuWest3"] = "eu-west-3";
FunctionRegion["SaEast1"] = "sa-east-1";
FunctionRegion["UsEast1"] = "us-east-1";
FunctionRegion["UsWest1"] = "us-west-1";
FunctionRegion["UsWest2"] = "us-west-2";
})(FunctionRegion = exports.FunctionRegion || (exports.FunctionRegion = {}));
//# sourceMappingURL=types.js.map
-65
View File
@@ -1,65 +0,0 @@
{
"name": "@supabase/functions-js",
"version": "2.4.5",
"description": "JS Client library to interact with Supabase Functions.",
"main": "dist/main/index.js",
"module": "dist/module/index.js",
"types": "dist/module/index.d.ts",
"sideEffects": false,
"scripts": {
"clean": "rimraf dist docs/v2",
"format": "prettier --write \"{src,test}/**/*.ts\"",
"build": "run-s clean format build:*",
"build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json",
"docs": "typedoc src/index.ts --out docs/v2",
"docs:json": "typedoc --json docs/v2/spec.json --excludeExternals src/index.ts",
"test": "jest",
"test:coverage": "jest --coverage"
},
"repository": {
"type": "git",
"url": "git+https://github.com/supabase/functions-js.git"
},
"keywords": [
"functions",
"supabase"
],
"author": "Supabase",
"files": [
"dist",
"src"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/supabase/functions-js/issues"
},
"homepage": "https://github.com/supabase/functions-js#readme",
"dependencies": {
"@supabase/node-fetch": "^2.6.14"
},
"devDependencies": {
"@sebbo2002/semantic-release-jsr": "^1.0.0",
"@types/jest": "^28.1.0",
"@types/jsonwebtoken": "^8.5.8",
"@types/node": "^18.7.0",
"genversion": "^3.0.2",
"jest": "^28.1.0",
"jsonwebtoken": "^9.0.0",
"nanoid": "^3.3.1",
"npm-run-all": "^4.1.5",
"openai": "^4.52.5",
"prettier": "^2.6.0",
"rimraf": "^3.0.2",
"semantic-release-plugin-update-version-in-files": "^1.1.0",
"testcontainers": "^8.5.1",
"ts-jest": "^28.0.0",
"ts-node": "^10.9.0",
"ts-test-decorators": "^0.0.6",
"typedoc": "^0.22.13",
"typescript": "^4.6.2"
},
"publishConfig": {
"access": "public"
}
}
File diff suppressed because it is too large Load Diff
-80
View File
@@ -1,80 +0,0 @@
{
"name": "@supabase/node-fetch",
"publishConfig": {
"access": "public"
},
"version": "2.6.15",
"description": "A light-weight module that brings window.fetch to node.js",
"main": "lib/index.js",
"browser": "./browser.js",
"files": [
"lib/index.js",
"lib/index.mjs",
"lib/index.es.js",
"browser.js"
],
"engines": {
"node": "4.x || >=6.0.0"
},
"scripts": {
"build": "cross-env BABEL_ENV=rollup rollup -c",
"prepare": "npm run build",
"test": "cross-env BABEL_ENV=test mocha --require babel-register --throw-deprecation test/test.js",
"report": "cross-env BABEL_ENV=coverage nyc --reporter lcov --reporter text mocha -R spec test/test.js",
"coverage": "cross-env BABEL_ENV=coverage nyc --reporter json --reporter text mocha -R spec test/test.js && codecov -f coverage/coverage-final.json"
},
"repository": "supabase/node-fetch",
"keywords": [
"fetch",
"http",
"promise"
],
"author": "David Frank",
"license": "MIT",
"bugs": {
"url": "https://github.com/supabase/node-fetch/issues"
},
"homepage": "https://github.com/supabase/node-fetch",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"devDependencies": {
"@ungap/url-search-params": "^0.1.2",
"abort-controller": "^1.1.0",
"abortcontroller-polyfill": "^1.3.0",
"babel-core": "^6.26.3",
"babel-plugin-istanbul": "^4.1.6",
"babel-plugin-transform-async-generator-functions": "^6.24.1",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "1.4.0",
"babel-register": "^6.16.3",
"chai": "^3.5.0",
"chai-as-promised": "^7.1.1",
"chai-iterator": "^1.1.1",
"chai-string": "~1.3.0",
"codecov": "3.3.0",
"cross-env": "^5.2.0",
"form-data": "^2.3.3",
"is-builtin-module": "^1.0.0",
"mocha": "^5.0.0",
"nyc": "11.9.0",
"parted": "^0.1.1",
"promise": "^8.0.3",
"resumer": "0.0.0",
"rollup": "^0.63.4",
"rollup-plugin-babel": "^3.0.7",
"string-to-arraybuffer": "^1.0.2",
"teeny-request": "3.7.0"
},
"release": {
"branches": [
"+([0-9]).x",
"main",
"next",
{
"name": "beta",
"prerelease": true
}
]
}
}
@@ -1,221 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// @ts-ignore
const node_fetch_1 = __importDefault(require("@supabase/node-fetch"));
const PostgrestError_1 = __importDefault(require("./PostgrestError"));
class PostgrestBuilder {
constructor(builder) {
this.shouldThrowOnError = false;
this.method = builder.method;
this.url = builder.url;
this.headers = builder.headers;
this.schema = builder.schema;
this.body = builder.body;
this.shouldThrowOnError = builder.shouldThrowOnError;
this.signal = builder.signal;
this.isMaybeSingle = builder.isMaybeSingle;
if (builder.fetch) {
this.fetch = builder.fetch;
}
else if (typeof fetch === 'undefined') {
this.fetch = node_fetch_1.default;
}
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 = Object.assign({}, this.headers);
this.headers[name] = value;
return this;
}
then(onfulfilled, onrejected) {
// https://postgrest.org/en/stable/api.html#switching-schemas
if (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';
}
// NOTE: Invoke w/o `this` to avoid illegal invocation error.
// https://github.com/supabase/postgrest-js/pull/247
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) => {
var _a, _b, _c;
let error = null;
let data = null;
let count = null;
let status = res.status;
let statusText = res.statusText;
if (res.ok) {
if (this.method !== 'HEAD') {
const body = await res.text();
if (body === '') {
// Prefer: return=minimal
}
else if (this.headers['Accept'] === 'text/csv') {
data = body;
}
else if (this.headers['Accept'] &&
this.headers['Accept'].includes('application/vnd.pgrst.plan+text')) {
data = body;
}
else {
data = JSON.parse(body);
}
}
const countHeader = (_a = this.headers['Prefer']) === null || _a === void 0 ? void 0 : _a.match(/count=(exact|planned|estimated)/);
const contentRange = (_b = res.headers.get('content-range')) === null || _b === void 0 ? void 0 : _b.split('/');
if (countHeader && contentRange && contentRange.length > 1) {
count = parseInt(contentRange[1]);
}
// Temporary partial fix for https://github.com/supabase/postgrest-js/issues/361
// Issue persists e.g. for `.insert([...]).select().maybeSingle()`
if (this.isMaybeSingle && this.method === 'GET' && Array.isArray(data)) {
if (data.length > 1) {
error = {
// https://github.com/PostgREST/postgrest/blob/a867d79c42419af16c18c3fb019eba8df992626f/src/PostgREST/Error.hs#L553
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 {
const body = await res.text();
try {
error = JSON.parse(body);
// Workaround for https://github.com/supabase/postgrest-js/issues/295
if (Array.isArray(error) && res.status === 404) {
data = [];
error = null;
status = 200;
statusText = 'OK';
}
}
catch (_d) {
// Workaround for https://github.com/supabase/postgrest-js/issues/295
if (res.status === 404 && body === '') {
status = 204;
statusText = 'No Content';
}
else {
error = {
message: body,
};
}
}
if (error && this.isMaybeSingle && ((_c = error === null || error === void 0 ? void 0 : error.details) === null || _c === void 0 ? void 0 : _c.includes('0 rows'))) {
error = null;
status = 200;
statusText = 'OK';
}
if (error && this.shouldThrowOnError) {
throw new PostgrestError_1.default(error);
}
}
const postgrestResponse = {
error,
data,
count,
status,
statusText,
};
return postgrestResponse;
});
if (!this.shouldThrowOnError) {
res = res.catch((fetchError) => {
var _a, _b, _c;
return ({
error: {
message: `${(_a = fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) !== null && _a !== void 0 ? _a : 'FetchError'}: ${fetchError === null || fetchError === void 0 ? void 0 : fetchError.message}`,
details: `${(_b = fetchError === null || fetchError === void 0 ? void 0 : fetchError.stack) !== null && _b !== void 0 ? _b : ''}`,
hint: '',
code: `${(_c = fetchError === null || fetchError === void 0 ? void 0 : fetchError.code) !== null && _c !== void 0 ? _c : ''}`,
},
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;
}
}
exports.default = PostgrestBuilder;
//# sourceMappingURL=PostgrestBuilder.js.map
@@ -1,122 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const PostgrestQueryBuilder_1 = __importDefault(require("./PostgrestQueryBuilder"));
const PostgrestFilterBuilder_1 = __importDefault(require("./PostgrestFilterBuilder"));
const constants_1 = require("./constants");
/**
* 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.
*/
class PostgrestClient {
// TODO: Add back shouldThrowOnError once we figure out the typings
/**
* 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
*/
constructor(url, { headers = {}, schema, fetch, } = {}) {
this.url = url;
this.headers = Object.assign(Object.assign({}, constants_1.DEFAULT_HEADERS), headers);
this.schemaName = schema;
this.fetch = fetch;
}
/**
* Perform a query on a table or a view.
*
* @param relation - The table or view name to query
*/
from(relation) {
const url = new URL(`${this.url}/${relation}`);
return new PostgrestQueryBuilder_1.default(url, {
headers: Object.assign({}, this.headers),
schema: this.schemaName,
fetch: this.fetch,
});
}
/**
* 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,
});
}
/**
* 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.
*/
rpc(fn, args = {}, { head = false, get = false, count, } = {}) {
let method;
const url = new URL(`${this.url}/rpc/${fn}`);
let body;
if (head || get) {
method = head ? 'HEAD' : 'GET';
Object.entries(args)
// params with undefined value needs to be filtered out, otherwise it'll
// show up as `?param=undefined`
.filter(([_, value]) => value !== undefined)
// array values need special syntax
.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 = Object.assign({}, this.headers);
if (count) {
headers['Prefer'] = `count=${count}`;
}
return new PostgrestFilterBuilder_1.default({
method,
url,
headers,
schema: this.schemaName,
body,
fetch: this.fetch,
allowEmpty: false,
});
}
}
exports.default = PostgrestClient;
//# sourceMappingURL=PostgrestClient.js.map
@@ -1,18 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Error format
*
* {@link https://postgrest.org/en/stable/api.html?highlight=options#errors-and-http-status-codes}
*/
class PostgrestError extends Error {
constructor(context) {
super(context.message);
this.name = 'PostgrestError';
this.details = context.details;
this.hint = context.hint;
this.code = context.code;
}
}
exports.default = PostgrestError;
//# sourceMappingURL=PostgrestError.js.map
@@ -1,381 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const PostgrestTransformBuilder_1 = __importDefault(require("./PostgrestTransformBuilder"));
class PostgrestFilterBuilder extends PostgrestTransformBuilder_1.default {
/**
* 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` 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 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) => {
// handle postgrest reserved characters
// https://postgrest.org/en/v7.0.0/api.html#reserved-characters
if (typeof s === 'string' && new RegExp('[,()]').test(s))
return `"${s}"`;
else
return `${s}`;
})
.join(',');
this.url.searchParams.append(column, `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') {
// 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.{${value.join(',')}}`);
}
else {
// json
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') {
// range
this.url.searchParams.append(column, `cd.${value}`);
}
else if (Array.isArray(value)) {
// array
this.url.searchParams.append(column, `cd.{${value.join(',')}}`);
}
else {
// json
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') {
// range
this.url.searchParams.append(column, `ov.${value}`);
}
else {
// array
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 === undefined ? '' : `(${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;
}
}
exports.default = PostgrestFilterBuilder;
//# sourceMappingURL=PostgrestFilterBuilder.js.map
@@ -1,271 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const PostgrestFilterBuilder_1 = __importDefault(require("./PostgrestFilterBuilder"));
class PostgrestQueryBuilder {
constructor(url, { headers = {}, schema, fetch, }) {
this.url = url;
this.headers = headers;
this.schema = schema;
this.fetch = fetch;
}
/**
* 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.
*/
select(columns, { head = false, count, } = {}) {
const method = head ? 'HEAD' : 'GET';
// Remove whitespaces except when quoted
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);
if (count) {
this.headers['Prefer'] = `count=${count}`;
}
return new PostgrestFilterBuilder_1.default({
method,
url: this.url,
headers: this.headers,
schema: this.schema,
fetch: this.fetch,
allowEmpty: false,
});
}
/**
* 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, } = {}) {
const method = 'POST';
const prefersHeaders = [];
if (this.headers['Prefer']) {
prefersHeaders.push(this.headers['Prefer']);
}
if (count) {
prefersHeaders.push(`count=${count}`);
}
if (!defaultToNull) {
prefersHeaders.push('missing=default');
}
this.headers['Prefer'] = prefersHeaders.join(',');
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}"`);
this.url.searchParams.set('columns', uniqueColumns.join(','));
}
}
return new PostgrestFilterBuilder_1.default({
method,
url: this.url,
headers: this.headers,
schema: this.schema,
body: values,
fetch: this.fetch,
allowEmpty: false,
});
}
/**
* 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.
*/
upsert(values, { onConflict, ignoreDuplicates = false, count, defaultToNull = true, } = {}) {
const method = 'POST';
const prefersHeaders = [`resolution=${ignoreDuplicates ? 'ignore' : 'merge'}-duplicates`];
if (onConflict !== undefined)
this.url.searchParams.set('on_conflict', onConflict);
if (this.headers['Prefer']) {
prefersHeaders.push(this.headers['Prefer']);
}
if (count) {
prefersHeaders.push(`count=${count}`);
}
if (!defaultToNull) {
prefersHeaders.push('missing=default');
}
this.headers['Prefer'] = prefersHeaders.join(',');
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}"`);
this.url.searchParams.set('columns', uniqueColumns.join(','));
}
}
return new PostgrestFilterBuilder_1.default({
method,
url: this.url,
headers: this.headers,
schema: this.schema,
body: values,
fetch: this.fetch,
allowEmpty: false,
});
}
/**
* 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, } = {}) {
const method = 'PATCH';
const prefersHeaders = [];
if (this.headers['Prefer']) {
prefersHeaders.push(this.headers['Prefer']);
}
if (count) {
prefersHeaders.push(`count=${count}`);
}
this.headers['Prefer'] = prefersHeaders.join(',');
return new PostgrestFilterBuilder_1.default({
method,
url: this.url,
headers: this.headers,
schema: this.schema,
body: values,
fetch: this.fetch,
allowEmpty: false,
});
}
/**
* 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, } = {}) {
const method = 'DELETE';
const prefersHeaders = [];
if (count) {
prefersHeaders.push(`count=${count}`);
}
if (this.headers['Prefer']) {
prefersHeaders.unshift(this.headers['Prefer']);
}
this.headers['Prefer'] = prefersHeaders.join(',');
return new PostgrestFilterBuilder_1.default({
method,
url: this.url,
headers: this.headers,
schema: this.schema,
fetch: this.fetch,
allowEmpty: false,
});
}
}
exports.default = PostgrestQueryBuilder;
//# sourceMappingURL=PostgrestQueryBuilder.js.map
@@ -1,222 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const PostgrestBuilder_1 = __importDefault(require("./PostgrestBuilder"));
class PostgrestTransformBuilder extends PostgrestBuilder_1.default {
/**
* 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) {
// Remove whitespaces except when quoted
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);
if (this.headers['Prefer']) {
this.headers['Prefer'] += ',';
}
this.headers['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 === undefined ? '' : 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}`);
// Range is inclusive, so add 1
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['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() {
// Temporary partial fix for https://github.com/supabase/postgrest-js/issues/361
// Issue persists e.g. for `.insert([...]).select().maybeSingle()`
if (this.method === 'GET') {
this.headers['Accept'] = 'application/json';
}
else {
this.headers['Accept'] = 'application/vnd.pgrst.object+json';
}
this.isMaybeSingle = true;
return this;
}
/**
* Return `data` as a string in CSV format.
*/
csv() {
this.headers['Accept'] = 'text/csv';
return this;
}
/**
* Return `data` as an object in [GeoJSON](https://geojson.org) format.
*/
geojson() {
this.headers['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 _a;
const options = [
analyze ? 'analyze' : null,
verbose ? 'verbose' : null,
settings ? 'settings' : null,
buffers ? 'buffers' : null,
wal ? 'wal' : null,
]
.filter(Boolean)
.join('|');
// An Accept header can carry multiple media types but postgrest-js always sends one
const forMediatype = (_a = this.headers['Accept']) !== null && _a !== void 0 ? _a : 'application/json';
this.headers['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() {
var _a;
if (((_a = this.headers['Prefer']) !== null && _a !== void 0 ? _a : '').trim().length > 0) {
this.headers['Prefer'] += ',tx=rollback';
}
else {
this.headers['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;
}
}
exports.default = PostgrestTransformBuilder;
//# sourceMappingURL=PostgrestTransformBuilder.js.map
@@ -1,6 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_HEADERS = void 0;
const version_1 = require("./version");
exports.DEFAULT_HEADERS = { 'X-Client-Info': `postgrest-js/${version_1.version}` };
//# sourceMappingURL=constants.js.map
-28
View File
@@ -1,28 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostgrestError = exports.PostgrestBuilder = exports.PostgrestTransformBuilder = exports.PostgrestFilterBuilder = exports.PostgrestQueryBuilder = exports.PostgrestClient = void 0;
// Always update wrapper.mjs when updating this file.
const PostgrestClient_1 = __importDefault(require("./PostgrestClient"));
exports.PostgrestClient = PostgrestClient_1.default;
const PostgrestQueryBuilder_1 = __importDefault(require("./PostgrestQueryBuilder"));
exports.PostgrestQueryBuilder = PostgrestQueryBuilder_1.default;
const PostgrestFilterBuilder_1 = __importDefault(require("./PostgrestFilterBuilder"));
exports.PostgrestFilterBuilder = PostgrestFilterBuilder_1.default;
const PostgrestTransformBuilder_1 = __importDefault(require("./PostgrestTransformBuilder"));
exports.PostgrestTransformBuilder = PostgrestTransformBuilder_1.default;
const PostgrestBuilder_1 = __importDefault(require("./PostgrestBuilder"));
exports.PostgrestBuilder = PostgrestBuilder_1.default;
const PostgrestError_1 = __importDefault(require("./PostgrestError"));
exports.PostgrestError = PostgrestError_1.default;
exports.default = {
PostgrestClient: PostgrestClient_1.default,
PostgrestQueryBuilder: PostgrestQueryBuilder_1.default,
PostgrestFilterBuilder: PostgrestFilterBuilder_1.default,
PostgrestTransformBuilder: PostgrestTransformBuilder_1.default,
PostgrestBuilder: PostgrestBuilder_1.default,
PostgrestError: PostgrestError_1.default,
};
//# sourceMappingURL=index.js.map
@@ -1,5 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = void 0;
exports.version = '0.0.0-automated';
//# sourceMappingURL=version.js.map
@@ -1,28 +0,0 @@
import index from '../cjs/index.js'
const {
PostgrestClient,
PostgrestQueryBuilder,
PostgrestFilterBuilder,
PostgrestTransformBuilder,
PostgrestBuilder,
PostgrestError,
} = index
export {
PostgrestBuilder,
PostgrestClient,
PostgrestFilterBuilder,
PostgrestQueryBuilder,
PostgrestTransformBuilder,
PostgrestError,
}
// compatibility with CJS output
export default {
PostgrestClient,
PostgrestQueryBuilder,
PostgrestFilterBuilder,
PostgrestTransformBuilder,
PostgrestBuilder,
PostgrestError,
}
-67
View File
@@ -1,67 +0,0 @@
{
"name": "@supabase/postgrest-js",
"version": "1.19.4",
"description": "Isomorphic PostgREST client",
"keywords": [
"postgrest",
"supabase"
],
"homepage": "https://github.com/supabase/postgrest-js",
"bugs": "https://github.com/supabase/postgrest-js/issues",
"license": "MIT",
"author": "Supabase",
"files": [
"dist",
"src"
],
"main": "dist/cjs/index.js",
"module": "dist/esm/wrapper.mjs",
"exports": {
"import": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/esm/wrapper.mjs"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index.js"
}
},
"types": "./dist/cjs/index.d.ts",
"repository": "supabase/postgrest-js",
"scripts": {
"clean": "rimraf dist docs/v2",
"format": "prettier --write \"{src,test}/**/*.ts\" wrapper.mjs",
"format:check": "prettier --check \"{src,test}/**/*.ts\"",
"build": "run-s clean format build:*",
"build:cjs": "tsc -p tsconfig.json",
"build:esm": "cpy wrapper.mjs dist/esm/",
"docs": "typedoc src/index.ts --out docs/v2",
"docs:json": "typedoc --json docs/v2/spec.json --excludeExternals src/index.ts",
"test": "run-s format:check test:types db:clean db:run test:run db:clean && node test/smoke.cjs && node test/smoke.mjs",
"test:run": "jest --runInBand --coverage",
"test:update": "run-s db:clean db:run && jest --runInBand --updateSnapshot && run-s db:clean",
"test:types": "run-s build && tsd --files 'test/**/*.test-d.ts'",
"db:clean": "cd test/db && docker compose down --volumes",
"db:run": "cd test/db && docker compose up --detach && wait-for-localhost 3000"
},
"dependencies": {
"@supabase/node-fetch": "^2.6.14"
},
"devDependencies": {
"@types/jest": "^27.5.1",
"cpy-cli": "^5.0.0",
"jest": "^28.1.0",
"node-abort-controller": "^3.0.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.6.2",
"rimraf": "^3.0.2",
"semantic-release-plugin-update-version-in-files": "^1.1.0",
"ts-expect": "^1.3.0",
"ts-jest": "^28.0.3",
"tsd": "^0.31.2",
"type-fest": "^4.32.0",
"typedoc": "^0.22.16",
"typescript": "^4.5.5",
"wait-for-localhost-cli": "^3.0.0"
}
}
@@ -1,580 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.REALTIME_CHANNEL_STATES = exports.REALTIME_SUBSCRIBE_STATES = exports.REALTIME_LISTEN_TYPES = exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = void 0;
const constants_1 = require("./lib/constants");
const push_1 = __importDefault(require("./lib/push"));
const timer_1 = __importDefault(require("./lib/timer"));
const RealtimePresence_1 = __importDefault(require("./RealtimePresence"));
const Transformers = __importStar(require("./lib/transformers"));
const transformers_1 = require("./lib/transformers");
var REALTIME_POSTGRES_CHANGES_LISTEN_EVENT;
(function (REALTIME_POSTGRES_CHANGES_LISTEN_EVENT) {
REALTIME_POSTGRES_CHANGES_LISTEN_EVENT["ALL"] = "*";
REALTIME_POSTGRES_CHANGES_LISTEN_EVENT["INSERT"] = "INSERT";
REALTIME_POSTGRES_CHANGES_LISTEN_EVENT["UPDATE"] = "UPDATE";
REALTIME_POSTGRES_CHANGES_LISTEN_EVENT["DELETE"] = "DELETE";
})(REALTIME_POSTGRES_CHANGES_LISTEN_EVENT || (exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = {}));
var REALTIME_LISTEN_TYPES;
(function (REALTIME_LISTEN_TYPES) {
REALTIME_LISTEN_TYPES["BROADCAST"] = "broadcast";
REALTIME_LISTEN_TYPES["PRESENCE"] = "presence";
REALTIME_LISTEN_TYPES["POSTGRES_CHANGES"] = "postgres_changes";
REALTIME_LISTEN_TYPES["SYSTEM"] = "system";
})(REALTIME_LISTEN_TYPES || (exports.REALTIME_LISTEN_TYPES = REALTIME_LISTEN_TYPES = {}));
var REALTIME_SUBSCRIBE_STATES;
(function (REALTIME_SUBSCRIBE_STATES) {
REALTIME_SUBSCRIBE_STATES["SUBSCRIBED"] = "SUBSCRIBED";
REALTIME_SUBSCRIBE_STATES["TIMED_OUT"] = "TIMED_OUT";
REALTIME_SUBSCRIBE_STATES["CLOSED"] = "CLOSED";
REALTIME_SUBSCRIBE_STATES["CHANNEL_ERROR"] = "CHANNEL_ERROR";
})(REALTIME_SUBSCRIBE_STATES || (exports.REALTIME_SUBSCRIBE_STATES = REALTIME_SUBSCRIBE_STATES = {}));
exports.REALTIME_CHANNEL_STATES = constants_1.CHANNEL_STATES;
/** A channel is the basic building block of Realtime
* and narrows the scope of data flow to subscribed clients.
* You can think of a channel as a chatroom where participants are able to see who's online
* and send and receive messages.
*/
class RealtimeChannel {
constructor(
/** Topic name can be any string. */
topic, params = { config: {} }, socket) {
this.topic = topic;
this.params = params;
this.socket = socket;
this.bindings = {};
this.state = constants_1.CHANNEL_STATES.closed;
this.joinedOnce = false;
this.pushBuffer = [];
this.subTopic = topic.replace(/^realtime:/i, '');
this.params.config = Object.assign({
broadcast: { ack: false, self: false },
presence: { key: '', enabled: false },
private: false,
}, params.config);
this.timeout = this.socket.timeout;
this.joinPush = new push_1.default(this, constants_1.CHANNEL_EVENTS.join, this.params, this.timeout);
this.rejoinTimer = new timer_1.default(() => this._rejoinUntilConnected(), this.socket.reconnectAfterMs);
this.joinPush.receive('ok', () => {
this.state = constants_1.CHANNEL_STATES.joined;
this.rejoinTimer.reset();
this.pushBuffer.forEach((pushEvent) => pushEvent.send());
this.pushBuffer = [];
});
this._onClose(() => {
this.rejoinTimer.reset();
this.socket.log('channel', `close ${this.topic} ${this._joinRef()}`);
this.state = constants_1.CHANNEL_STATES.closed;
this.socket._remove(this);
});
this._onError((reason) => {
if (this._isLeaving() || this._isClosed()) {
return;
}
this.socket.log('channel', `error ${this.topic}`, reason);
this.state = constants_1.CHANNEL_STATES.errored;
this.rejoinTimer.scheduleTimeout();
});
this.joinPush.receive('timeout', () => {
if (!this._isJoining()) {
return;
}
this.socket.log('channel', `timeout ${this.topic}`, this.joinPush.timeout);
this.state = constants_1.CHANNEL_STATES.errored;
this.rejoinTimer.scheduleTimeout();
});
this.joinPush.receive('error', (reason) => {
if (this._isLeaving() || this._isClosed()) {
return;
}
this.socket.log('channel', `error ${this.topic}`, reason);
this.state = constants_1.CHANNEL_STATES.errored;
this.rejoinTimer.scheduleTimeout();
});
this._on(constants_1.CHANNEL_EVENTS.reply, {}, (payload, ref) => {
this._trigger(this._replyEventName(ref), payload);
});
this.presence = new RealtimePresence_1.default(this);
this.broadcastEndpointURL = (0, transformers_1.httpEndpointURL)(this.socket.endPoint);
this.private = this.params.config.private || false;
}
/** Subscribe registers your client with the server */
subscribe(callback, timeout = this.timeout) {
var _a, _b;
if (!this.socket.isConnected()) {
this.socket.connect();
}
if (this.state == constants_1.CHANNEL_STATES.closed) {
const { config: { broadcast, presence, private: isPrivate }, } = this.params;
const postgres_changes = (_b = (_a = this.bindings.postgres_changes) === null || _a === void 0 ? void 0 : _a.map((r) => r.filter)) !== null && _b !== void 0 ? _b : [];
const presence_enabled = !!this.bindings[REALTIME_LISTEN_TYPES.PRESENCE] &&
this.bindings[REALTIME_LISTEN_TYPES.PRESENCE].length > 0;
const accessTokenPayload = {};
const config = {
broadcast,
presence: Object.assign(Object.assign({}, presence), { enabled: presence_enabled }),
postgres_changes,
private: isPrivate,
};
if (this.socket.accessTokenValue) {
accessTokenPayload.access_token = this.socket.accessTokenValue;
}
this._onError((e) => callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, e));
this._onClose(() => callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CLOSED));
this.updateJoinPayload(Object.assign({ config }, accessTokenPayload));
this.joinedOnce = true;
this._rejoin(timeout);
this.joinPush
.receive('ok', async ({ postgres_changes }) => {
var _a;
this.socket.setAuth();
if (postgres_changes === undefined) {
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED);
return;
}
else {
const clientPostgresBindings = this.bindings.postgres_changes;
const bindingsLen = (_a = clientPostgresBindings === null || clientPostgresBindings === void 0 ? void 0 : clientPostgresBindings.length) !== null && _a !== void 0 ? _a : 0;
const newPostgresBindings = [];
for (let i = 0; i < bindingsLen; i++) {
const clientPostgresBinding = clientPostgresBindings[i];
const { filter: { event, schema, table, filter }, } = clientPostgresBinding;
const serverPostgresFilter = postgres_changes && postgres_changes[i];
if (serverPostgresFilter &&
serverPostgresFilter.event === event &&
serverPostgresFilter.schema === schema &&
serverPostgresFilter.table === table &&
serverPostgresFilter.filter === filter) {
newPostgresBindings.push(Object.assign(Object.assign({}, clientPostgresBinding), { id: serverPostgresFilter.id }));
}
else {
this.unsubscribe();
this.state = constants_1.CHANNEL_STATES.errored;
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error('mismatch between server and client bindings for postgres changes'));
return;
}
}
this.bindings.postgres_changes = newPostgresBindings;
callback && callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED);
return;
}
})
.receive('error', (error) => {
this.state = constants_1.CHANNEL_STATES.errored;
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error(JSON.stringify(Object.values(error).join(', ') || 'error')));
return;
})
.receive('timeout', () => {
callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.TIMED_OUT);
return;
});
}
return this;
}
presenceState() {
return this.presence.state;
}
async track(payload, opts = {}) {
return await this.send({
type: 'presence',
event: 'track',
payload,
}, opts.timeout || this.timeout);
}
async untrack(opts = {}) {
return await this.send({
type: 'presence',
event: 'untrack',
}, opts);
}
on(type, filter, callback) {
if (this.state === constants_1.CHANNEL_STATES.joined &&
type === REALTIME_LISTEN_TYPES.PRESENCE) {
this.socket.log('channel', `resubscribe to ${this.topic} due to change in presence callbacks on joined channel`);
this.unsubscribe().then(() => this.subscribe());
}
return this._on(type, filter, callback);
}
/**
* Sends a message into the channel.
*
* @param args Arguments to send to channel
* @param args.type The type of event to send
* @param args.event The name of the event being sent
* @param args.payload Payload to be sent
* @param opts Options to be used during the send process
*/
async send(args, opts = {}) {
var _a, _b;
if (!this._canPush() && args.type === 'broadcast') {
const { event, payload: endpoint_payload } = args;
const authorization = this.socket.accessTokenValue
? `Bearer ${this.socket.accessTokenValue}`
: '';
const options = {
method: 'POST',
headers: {
Authorization: authorization,
apikey: this.socket.apiKey ? this.socket.apiKey : '',
'Content-Type': 'application/json',
},
body: JSON.stringify({
messages: [
{
topic: this.subTopic,
event,
payload: endpoint_payload,
private: this.private,
},
],
}),
};
try {
const response = await this._fetchWithTimeout(this.broadcastEndpointURL, options, (_a = opts.timeout) !== null && _a !== void 0 ? _a : this.timeout);
await ((_b = response.body) === null || _b === void 0 ? void 0 : _b.cancel());
return response.ok ? 'ok' : 'error';
}
catch (error) {
if (error.name === 'AbortError') {
return 'timed out';
}
else {
return 'error';
}
}
}
else {
return new Promise((resolve) => {
var _a, _b, _c;
const push = this._push(args.type, args, opts.timeout || this.timeout);
if (args.type === 'broadcast' && !((_c = (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) {
resolve('ok');
}
push.receive('ok', () => resolve('ok'));
push.receive('error', () => resolve('error'));
push.receive('timeout', () => resolve('timed out'));
});
}
}
updateJoinPayload(payload) {
this.joinPush.updatePayload(payload);
}
/**
* Leaves the channel.
*
* Unsubscribes from server events, and instructs channel to terminate on server.
* Triggers onClose() hooks.
*
* To receive leave acknowledgements, use the a `receive` hook to bind to the server ack, ie:
* channel.unsubscribe().receive("ok", () => alert("left!") )
*/
unsubscribe(timeout = this.timeout) {
this.state = constants_1.CHANNEL_STATES.leaving;
const onClose = () => {
this.socket.log('channel', `leave ${this.topic}`);
this._trigger(constants_1.CHANNEL_EVENTS.close, 'leave', this._joinRef());
};
this.joinPush.destroy();
let leavePush = null;
return new Promise((resolve) => {
leavePush = new push_1.default(this, constants_1.CHANNEL_EVENTS.leave, {}, timeout);
leavePush
.receive('ok', () => {
onClose();
resolve('ok');
})
.receive('timeout', () => {
onClose();
resolve('timed out');
})
.receive('error', () => {
resolve('error');
});
leavePush.send();
if (!this._canPush()) {
leavePush.trigger('ok', {});
}
}).finally(() => {
leavePush === null || leavePush === void 0 ? void 0 : leavePush.destroy();
});
}
/**
* Teardown the channel.
*
* Destroys and stops related timers.
*/
teardown() {
this.pushBuffer.forEach((push) => push.destroy());
this.pushBuffer = [];
this.rejoinTimer.reset();
this.joinPush.destroy();
this.state = constants_1.CHANNEL_STATES.closed;
this.bindings = {};
}
/** @internal */
async _fetchWithTimeout(url, options, timeout) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
const response = await this.socket.fetch(url, Object.assign(Object.assign({}, options), { signal: controller.signal }));
clearTimeout(id);
return response;
}
/** @internal */
_push(event, payload, timeout = this.timeout) {
if (!this.joinedOnce) {
throw `tried to push '${event}' to '${this.topic}' before joining. Use channel.subscribe() before pushing events`;
}
let pushEvent = new push_1.default(this, event, payload, timeout);
if (this._canPush()) {
pushEvent.send();
}
else {
this._addToPushBuffer(pushEvent);
}
return pushEvent;
}
/** @internal */
_addToPushBuffer(pushEvent) {
pushEvent.startTimeout();
this.pushBuffer.push(pushEvent);
// Enforce buffer size limit
if (this.pushBuffer.length > constants_1.MAX_PUSH_BUFFER_SIZE) {
const removedPush = this.pushBuffer.shift();
if (removedPush) {
removedPush.destroy();
this.socket.log('channel', `discarded push due to buffer overflow: ${removedPush.event}`, removedPush.payload);
}
}
}
/**
* Overridable message hook
*
* Receives all events for specialized message handling before dispatching to the channel callbacks.
* Must return the payload, modified or unmodified.
*
* @internal
*/
_onMessage(_event, payload, _ref) {
return payload;
}
/** @internal */
_isMember(topic) {
return this.topic === topic;
}
/** @internal */
_joinRef() {
return this.joinPush.ref;
}
/** @internal */
_trigger(type, payload, ref) {
var _a, _b;
const typeLower = type.toLocaleLowerCase();
const { close, error, leave, join } = constants_1.CHANNEL_EVENTS;
const events = [close, error, leave, join];
if (ref && events.indexOf(typeLower) >= 0 && ref !== this._joinRef()) {
return;
}
let handledPayload = this._onMessage(typeLower, payload, ref);
if (payload && !handledPayload) {
throw 'channel onMessage callbacks must return the payload, modified or unmodified';
}
if (['insert', 'update', 'delete'].includes(typeLower)) {
(_a = this.bindings.postgres_changes) === null || _a === void 0 ? void 0 : _a.filter((bind) => {
var _a, _b, _c;
return (((_a = bind.filter) === null || _a === void 0 ? void 0 : _a.event) === '*' ||
((_c = (_b = bind.filter) === null || _b === void 0 ? void 0 : _b.event) === null || _c === void 0 ? void 0 : _c.toLocaleLowerCase()) === typeLower);
}).map((bind) => bind.callback(handledPayload, ref));
}
else {
(_b = this.bindings[typeLower]) === null || _b === void 0 ? void 0 : _b.filter((bind) => {
var _a, _b, _c, _d, _e, _f;
if (['broadcast', 'presence', 'postgres_changes'].includes(typeLower)) {
if ('id' in bind) {
const bindId = bind.id;
const bindEvent = (_a = bind.filter) === null || _a === void 0 ? void 0 : _a.event;
return (bindId &&
((_b = payload.ids) === null || _b === void 0 ? void 0 : _b.includes(bindId)) &&
(bindEvent === '*' ||
(bindEvent === null || bindEvent === void 0 ? void 0 : bindEvent.toLocaleLowerCase()) ===
((_c = payload.data) === null || _c === void 0 ? void 0 : _c.type.toLocaleLowerCase())));
}
else {
const bindEvent = (_e = (_d = bind === null || bind === void 0 ? void 0 : bind.filter) === null || _d === void 0 ? void 0 : _d.event) === null || _e === void 0 ? void 0 : _e.toLocaleLowerCase();
return (bindEvent === '*' ||
bindEvent === ((_f = payload === null || payload === void 0 ? void 0 : payload.event) === null || _f === void 0 ? void 0 : _f.toLocaleLowerCase()));
}
}
else {
return bind.type.toLocaleLowerCase() === typeLower;
}
}).map((bind) => {
if (typeof handledPayload === 'object' && 'ids' in handledPayload) {
const postgresChanges = handledPayload.data;
const { schema, table, commit_timestamp, type, errors } = postgresChanges;
const enrichedPayload = {
schema: schema,
table: table,
commit_timestamp: commit_timestamp,
eventType: type,
new: {},
old: {},
errors: errors,
};
handledPayload = Object.assign(Object.assign({}, enrichedPayload), this._getPayloadRecords(postgresChanges));
}
bind.callback(handledPayload, ref);
});
}
}
/** @internal */
_isClosed() {
return this.state === constants_1.CHANNEL_STATES.closed;
}
/** @internal */
_isJoined() {
return this.state === constants_1.CHANNEL_STATES.joined;
}
/** @internal */
_isJoining() {
return this.state === constants_1.CHANNEL_STATES.joining;
}
/** @internal */
_isLeaving() {
return this.state === constants_1.CHANNEL_STATES.leaving;
}
/** @internal */
_replyEventName(ref) {
return `chan_reply_${ref}`;
}
/** @internal */
_on(type, filter, callback) {
const typeLower = type.toLocaleLowerCase();
const binding = {
type: typeLower,
filter: filter,
callback: callback,
};
if (this.bindings[typeLower]) {
this.bindings[typeLower].push(binding);
}
else {
this.bindings[typeLower] = [binding];
}
return this;
}
/** @internal */
_off(type, filter) {
const typeLower = type.toLocaleLowerCase();
if (this.bindings[typeLower]) {
this.bindings[typeLower] = this.bindings[typeLower].filter((bind) => {
var _a;
return !(((_a = bind.type) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) === typeLower &&
RealtimeChannel.isEqual(bind.filter, filter));
});
}
return this;
}
/** @internal */
static isEqual(obj1, obj2) {
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
return false;
}
for (const k in obj1) {
if (obj1[k] !== obj2[k]) {
return false;
}
}
return true;
}
/** @internal */
_rejoinUntilConnected() {
this.rejoinTimer.scheduleTimeout();
if (this.socket.isConnected()) {
this._rejoin();
}
}
/**
* Registers a callback that will be executed when the channel closes.
*
* @internal
*/
_onClose(callback) {
this._on(constants_1.CHANNEL_EVENTS.close, {}, callback);
}
/**
* Registers a callback that will be executed when the channel encounteres an error.
*
* @internal
*/
_onError(callback) {
this._on(constants_1.CHANNEL_EVENTS.error, {}, (reason) => callback(reason));
}
/**
* Returns `true` if the socket is connected and the channel has been joined.
*
* @internal
*/
_canPush() {
return this.socket.isConnected() && this._isJoined();
}
/** @internal */
_rejoin(timeout = this.timeout) {
if (this._isLeaving()) {
return;
}
this.socket._leaveOpenTopic(this.topic);
this.state = constants_1.CHANNEL_STATES.joining;
this.joinPush.resend(timeout);
}
/** @internal */
_getPayloadRecords(payload) {
const records = {
new: {},
old: {},
};
if (payload.type === 'INSERT' || payload.type === 'UPDATE') {
records.new = Transformers.convertChangeData(payload.columns, payload.record);
}
if (payload.type === 'UPDATE' || payload.type === 'DELETE') {
records.old = Transformers.convertChangeData(payload.columns, payload.old_record);
}
return records;
}
}
exports.default = RealtimeChannel;
//# sourceMappingURL=RealtimeChannel.js.map
@@ -1,737 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const websocket_factory_1 = __importDefault(require("./lib/websocket-factory"));
const constants_1 = require("./lib/constants");
const serializer_1 = __importDefault(require("./lib/serializer"));
const timer_1 = __importDefault(require("./lib/timer"));
const transformers_1 = require("./lib/transformers");
const RealtimeChannel_1 = __importDefault(require("./RealtimeChannel"));
const noop = () => { };
// Connection-related constants
const CONNECTION_TIMEOUTS = {
HEARTBEAT_INTERVAL: 25000,
RECONNECT_DELAY: 10,
HEARTBEAT_TIMEOUT_FALLBACK: 100,
};
const RECONNECT_INTERVALS = [1000, 2000, 5000, 10000];
const DEFAULT_RECONNECT_FALLBACK = 10000;
const WORKER_SCRIPT = `
addEventListener("message", (e) => {
if (e.data.event === "start") {
setInterval(() => postMessage({ event: "keepAlive" }), e.data.interval);
}
});`;
class RealtimeClient {
/**
* Initializes the Socket.
*
* @param endPoint The string WebSocket endpoint, ie, "ws://example.com/socket", "wss://example.com", "/socket" (inherited host & protocol)
* @param httpEndpoint The string HTTP endpoint, ie, "https://example.com", "/" (inherited host & protocol)
* @param options.transport The Websocket Transport, for example WebSocket. This can be a custom implementation
* @param options.timeout The default timeout in milliseconds to trigger push timeouts.
* @param options.params The optional params to pass when connecting.
* @param options.headers Deprecated: headers cannot be set on websocket connections and this option will be removed in the future.
* @param options.heartbeatIntervalMs The millisec interval to send a heartbeat message.
* @param options.logger The optional function for specialized logging, ie: logger: (kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }
* @param options.logLevel Sets the log level for Realtime
* @param options.encode The function to encode outgoing messages. Defaults to JSON: (payload, callback) => callback(JSON.stringify(payload))
* @param options.decode The function to decode incoming messages. Defaults to Serializer's decode.
* @param options.reconnectAfterMs he optional function that returns the millsec reconnect interval. Defaults to stepped backoff off.
* @param options.worker Use Web Worker to set a side flow. Defaults to false.
* @param options.workerUrl The URL of the worker script. Defaults to https://realtime.supabase.com/worker.js that includes a heartbeat event call to keep the connection alive.
*/
constructor(endPoint, options) {
var _a;
this.accessTokenValue = null;
this.apiKey = null;
this.channels = new Array();
this.endPoint = '';
this.httpEndpoint = '';
/** @deprecated headers cannot be set on websocket connections */
this.headers = {};
this.params = {};
this.timeout = constants_1.DEFAULT_TIMEOUT;
this.transport = null;
this.heartbeatIntervalMs = CONNECTION_TIMEOUTS.HEARTBEAT_INTERVAL;
this.heartbeatTimer = undefined;
this.pendingHeartbeatRef = null;
this.heartbeatCallback = noop;
this.ref = 0;
this.reconnectTimer = null;
this.logger = noop;
this.conn = null;
this.sendBuffer = [];
this.serializer = new serializer_1.default();
this.stateChangeCallbacks = {
open: [],
close: [],
error: [],
message: [],
};
this.accessToken = null;
this._connectionState = 'disconnected';
this._wasManualDisconnect = false;
this._authPromise = null;
/**
* Use either custom fetch, if provided, or default fetch to make HTTP requests
*
* @internal
*/
this._resolveFetch = (customFetch) => {
let _fetch;
if (customFetch) {
_fetch = customFetch;
}
else if (typeof fetch === 'undefined') {
// Node.js environment without native fetch
_fetch = (...args) => Promise.resolve(`${'@supabase/node-fetch'}`).then(s => __importStar(require(s))).then(({ default: fetch }) => fetch(...args))
.catch((error) => {
throw new Error(`Failed to load @supabase/node-fetch: ${error.message}. ` +
`This is required for HTTP requests in Node.js environments without native fetch.`);
});
}
else {
_fetch = fetch;
}
return (...args) => _fetch(...args);
};
// Validate required parameters
if (!((_a = options === null || options === void 0 ? void 0 : options.params) === null || _a === void 0 ? void 0 : _a.apikey)) {
throw new Error('API key is required to connect to Realtime');
}
this.apiKey = options.params.apikey;
// Initialize endpoint URLs
this.endPoint = `${endPoint}/${constants_1.TRANSPORTS.websocket}`;
this.httpEndpoint = (0, transformers_1.httpEndpointURL)(endPoint);
this._initializeOptions(options);
this._setupReconnectionTimer();
this.fetch = this._resolveFetch(options === null || options === void 0 ? void 0 : options.fetch);
}
/**
* Connects the socket, unless already connected.
*/
connect() {
// Skip if already connecting, disconnecting, or connected
if (this.isConnecting() ||
this.isDisconnecting() ||
(this.conn !== null && this.isConnected())) {
return;
}
this._setConnectionState('connecting');
this._setAuthSafely('connect');
// Establish WebSocket connection
if (this.transport) {
// Use custom transport if provided
this.conn = new this.transport(this.endpointURL());
}
else {
// Try to use native WebSocket
try {
this.conn = websocket_factory_1.default.createWebSocket(this.endpointURL());
}
catch (error) {
this._setConnectionState('disconnected');
const errorMessage = error.message;
// Provide helpful error message based on environment
if (errorMessage.includes('Node.js')) {
throw new Error(`${errorMessage}\n\n` +
'To use Realtime in Node.js, you need to provide a WebSocket implementation:\n\n' +
'Option 1: Use Node.js 22+ which has native WebSocket support\n' +
'Option 2: Install and provide the "ws" package:\n\n' +
' npm install ws\n\n' +
' import ws from "ws"\n' +
' const client = new RealtimeClient(url, {\n' +
' ...options,\n' +
' transport: ws\n' +
' })');
}
throw new Error(`WebSocket not available: ${errorMessage}`);
}
}
this._setupConnectionHandlers();
}
/**
* Returns the URL of the websocket.
* @returns string The URL of the websocket.
*/
endpointURL() {
return this._appendParams(this.endPoint, Object.assign({}, this.params, { vsn: constants_1.VSN }));
}
/**
* Disconnects the socket.
*
* @param code A numeric status code to send on disconnect.
* @param reason A custom reason for the disconnect.
*/
disconnect(code, reason) {
if (this.isDisconnecting()) {
return;
}
this._setConnectionState('disconnecting', true);
if (this.conn) {
// Setup fallback timer to prevent hanging in disconnecting state
const fallbackTimer = setTimeout(() => {
this._setConnectionState('disconnected');
}, 100);
this.conn.onclose = () => {
clearTimeout(fallbackTimer);
this._setConnectionState('disconnected');
};
// Close the WebSocket connection
if (code) {
this.conn.close(code, reason !== null && reason !== void 0 ? reason : '');
}
else {
this.conn.close();
}
this._teardownConnection();
}
else {
this._setConnectionState('disconnected');
}
}
/**
* Returns all created channels
*/
getChannels() {
return this.channels;
}
/**
* Unsubscribes and removes a single channel
* @param channel A RealtimeChannel instance
*/
async removeChannel(channel) {
const status = await channel.unsubscribe();
if (this.channels.length === 0) {
this.disconnect();
}
return status;
}
/**
* Unsubscribes and removes all channels
*/
async removeAllChannels() {
const values_1 = await Promise.all(this.channels.map((channel) => channel.unsubscribe()));
this.channels = [];
this.disconnect();
return values_1;
}
/**
* Logs the message.
*
* For customized logging, `this.logger` can be overridden.
*/
log(kind, msg, data) {
this.logger(kind, msg, data);
}
/**
* Returns the current state of the socket.
*/
connectionState() {
switch (this.conn && this.conn.readyState) {
case constants_1.SOCKET_STATES.connecting:
return constants_1.CONNECTION_STATE.Connecting;
case constants_1.SOCKET_STATES.open:
return constants_1.CONNECTION_STATE.Open;
case constants_1.SOCKET_STATES.closing:
return constants_1.CONNECTION_STATE.Closing;
default:
return constants_1.CONNECTION_STATE.Closed;
}
}
/**
* Returns `true` is the connection is open.
*/
isConnected() {
return this.connectionState() === constants_1.CONNECTION_STATE.Open;
}
/**
* Returns `true` if the connection is currently connecting.
*/
isConnecting() {
return this._connectionState === 'connecting';
}
/**
* Returns `true` if the connection is currently disconnecting.
*/
isDisconnecting() {
return this._connectionState === 'disconnecting';
}
channel(topic, params = { config: {} }) {
const realtimeTopic = `realtime:${topic}`;
const exists = this.getChannels().find((c) => c.topic === realtimeTopic);
if (!exists) {
const chan = new RealtimeChannel_1.default(`realtime:${topic}`, params, this);
this.channels.push(chan);
return chan;
}
else {
return exists;
}
}
/**
* Push out a message if the socket is connected.
*
* If the socket is not connected, the message gets enqueued within a local buffer, and sent out when a connection is next established.
*/
push(data) {
const { topic, event, payload, ref } = data;
const callback = () => {
this.encode(data, (result) => {
var _a;
(_a = this.conn) === null || _a === void 0 ? void 0 : _a.send(result);
});
};
this.log('push', `${topic} ${event} (${ref})`, payload);
if (this.isConnected()) {
callback();
}
else {
this.sendBuffer.push(callback);
}
}
/**
* Sets the JWT access token used for channel subscription authorization and Realtime RLS.
*
* If param is null it will use the `accessToken` callback function or the token set on the client.
*
* On callback used, it will set the value of the token internal to the client.
*
* @param token A JWT string to override the token set on the client.
*/
async setAuth(token = null) {
this._authPromise = this._performAuth(token);
try {
await this._authPromise;
}
finally {
this._authPromise = null;
}
}
/**
* Sends a heartbeat message if the socket is connected.
*/
async sendHeartbeat() {
var _a;
if (!this.isConnected()) {
this.heartbeatCallback('disconnected');
return;
}
// Handle heartbeat timeout and force reconnection if needed
if (this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;
this.log('transport', 'heartbeat timeout. Attempting to re-establish connection');
this.heartbeatCallback('timeout');
// Force reconnection after heartbeat timeout
this._wasManualDisconnect = false;
(_a = this.conn) === null || _a === void 0 ? void 0 : _a.close(constants_1.WS_CLOSE_NORMAL, 'heartbeat timeout');
setTimeout(() => {
var _a;
if (!this.isConnected()) {
(_a = this.reconnectTimer) === null || _a === void 0 ? void 0 : _a.scheduleTimeout();
}
}, CONNECTION_TIMEOUTS.HEARTBEAT_TIMEOUT_FALLBACK);
return;
}
// Send heartbeat message to server
this.pendingHeartbeatRef = this._makeRef();
this.push({
topic: 'phoenix',
event: 'heartbeat',
payload: {},
ref: this.pendingHeartbeatRef,
});
this.heartbeatCallback('sent');
this._setAuthSafely('heartbeat');
}
onHeartbeat(callback) {
this.heartbeatCallback = callback;
}
/**
* Flushes send buffer
*/
flushSendBuffer() {
if (this.isConnected() && this.sendBuffer.length > 0) {
this.sendBuffer.forEach((callback) => callback());
this.sendBuffer = [];
}
}
/**
* Return the next message ref, accounting for overflows
*
* @internal
*/
_makeRef() {
let newRef = this.ref + 1;
if (newRef === this.ref) {
this.ref = 0;
}
else {
this.ref = newRef;
}
return this.ref.toString();
}
/**
* Unsubscribe from channels with the specified topic.
*
* @internal
*/
_leaveOpenTopic(topic) {
let dupChannel = this.channels.find((c) => c.topic === topic && (c._isJoined() || c._isJoining()));
if (dupChannel) {
this.log('transport', `leaving duplicate topic "${topic}"`);
dupChannel.unsubscribe();
}
}
/**
* Removes a subscription from the socket.
*
* @param channel An open subscription.
*
* @internal
*/
_remove(channel) {
this.channels = this.channels.filter((c) => c.topic !== channel.topic);
}
/** @internal */
_onConnMessage(rawMessage) {
this.decode(rawMessage.data, (msg) => {
// Handle heartbeat responses
if (msg.topic === 'phoenix' && msg.event === 'phx_reply') {
this.heartbeatCallback(msg.payload.status === 'ok' ? 'ok' : 'error');
}
// Handle pending heartbeat reference cleanup
if (msg.ref && msg.ref === this.pendingHeartbeatRef) {
this.pendingHeartbeatRef = null;
}
// Log incoming message
const { topic, event, payload, ref } = msg;
const refString = ref ? `(${ref})` : '';
const status = payload.status || '';
this.log('receive', `${status} ${topic} ${event} ${refString}`.trim(), payload);
// Route message to appropriate channels
this.channels
.filter((channel) => channel._isMember(topic))
.forEach((channel) => channel._trigger(event, payload, ref));
this._triggerStateCallbacks('message', msg);
});
}
/**
* Clear specific timer
* @internal
*/
_clearTimer(timer) {
var _a;
if (timer === 'heartbeat' && this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = undefined;
}
else if (timer === 'reconnect') {
(_a = this.reconnectTimer) === null || _a === void 0 ? void 0 : _a.reset();
}
}
/**
* Clear all timers
* @internal
*/
_clearAllTimers() {
this._clearTimer('heartbeat');
this._clearTimer('reconnect');
}
/**
* Setup connection handlers for WebSocket events
* @internal
*/
_setupConnectionHandlers() {
if (!this.conn)
return;
// Set binary type if supported (browsers and most WebSocket implementations)
if ('binaryType' in this.conn) {
;
this.conn.binaryType = 'arraybuffer';
}
this.conn.onopen = () => this._onConnOpen();
this.conn.onerror = (error) => this._onConnError(error);
this.conn.onmessage = (event) => this._onConnMessage(event);
this.conn.onclose = (event) => this._onConnClose(event);
}
/**
* Teardown connection and cleanup resources
* @internal
*/
_teardownConnection() {
if (this.conn) {
this.conn.onopen = null;
this.conn.onerror = null;
this.conn.onmessage = null;
this.conn.onclose = null;
this.conn = null;
}
this._clearAllTimers();
this.channels.forEach((channel) => channel.teardown());
}
/** @internal */
_onConnOpen() {
this._setConnectionState('connected');
this.log('transport', `connected to ${this.endpointURL()}`);
this.flushSendBuffer();
this._clearTimer('reconnect');
if (!this.worker) {
this._startHeartbeat();
}
else {
if (!this.workerRef) {
this._startWorkerHeartbeat();
}
}
this._triggerStateCallbacks('open');
}
/** @internal */
_startHeartbeat() {
this.heartbeatTimer && clearInterval(this.heartbeatTimer);
this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), this.heartbeatIntervalMs);
}
/** @internal */
_startWorkerHeartbeat() {
if (this.workerUrl) {
this.log('worker', `starting worker for from ${this.workerUrl}`);
}
else {
this.log('worker', `starting default worker`);
}
const objectUrl = this._workerObjectUrl(this.workerUrl);
this.workerRef = new Worker(objectUrl);
this.workerRef.onerror = (error) => {
this.log('worker', 'worker error', error.message);
this.workerRef.terminate();
};
this.workerRef.onmessage = (event) => {
if (event.data.event === 'keepAlive') {
this.sendHeartbeat();
}
};
this.workerRef.postMessage({
event: 'start',
interval: this.heartbeatIntervalMs,
});
}
/** @internal */
_onConnClose(event) {
var _a;
this._setConnectionState('disconnected');
this.log('transport', 'close', event);
this._triggerChanError();
this._clearTimer('heartbeat');
// Only schedule reconnection if it wasn't a manual disconnect
if (!this._wasManualDisconnect) {
(_a = this.reconnectTimer) === null || _a === void 0 ? void 0 : _a.scheduleTimeout();
}
this._triggerStateCallbacks('close', event);
}
/** @internal */
_onConnError(error) {
this._setConnectionState('disconnected');
this.log('transport', `${error}`);
this._triggerChanError();
this._triggerStateCallbacks('error', error);
}
/** @internal */
_triggerChanError() {
this.channels.forEach((channel) => channel._trigger(constants_1.CHANNEL_EVENTS.error));
}
/** @internal */
_appendParams(url, params) {
if (Object.keys(params).length === 0) {
return url;
}
const prefix = url.match(/\?/) ? '&' : '?';
const query = new URLSearchParams(params);
return `${url}${prefix}${query}`;
}
_workerObjectUrl(url) {
let result_url;
if (url) {
result_url = url;
}
else {
const blob = new Blob([WORKER_SCRIPT], { type: 'application/javascript' });
result_url = URL.createObjectURL(blob);
}
return result_url;
}
/**
* Set connection state with proper state management
* @internal
*/
_setConnectionState(state, manual = false) {
this._connectionState = state;
if (state === 'connecting') {
this._wasManualDisconnect = false;
}
else if (state === 'disconnecting') {
this._wasManualDisconnect = manual;
}
}
/**
* Perform the actual auth operation
* @internal
*/
async _performAuth(token = null) {
let tokenToSend;
if (token) {
tokenToSend = token;
}
else if (this.accessToken) {
// Always call the accessToken callback to get fresh token
tokenToSend = await this.accessToken();
}
else {
tokenToSend = this.accessTokenValue;
}
if (this.accessTokenValue != tokenToSend) {
this.accessTokenValue = tokenToSend;
this.channels.forEach((channel) => {
const payload = {
access_token: tokenToSend,
version: constants_1.DEFAULT_VERSION,
};
tokenToSend && channel.updateJoinPayload(payload);
if (channel.joinedOnce && channel._isJoined()) {
channel._push(constants_1.CHANNEL_EVENTS.access_token, {
access_token: tokenToSend,
});
}
});
}
}
/**
* Wait for any in-flight auth operations to complete
* @internal
*/
async _waitForAuthIfNeeded() {
if (this._authPromise) {
await this._authPromise;
}
}
/**
* Safely call setAuth with standardized error handling
* @internal
*/
_setAuthSafely(context = 'general') {
this.setAuth().catch((e) => {
this.log('error', `error setting auth in ${context}`, e);
});
}
/**
* Trigger state change callbacks with proper error handling
* @internal
*/
_triggerStateCallbacks(event, data) {
try {
this.stateChangeCallbacks[event].forEach((callback) => {
try {
callback(data);
}
catch (e) {
this.log('error', `error in ${event} callback`, e);
}
});
}
catch (e) {
this.log('error', `error triggering ${event} callbacks`, e);
}
}
/**
* Setup reconnection timer with proper configuration
* @internal
*/
_setupReconnectionTimer() {
this.reconnectTimer = new timer_1.default(async () => {
setTimeout(async () => {
await this._waitForAuthIfNeeded();
if (!this.isConnected()) {
this.connect();
}
}, CONNECTION_TIMEOUTS.RECONNECT_DELAY);
}, this.reconnectAfterMs);
}
/**
* Initialize client options with defaults
* @internal
*/
_initializeOptions(options) {
var _a, _b, _c, _d, _e, _f, _g, _h;
// Set defaults
this.transport = (_a = options === null || options === void 0 ? void 0 : options.transport) !== null && _a !== void 0 ? _a : null;
this.timeout = (_b = options === null || options === void 0 ? void 0 : options.timeout) !== null && _b !== void 0 ? _b : constants_1.DEFAULT_TIMEOUT;
this.heartbeatIntervalMs =
(_c = options === null || options === void 0 ? void 0 : options.heartbeatIntervalMs) !== null && _c !== void 0 ? _c : CONNECTION_TIMEOUTS.HEARTBEAT_INTERVAL;
this.worker = (_d = options === null || options === void 0 ? void 0 : options.worker) !== null && _d !== void 0 ? _d : false;
this.accessToken = (_e = options === null || options === void 0 ? void 0 : options.accessToken) !== null && _e !== void 0 ? _e : null;
// Handle special cases
if (options === null || options === void 0 ? void 0 : options.params)
this.params = options.params;
if (options === null || options === void 0 ? void 0 : options.logger)
this.logger = options.logger;
if ((options === null || options === void 0 ? void 0 : options.logLevel) || (options === null || options === void 0 ? void 0 : options.log_level)) {
this.logLevel = options.logLevel || options.log_level;
this.params = Object.assign(Object.assign({}, this.params), { log_level: this.logLevel });
}
// Set up functions with defaults
this.reconnectAfterMs =
(_f = options === null || options === void 0 ? void 0 : options.reconnectAfterMs) !== null && _f !== void 0 ? _f : ((tries) => {
return RECONNECT_INTERVALS[tries - 1] || DEFAULT_RECONNECT_FALLBACK;
});
this.encode =
(_g = options === null || options === void 0 ? void 0 : options.encode) !== null && _g !== void 0 ? _g : ((payload, callback) => {
return callback(JSON.stringify(payload));
});
this.decode =
(_h = options === null || options === void 0 ? void 0 : options.decode) !== null && _h !== void 0 ? _h : this.serializer.decode.bind(this.serializer);
// Handle worker setup
if (this.worker) {
if (typeof window !== 'undefined' && !window.Worker) {
throw new Error('Web Worker is not supported');
}
this.workerUrl = options === null || options === void 0 ? void 0 : options.workerUrl;
}
}
}
exports.default = RealtimeClient;
//# sourceMappingURL=RealtimeClient.js.map
@@ -1,229 +0,0 @@
"use strict";
/*
This file draws heavily from https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/assets/js/phoenix/presence.js
License: https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/LICENSE.md
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.REALTIME_PRESENCE_LISTEN_EVENTS = void 0;
var REALTIME_PRESENCE_LISTEN_EVENTS;
(function (REALTIME_PRESENCE_LISTEN_EVENTS) {
REALTIME_PRESENCE_LISTEN_EVENTS["SYNC"] = "sync";
REALTIME_PRESENCE_LISTEN_EVENTS["JOIN"] = "join";
REALTIME_PRESENCE_LISTEN_EVENTS["LEAVE"] = "leave";
})(REALTIME_PRESENCE_LISTEN_EVENTS || (exports.REALTIME_PRESENCE_LISTEN_EVENTS = REALTIME_PRESENCE_LISTEN_EVENTS = {}));
class RealtimePresence {
/**
* Initializes the Presence.
*
* @param channel - The RealtimeChannel
* @param opts - The options,
* for example `{events: {state: 'state', diff: 'diff'}}`
*/
constructor(channel, opts) {
this.channel = channel;
this.state = {};
this.pendingDiffs = [];
this.joinRef = null;
this.enabled = false;
this.caller = {
onJoin: () => { },
onLeave: () => { },
onSync: () => { },
};
const events = (opts === null || opts === void 0 ? void 0 : opts.events) || {
state: 'presence_state',
diff: 'presence_diff',
};
this.channel._on(events.state, {}, (newState) => {
const { onJoin, onLeave, onSync } = this.caller;
this.joinRef = this.channel._joinRef();
this.state = RealtimePresence.syncState(this.state, newState, onJoin, onLeave);
this.pendingDiffs.forEach((diff) => {
this.state = RealtimePresence.syncDiff(this.state, diff, onJoin, onLeave);
});
this.pendingDiffs = [];
onSync();
});
this.channel._on(events.diff, {}, (diff) => {
const { onJoin, onLeave, onSync } = this.caller;
if (this.inPendingSyncState()) {
this.pendingDiffs.push(diff);
}
else {
this.state = RealtimePresence.syncDiff(this.state, diff, onJoin, onLeave);
onSync();
}
});
this.onJoin((key, currentPresences, newPresences) => {
this.channel._trigger('presence', {
event: 'join',
key,
currentPresences,
newPresences,
});
});
this.onLeave((key, currentPresences, leftPresences) => {
this.channel._trigger('presence', {
event: 'leave',
key,
currentPresences,
leftPresences,
});
});
this.onSync(() => {
this.channel._trigger('presence', { event: 'sync' });
});
}
/**
* Used to sync the list of presences on the server with the
* client's state.
*
* An optional `onJoin` and `onLeave` callback can be provided to
* react to changes in the client's local presences across
* disconnects and reconnects with the server.
*
* @internal
*/
static syncState(currentState, newState, onJoin, onLeave) {
const state = this.cloneDeep(currentState);
const transformedState = this.transformState(newState);
const joins = {};
const leaves = {};
this.map(state, (key, presences) => {
if (!transformedState[key]) {
leaves[key] = presences;
}
});
this.map(transformedState, (key, newPresences) => {
const currentPresences = state[key];
if (currentPresences) {
const newPresenceRefs = newPresences.map((m) => m.presence_ref);
const curPresenceRefs = currentPresences.map((m) => m.presence_ref);
const joinedPresences = newPresences.filter((m) => curPresenceRefs.indexOf(m.presence_ref) < 0);
const leftPresences = currentPresences.filter((m) => newPresenceRefs.indexOf(m.presence_ref) < 0);
if (joinedPresences.length > 0) {
joins[key] = joinedPresences;
}
if (leftPresences.length > 0) {
leaves[key] = leftPresences;
}
}
else {
joins[key] = newPresences;
}
});
return this.syncDiff(state, { joins, leaves }, onJoin, onLeave);
}
/**
* Used to sync a diff of presence join and leave events from the
* server, as they happen.
*
* Like `syncState`, `syncDiff` accepts optional `onJoin` and
* `onLeave` callbacks to react to a user joining or leaving from a
* device.
*
* @internal
*/
static syncDiff(state, diff, onJoin, onLeave) {
const { joins, leaves } = {
joins: this.transformState(diff.joins),
leaves: this.transformState(diff.leaves),
};
if (!onJoin) {
onJoin = () => { };
}
if (!onLeave) {
onLeave = () => { };
}
this.map(joins, (key, newPresences) => {
var _a;
const currentPresences = (_a = state[key]) !== null && _a !== void 0 ? _a : [];
state[key] = this.cloneDeep(newPresences);
if (currentPresences.length > 0) {
const joinedPresenceRefs = state[key].map((m) => m.presence_ref);
const curPresences = currentPresences.filter((m) => joinedPresenceRefs.indexOf(m.presence_ref) < 0);
state[key].unshift(...curPresences);
}
onJoin(key, currentPresences, newPresences);
});
this.map(leaves, (key, leftPresences) => {
let currentPresences = state[key];
if (!currentPresences)
return;
const presenceRefsToRemove = leftPresences.map((m) => m.presence_ref);
currentPresences = currentPresences.filter((m) => presenceRefsToRemove.indexOf(m.presence_ref) < 0);
state[key] = currentPresences;
onLeave(key, currentPresences, leftPresences);
if (currentPresences.length === 0)
delete state[key];
});
return state;
}
/** @internal */
static map(obj, func) {
return Object.getOwnPropertyNames(obj).map((key) => func(key, obj[key]));
}
/**
* Remove 'metas' key
* Change 'phx_ref' to 'presence_ref'
* Remove 'phx_ref' and 'phx_ref_prev'
*
* @example
* // returns {
* abc123: [
* { presence_ref: '2', user_id: 1 },
* { presence_ref: '3', user_id: 2 }
* ]
* }
* RealtimePresence.transformState({
* abc123: {
* metas: [
* { phx_ref: '2', phx_ref_prev: '1' user_id: 1 },
* { phx_ref: '3', user_id: 2 }
* ]
* }
* })
*
* @internal
*/
static transformState(state) {
state = this.cloneDeep(state);
return Object.getOwnPropertyNames(state).reduce((newState, key) => {
const presences = state[key];
if ('metas' in presences) {
newState[key] = presences.metas.map((presence) => {
presence['presence_ref'] = presence['phx_ref'];
delete presence['phx_ref'];
delete presence['phx_ref_prev'];
return presence;
});
}
else {
newState[key] = presences;
}
return newState;
}, {});
}
/** @internal */
static cloneDeep(obj) {
return JSON.parse(JSON.stringify(obj));
}
/** @internal */
onJoin(callback) {
this.caller.onJoin = callback;
}
/** @internal */
onLeave(callback) {
this.caller.onLeave = callback;
}
/** @internal */
onSync(callback) {
this.caller.onSync = callback;
}
/** @internal */
inPendingSyncState() {
return !this.joinRef || this.joinRef !== this.channel._joinRef();
}
}
exports.default = RealtimePresence;
//# sourceMappingURL=RealtimePresence.js.map
-53
View File
@@ -1,53 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketFactory = exports.REALTIME_CHANNEL_STATES = exports.REALTIME_SUBSCRIBE_STATES = exports.REALTIME_PRESENCE_LISTEN_EVENTS = exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = exports.REALTIME_LISTEN_TYPES = exports.RealtimeClient = exports.RealtimeChannel = exports.RealtimePresence = void 0;
const RealtimeClient_1 = __importDefault(require("./RealtimeClient"));
exports.RealtimeClient = RealtimeClient_1.default;
const RealtimeChannel_1 = __importStar(require("./RealtimeChannel"));
exports.RealtimeChannel = RealtimeChannel_1.default;
Object.defineProperty(exports, "REALTIME_LISTEN_TYPES", { enumerable: true, get: function () { return RealtimeChannel_1.REALTIME_LISTEN_TYPES; } });
Object.defineProperty(exports, "REALTIME_POSTGRES_CHANGES_LISTEN_EVENT", { enumerable: true, get: function () { return RealtimeChannel_1.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT; } });
Object.defineProperty(exports, "REALTIME_SUBSCRIBE_STATES", { enumerable: true, get: function () { return RealtimeChannel_1.REALTIME_SUBSCRIBE_STATES; } });
Object.defineProperty(exports, "REALTIME_CHANNEL_STATES", { enumerable: true, get: function () { return RealtimeChannel_1.REALTIME_CHANNEL_STATES; } });
const RealtimePresence_1 = __importStar(require("./RealtimePresence"));
exports.RealtimePresence = RealtimePresence_1.default;
Object.defineProperty(exports, "REALTIME_PRESENCE_LISTEN_EVENTS", { enumerable: true, get: function () { return RealtimePresence_1.REALTIME_PRESENCE_LISTEN_EVENTS; } });
const websocket_factory_1 = __importDefault(require("./lib/websocket-factory"));
exports.WebSocketFactory = websocket_factory_1.default;
//# sourceMappingURL=index.js.map
@@ -1,46 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CONNECTION_STATE = exports.TRANSPORTS = exports.CHANNEL_EVENTS = exports.CHANNEL_STATES = exports.SOCKET_STATES = exports.MAX_PUSH_BUFFER_SIZE = exports.WS_CLOSE_NORMAL = exports.DEFAULT_TIMEOUT = exports.VERSION = exports.VSN = exports.DEFAULT_VERSION = void 0;
const version_1 = require("./version");
exports.DEFAULT_VERSION = `realtime-js/${version_1.version}`;
exports.VSN = '1.0.0';
exports.VERSION = version_1.version;
exports.DEFAULT_TIMEOUT = 10000;
exports.WS_CLOSE_NORMAL = 1000;
exports.MAX_PUSH_BUFFER_SIZE = 100;
var SOCKET_STATES;
(function (SOCKET_STATES) {
SOCKET_STATES[SOCKET_STATES["connecting"] = 0] = "connecting";
SOCKET_STATES[SOCKET_STATES["open"] = 1] = "open";
SOCKET_STATES[SOCKET_STATES["closing"] = 2] = "closing";
SOCKET_STATES[SOCKET_STATES["closed"] = 3] = "closed";
})(SOCKET_STATES || (exports.SOCKET_STATES = SOCKET_STATES = {}));
var CHANNEL_STATES;
(function (CHANNEL_STATES) {
CHANNEL_STATES["closed"] = "closed";
CHANNEL_STATES["errored"] = "errored";
CHANNEL_STATES["joined"] = "joined";
CHANNEL_STATES["joining"] = "joining";
CHANNEL_STATES["leaving"] = "leaving";
})(CHANNEL_STATES || (exports.CHANNEL_STATES = CHANNEL_STATES = {}));
var CHANNEL_EVENTS;
(function (CHANNEL_EVENTS) {
CHANNEL_EVENTS["close"] = "phx_close";
CHANNEL_EVENTS["error"] = "phx_error";
CHANNEL_EVENTS["join"] = "phx_join";
CHANNEL_EVENTS["reply"] = "phx_reply";
CHANNEL_EVENTS["leave"] = "phx_leave";
CHANNEL_EVENTS["access_token"] = "access_token";
})(CHANNEL_EVENTS || (exports.CHANNEL_EVENTS = CHANNEL_EVENTS = {}));
var TRANSPORTS;
(function (TRANSPORTS) {
TRANSPORTS["websocket"] = "websocket";
})(TRANSPORTS || (exports.TRANSPORTS = TRANSPORTS = {}));
var CONNECTION_STATE;
(function (CONNECTION_STATE) {
CONNECTION_STATE["Connecting"] = "connecting";
CONNECTION_STATE["Open"] = "open";
CONNECTION_STATE["Closing"] = "closing";
CONNECTION_STATE["Closed"] = "closed";
})(CONNECTION_STATE || (exports.CONNECTION_STATE = CONNECTION_STATE = {}));
//# sourceMappingURL=constants.js.map
-104
View File
@@ -1,104 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("../lib/constants");
class Push {
/**
* Initializes the Push
*
* @param channel The Channel
* @param event The event, for example `"phx_join"`
* @param payload The payload, for example `{user_id: 123}`
* @param timeout The push timeout in milliseconds
*/
constructor(channel, event, payload = {}, timeout = constants_1.DEFAULT_TIMEOUT) {
this.channel = channel;
this.event = event;
this.payload = payload;
this.timeout = timeout;
this.sent = false;
this.timeoutTimer = undefined;
this.ref = '';
this.receivedResp = null;
this.recHooks = [];
this.refEvent = null;
}
resend(timeout) {
this.timeout = timeout;
this._cancelRefEvent();
this.ref = '';
this.refEvent = null;
this.receivedResp = null;
this.sent = false;
this.send();
}
send() {
if (this._hasReceived('timeout')) {
return;
}
this.startTimeout();
this.sent = true;
this.channel.socket.push({
topic: this.channel.topic,
event: this.event,
payload: this.payload,
ref: this.ref,
join_ref: this.channel._joinRef(),
});
}
updatePayload(payload) {
this.payload = Object.assign(Object.assign({}, this.payload), payload);
}
receive(status, callback) {
var _a;
if (this._hasReceived(status)) {
callback((_a = this.receivedResp) === null || _a === void 0 ? void 0 : _a.response);
}
this.recHooks.push({ status, callback });
return this;
}
startTimeout() {
if (this.timeoutTimer) {
return;
}
this.ref = this.channel.socket._makeRef();
this.refEvent = this.channel._replyEventName(this.ref);
const callback = (payload) => {
this._cancelRefEvent();
this._cancelTimeout();
this.receivedResp = payload;
this._matchReceive(payload);
};
this.channel._on(this.refEvent, {}, callback);
this.timeoutTimer = setTimeout(() => {
this.trigger('timeout', {});
}, this.timeout);
}
trigger(status, response) {
if (this.refEvent)
this.channel._trigger(this.refEvent, { status, response });
}
destroy() {
this._cancelRefEvent();
this._cancelTimeout();
}
_cancelRefEvent() {
if (!this.refEvent) {
return;
}
this.channel._off(this.refEvent, {});
}
_cancelTimeout() {
clearTimeout(this.timeoutTimer);
this.timeoutTimer = undefined;
}
_matchReceive({ status, response, }) {
this.recHooks
.filter((h) => h.status === status)
.forEach((h) => h.callback(response));
}
_hasReceived(status) {
return this.receivedResp && this.receivedResp.status === status;
}
}
exports.default = Push;
//# sourceMappingURL=push.js.map
@@ -1,36 +0,0 @@
"use strict";
// This file draws heavily from https://github.com/phoenixframework/phoenix/commit/cf098e9cf7a44ee6479d31d911a97d3c7430c6fe
// License: https://github.com/phoenixframework/phoenix/blob/master/LICENSE.md
Object.defineProperty(exports, "__esModule", { value: true });
class Serializer {
constructor() {
this.HEADER_LENGTH = 1;
}
decode(rawPayload, callback) {
if (rawPayload.constructor === ArrayBuffer) {
return callback(this._binaryDecode(rawPayload));
}
if (typeof rawPayload === 'string') {
return callback(JSON.parse(rawPayload));
}
return callback({});
}
_binaryDecode(buffer) {
const view = new DataView(buffer);
const decoder = new TextDecoder();
return this._decodeBroadcast(buffer, view, decoder);
}
_decodeBroadcast(buffer, view, decoder) {
const topicSize = view.getUint8(1);
const eventSize = view.getUint8(2);
let offset = this.HEADER_LENGTH + 2;
const topic = decoder.decode(buffer.slice(offset, offset + topicSize));
offset = offset + topicSize;
const event = decoder.decode(buffer.slice(offset, offset + eventSize));
offset = offset + eventSize;
const data = JSON.parse(decoder.decode(buffer.slice(offset, buffer.byteLength)));
return { ref: null, topic: topic, event: event, payload: data };
}
}
exports.default = Serializer;
//# sourceMappingURL=serializer.js.map
@@ -1,39 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Creates a timer that accepts a `timerCalc` function to perform calculated timeout retries, such as exponential backoff.
*
* @example
* let reconnectTimer = new Timer(() => this.connect(), function(tries){
* return [1000, 5000, 10000][tries - 1] || 10000
* })
* reconnectTimer.scheduleTimeout() // fires after 1000
* reconnectTimer.scheduleTimeout() // fires after 5000
* reconnectTimer.reset()
* reconnectTimer.scheduleTimeout() // fires after 1000
*/
class Timer {
constructor(callback, timerCalc) {
this.callback = callback;
this.timerCalc = timerCalc;
this.timer = undefined;
this.tries = 0;
this.callback = callback;
this.timerCalc = timerCalc;
}
reset() {
this.tries = 0;
clearTimeout(this.timer);
this.timer = undefined;
}
// Cancels any previous scheduleTimeout and schedules callback
scheduleTimeout() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.tries = this.tries + 1;
this.callback();
}, this.timerCalc(this.tries + 1));
}
}
exports.default = Timer;
//# sourceMappingURL=timer.js.map
@@ -1,229 +0,0 @@
"use strict";
/**
* Helpers to convert the change Payload into native JS types.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.httpEndpointURL = exports.toTimestampString = exports.toArray = exports.toJson = exports.toNumber = exports.toBoolean = exports.convertCell = exports.convertColumn = exports.convertChangeData = exports.PostgresTypes = void 0;
// Adapted from epgsql (src/epgsql_binary.erl), this module licensed under
// 3-clause BSD found here: https://raw.githubusercontent.com/epgsql/epgsql/devel/LICENSE
var PostgresTypes;
(function (PostgresTypes) {
PostgresTypes["abstime"] = "abstime";
PostgresTypes["bool"] = "bool";
PostgresTypes["date"] = "date";
PostgresTypes["daterange"] = "daterange";
PostgresTypes["float4"] = "float4";
PostgresTypes["float8"] = "float8";
PostgresTypes["int2"] = "int2";
PostgresTypes["int4"] = "int4";
PostgresTypes["int4range"] = "int4range";
PostgresTypes["int8"] = "int8";
PostgresTypes["int8range"] = "int8range";
PostgresTypes["json"] = "json";
PostgresTypes["jsonb"] = "jsonb";
PostgresTypes["money"] = "money";
PostgresTypes["numeric"] = "numeric";
PostgresTypes["oid"] = "oid";
PostgresTypes["reltime"] = "reltime";
PostgresTypes["text"] = "text";
PostgresTypes["time"] = "time";
PostgresTypes["timestamp"] = "timestamp";
PostgresTypes["timestamptz"] = "timestamptz";
PostgresTypes["timetz"] = "timetz";
PostgresTypes["tsrange"] = "tsrange";
PostgresTypes["tstzrange"] = "tstzrange";
})(PostgresTypes || (exports.PostgresTypes = PostgresTypes = {}));
/**
* Takes an array of columns and an object of string values then converts each string value
* to its mapped type.
*
* @param {{name: String, type: String}[]} columns
* @param {Object} record
* @param {Object} options The map of various options that can be applied to the mapper
* @param {Array} options.skipTypes The array of types that should not be converted
*
* @example convertChangeData([{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age:'33'}, {})
* //=>{ first_name: 'Paul', age: 33 }
*/
const convertChangeData = (columns, record, options = {}) => {
var _a;
const skipTypes = (_a = options.skipTypes) !== null && _a !== void 0 ? _a : [];
return Object.keys(record).reduce((acc, rec_key) => {
acc[rec_key] = (0, exports.convertColumn)(rec_key, columns, record, skipTypes);
return acc;
}, {});
};
exports.convertChangeData = convertChangeData;
/**
* Converts the value of an individual column.
*
* @param {String} columnName The column that you want to convert
* @param {{name: String, type: String}[]} columns All of the columns
* @param {Object} record The map of string values
* @param {Array} skipTypes An array of types that should not be converted
* @return {object} Useless information
*
* @example convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age: '33'}, [])
* //=> 33
* @example convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age: '33'}, ['int4'])
* //=> "33"
*/
const convertColumn = (columnName, columns, record, skipTypes) => {
const column = columns.find((x) => x.name === columnName);
const colType = column === null || column === void 0 ? void 0 : column.type;
const value = record[columnName];
if (colType && !skipTypes.includes(colType)) {
return (0, exports.convertCell)(colType, value);
}
return noop(value);
};
exports.convertColumn = convertColumn;
/**
* If the value of the cell is `null`, returns null.
* Otherwise converts the string value to the correct type.
* @param {String} type A postgres column type
* @param {String} value The cell value
*
* @example convertCell('bool', 't')
* //=> true
* @example convertCell('int8', '10')
* //=> 10
* @example convertCell('_int4', '{1,2,3,4}')
* //=> [1,2,3,4]
*/
const convertCell = (type, value) => {
// if data type is an array
if (type.charAt(0) === '_') {
const dataType = type.slice(1, type.length);
return (0, exports.toArray)(value, dataType);
}
// If not null, convert to correct type.
switch (type) {
case PostgresTypes.bool:
return (0, exports.toBoolean)(value);
case PostgresTypes.float4:
case PostgresTypes.float8:
case PostgresTypes.int2:
case PostgresTypes.int4:
case PostgresTypes.int8:
case PostgresTypes.numeric:
case PostgresTypes.oid:
return (0, exports.toNumber)(value);
case PostgresTypes.json:
case PostgresTypes.jsonb:
return (0, exports.toJson)(value);
case PostgresTypes.timestamp:
return (0, exports.toTimestampString)(value); // Format to be consistent with PostgREST
case PostgresTypes.abstime: // To allow users to cast it based on Timezone
case PostgresTypes.date: // To allow users to cast it based on Timezone
case PostgresTypes.daterange:
case PostgresTypes.int4range:
case PostgresTypes.int8range:
case PostgresTypes.money:
case PostgresTypes.reltime: // To allow users to cast it based on Timezone
case PostgresTypes.text:
case PostgresTypes.time: // To allow users to cast it based on Timezone
case PostgresTypes.timestamptz: // To allow users to cast it based on Timezone
case PostgresTypes.timetz: // To allow users to cast it based on Timezone
case PostgresTypes.tsrange:
case PostgresTypes.tstzrange:
return noop(value);
default:
// Return the value for remaining types
return noop(value);
}
};
exports.convertCell = convertCell;
const noop = (value) => {
return value;
};
const toBoolean = (value) => {
switch (value) {
case 't':
return true;
case 'f':
return false;
default:
return value;
}
};
exports.toBoolean = toBoolean;
const toNumber = (value) => {
if (typeof value === 'string') {
const parsedValue = parseFloat(value);
if (!Number.isNaN(parsedValue)) {
return parsedValue;
}
}
return value;
};
exports.toNumber = toNumber;
const toJson = (value) => {
if (typeof value === 'string') {
try {
return JSON.parse(value);
}
catch (error) {
console.log(`JSON parse error: ${error}`);
return value;
}
}
return value;
};
exports.toJson = toJson;
/**
* Converts a Postgres Array into a native JS array
*
* @example toArray('{}', 'int4')
* //=> []
* @example toArray('{"[2021-01-01,2021-12-31)","(2021-01-01,2021-12-32]"}', 'daterange')
* //=> ['[2021-01-01,2021-12-31)', '(2021-01-01,2021-12-32]']
* @example toArray([1,2,3,4], 'int4')
* //=> [1,2,3,4]
*/
const toArray = (value, type) => {
if (typeof value !== 'string') {
return value;
}
const lastIdx = value.length - 1;
const closeBrace = value[lastIdx];
const openBrace = value[0];
// Confirm value is a Postgres array by checking curly brackets
if (openBrace === '{' && closeBrace === '}') {
let arr;
const valTrim = value.slice(1, lastIdx);
// TODO: find a better solution to separate Postgres array data
try {
arr = JSON.parse('[' + valTrim + ']');
}
catch (_) {
// WARNING: splitting on comma does not cover all edge cases
arr = valTrim ? valTrim.split(',') : [];
}
return arr.map((val) => (0, exports.convertCell)(type, val));
}
return value;
};
exports.toArray = toArray;
/**
* Fixes timestamp to be ISO-8601. Swaps the space between the date and time for a 'T'
* See https://github.com/supabase/supabase/issues/18
*
* @example toTimestampString('2019-09-10 00:00:00')
* //=> '2019-09-10T00:00:00'
*/
const toTimestampString = (value) => {
if (typeof value === 'string') {
return value.replace(' ', 'T');
}
return value;
};
exports.toTimestampString = toTimestampString;
const httpEndpointURL = (socketUrl) => {
let url = socketUrl;
url = url.replace(/^ws/i, 'http');
url = url.replace(/(\/socket\/websocket|\/socket|\/websocket)\/?$/i, '');
return url.replace(/\/+$/, '') + '/api/broadcast';
};
exports.httpEndpointURL = httpEndpointURL;
//# sourceMappingURL=transformers.js.map
@@ -1,5 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = void 0;
exports.version = '2.15.1';
//# sourceMappingURL=version.js.map
@@ -1,95 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketFactory = void 0;
class WebSocketFactory {
static detectEnvironment() {
var _a;
if (typeof WebSocket !== 'undefined') {
return { type: 'native', constructor: WebSocket };
}
if (typeof globalThis !== 'undefined' &&
typeof globalThis.WebSocket !== 'undefined') {
return { type: 'native', constructor: globalThis.WebSocket };
}
if (typeof global !== 'undefined' &&
typeof global.WebSocket !== 'undefined') {
return { type: 'native', constructor: global.WebSocket };
}
if (typeof globalThis !== 'undefined' &&
typeof globalThis.WebSocketPair !== 'undefined' &&
typeof globalThis.WebSocket === 'undefined') {
return {
type: 'cloudflare',
error: 'Cloudflare Workers detected. WebSocket clients are not supported in Cloudflare Workers.',
workaround: 'Use Cloudflare Workers WebSocket API for server-side WebSocket handling, or deploy to a different runtime.',
};
}
if ((typeof globalThis !== 'undefined' && globalThis.EdgeRuntime) ||
(typeof navigator !== 'undefined' &&
((_a = navigator.userAgent) === null || _a === void 0 ? void 0 : _a.includes('Vercel-Edge')))) {
return {
type: 'unsupported',
error: 'Edge runtime detected (Vercel Edge/Netlify Edge). WebSockets are not supported in edge functions.',
workaround: 'Use serverless functions or a different deployment target for WebSocket functionality.',
};
}
if (typeof process !== 'undefined' &&
process.versions &&
process.versions.node) {
const nodeVersion = parseInt(process.versions.node.split('.')[0]);
// Node.js 22+ should have native WebSocket
if (nodeVersion >= 22) {
// Check if native WebSocket is available (should be in Node.js 22+)
if (typeof globalThis.WebSocket !== 'undefined') {
return { type: 'native', constructor: globalThis.WebSocket };
}
// If not available, user needs to provide it
return {
type: 'unsupported',
error: `Node.js ${nodeVersion} detected but native WebSocket not found.`,
workaround: 'Provide a WebSocket implementation via the transport option.',
};
}
// Node.js < 22 doesn't have native WebSocket
return {
type: 'unsupported',
error: `Node.js ${nodeVersion} detected without native WebSocket support.`,
workaround: 'For Node.js < 22, install "ws" package and provide it via the transport option:\n' +
'import ws from "ws"\n' +
'new RealtimeClient(url, { transport: ws })',
};
}
return {
type: 'unsupported',
error: 'Unknown JavaScript runtime without WebSocket support.',
workaround: "Ensure you're running in a supported environment (browser, Node.js, Deno) or provide a custom WebSocket implementation.",
};
}
static getWebSocketConstructor() {
const env = this.detectEnvironment();
if (env.constructor) {
return env.constructor;
}
let errorMessage = env.error || 'WebSocket not supported in this environment.';
if (env.workaround) {
errorMessage += `\n\nSuggested solution: ${env.workaround}`;
}
throw new Error(errorMessage);
}
static createWebSocket(url, protocols) {
const WS = this.getWebSocketConstructor();
return new WS(url, protocols);
}
static isWebSocketSupported() {
try {
const env = this.detectEnvironment();
return env.type === 'native' || env.type === 'ws';
}
catch (_a) {
return false;
}
}
}
exports.WebSocketFactory = WebSocketFactory;
exports.default = WebSocketFactory;
//# sourceMappingURL=websocket-factory.js.map
-65
View File
@@ -1,65 +0,0 @@
{
"name": "@supabase/realtime-js",
"version": "2.15.1",
"description": "Listen to realtime updates to your PostgreSQL database",
"keywords": [
"realtime",
"phoenix",
"elixir",
"javascript",
"typescript",
"firebase",
"supabase"
],
"homepage": "https://github.com/supabase/realtime-js",
"bugs": "https://github.com/supabase/realtime-js/issues",
"files": [
"dist",
"src"
],
"main": "dist/main/index.js",
"module": "dist/module/index.js",
"types": "dist/module/index.d.ts",
"repository": "https://github.com/supabase/realtime-js",
"author": "Supabase",
"license": "MIT",
"scripts": {
"clean": "rimraf dist docs/v2",
"format": "prettier --write \"{src,test}/**/*.ts\"",
"build": "run-s clean format build:*",
"build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json",
"test": "vitest run",
"test:watch": "vitest",
"coverage": "vitest run --coverage",
"coverage:text": "vitest run --coverage.enabled true --coverage.reporter=text",
"docs": "typedoc src/index.ts --out docs/v2",
"docs:json": "typedoc --json docs/v2/spec.json --excludeExternals src/index.ts",
"check-exports": "attw --pack .",
"ci": "run-s test coverage"
},
"dependencies": {
"@supabase/node-fetch": "^2.6.13",
"@types/phoenix": "^1.6.6",
"ws": "^8.18.2",
"@types/ws": "^8.18.1"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.16.4",
"@vitest/coverage-v8": "^3.1.4",
"eslint": "^9.27.0",
"esm": "^3.2.25",
"jsdom": "^16.7.0",
"jsdom-global": "3.0.0",
"jsonwebtoken": "^9.0.2",
"mock-socket": "^9.3.1",
"npm-run-all": "^4.1.5",
"nyc": "^15.1.0",
"prettier": "^2.8.8",
"semantic-release-plugin-update-version-in-files": "^1.1.0",
"typedoc": "^0.27.9",
"typescript": "^5.8.3",
"vitest": "^3.1.4",
"web-worker": "1.2.0"
}
}
@@ -1,23 +0,0 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StorageClient = void 0;
const StorageFileApi_1 = __importDefault(require("./packages/StorageFileApi"));
const StorageBucketApi_1 = __importDefault(require("./packages/StorageBucketApi"));
class StorageClient extends StorageBucketApi_1.default {
constructor(url, headers = {}, fetch, opts) {
super(url, headers, fetch, opts);
}
/**
* Perform file operation in a bucket.
*
* @param id The bucket id to operate on.
*/
from(id) {
return new StorageFileApi_1.default(this.url, this.headers, id, this.fetch);
}
}
exports.StorageClient = StorageClient;
//# sourceMappingURL=StorageClient.js.map
-22
View File
@@ -1,22 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StorageClient = void 0;
var StorageClient_1 = require("./StorageClient");
Object.defineProperty(exports, "StorageClient", { enumerable: true, get: function () { return StorageClient_1.StorageClient; } });
__exportStar(require("./lib/types"), exports);
__exportStar(require("./lib/errors"), exports);
//# sourceMappingURL=index.js.map
@@ -1,6 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_HEADERS = void 0;
const version_1 = require("./version");
exports.DEFAULT_HEADERS = { 'X-Client-Info': `storage-js/${version_1.version}` };
//# sourceMappingURL=constants.js.map
@@ -1,41 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StorageUnknownError = exports.StorageApiError = exports.isStorageError = exports.StorageError = void 0;
class StorageError extends Error {
constructor(message) {
super(message);
this.__isStorageError = true;
this.name = 'StorageError';
}
}
exports.StorageError = StorageError;
function isStorageError(error) {
return typeof error === 'object' && error !== null && '__isStorageError' in error;
}
exports.isStorageError = isStorageError;
class StorageApiError extends StorageError {
constructor(message, status, statusCode) {
super(message);
this.name = 'StorageApiError';
this.status = status;
this.statusCode = statusCode;
}
toJSON() {
return {
name: this.name,
message: this.message,
status: this.status,
statusCode: this.statusCode,
};
}
}
exports.StorageApiError = StorageApiError;
class StorageUnknownError extends StorageError {
constructor(message, originalError) {
super(message);
this.name = 'StorageUnknownError';
this.originalError = originalError;
}
}
exports.StorageUnknownError = StorageUnknownError;
//# sourceMappingURL=errors.js.map
@@ -1,97 +0,0 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.remove = exports.head = exports.put = exports.post = exports.get = void 0;
const errors_1 = require("./errors");
const helpers_1 = require("./helpers");
const _getErrorMessage = (err) => err.msg || err.message || err.error_description || err.error || JSON.stringify(err);
const handleError = (error, reject, options) => __awaiter(void 0, void 0, void 0, function* () {
const Res = yield (0, helpers_1.resolveResponse)();
if (error instanceof Res && !(options === null || options === void 0 ? void 0 : options.noResolveJson)) {
error
.json()
.then((err) => {
const status = error.status || 500;
const statusCode = (err === null || err === void 0 ? void 0 : err.statusCode) || status + '';
reject(new errors_1.StorageApiError(_getErrorMessage(err), status, statusCode));
})
.catch((err) => {
reject(new errors_1.StorageUnknownError(_getErrorMessage(err), err));
});
}
else {
reject(new errors_1.StorageUnknownError(_getErrorMessage(error), error));
}
});
const _getRequestParams = (method, options, parameters, body) => {
const params = { method, headers: (options === null || options === void 0 ? void 0 : options.headers) || {} };
if (method === 'GET' || !body) {
return params;
}
if ((0, helpers_1.isPlainObject)(body)) {
params.headers = Object.assign({ 'Content-Type': 'application/json' }, options === null || options === void 0 ? void 0 : options.headers);
params.body = JSON.stringify(body);
}
else {
params.body = body;
}
if (options === null || options === void 0 ? void 0 : options.duplex) {
params.duplex = options.duplex;
}
return Object.assign(Object.assign({}, params), parameters);
};
function _handleRequest(fetcher, method, url, options, parameters, body) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
fetcher(url, _getRequestParams(method, options, parameters, body))
.then((result) => {
if (!result.ok)
throw result;
if (options === null || options === void 0 ? void 0 : options.noResolveJson)
return result;
return result.json();
})
.then((data) => resolve(data))
.catch((error) => handleError(error, reject, options));
});
});
}
function get(fetcher, url, options, parameters) {
return __awaiter(this, void 0, void 0, function* () {
return _handleRequest(fetcher, 'GET', url, options, parameters);
});
}
exports.get = get;
function post(fetcher, url, body, options, parameters) {
return __awaiter(this, void 0, void 0, function* () {
return _handleRequest(fetcher, 'POST', url, options, parameters, body);
});
}
exports.post = post;
function put(fetcher, url, body, options, parameters) {
return __awaiter(this, void 0, void 0, function* () {
return _handleRequest(fetcher, 'PUT', url, options, parameters, body);
});
}
exports.put = put;
function head(fetcher, url, options, parameters) {
return __awaiter(this, void 0, void 0, function* () {
return _handleRequest(fetcher, 'HEAD', url, Object.assign(Object.assign({}, options), { noResolveJson: true }), parameters);
});
}
exports.head = head;
function remove(fetcher, url, body, options, parameters) {
return __awaiter(this, void 0, void 0, function* () {
return _handleRequest(fetcher, 'DELETE', url, options, parameters, body);
});
}
exports.remove = remove;
//# sourceMappingURL=fetch.js.map
@@ -1,90 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isPlainObject = exports.recursiveToCamel = exports.resolveResponse = exports.resolveFetch = void 0;
const resolveFetch = (customFetch) => {
let _fetch;
if (customFetch) {
_fetch = customFetch;
}
else if (typeof fetch === 'undefined') {
_fetch = (...args) => Promise.resolve().then(() => __importStar(require('@supabase/node-fetch'))).then(({ default: fetch }) => fetch(...args));
}
else {
_fetch = fetch;
}
return (...args) => _fetch(...args);
};
exports.resolveFetch = resolveFetch;
const resolveResponse = () => __awaiter(void 0, void 0, void 0, function* () {
if (typeof Response === 'undefined') {
// @ts-ignore
return (yield Promise.resolve().then(() => __importStar(require('@supabase/node-fetch')))).Response;
}
return Response;
});
exports.resolveResponse = resolveResponse;
const recursiveToCamel = (item) => {
if (Array.isArray(item)) {
return item.map((el) => (0, exports.recursiveToCamel)(el));
}
else if (typeof item === 'function' || item !== Object(item)) {
return item;
}
const result = {};
Object.entries(item).forEach(([key, value]) => {
const newKey = key.replace(/([-_][a-z])/gi, (c) => c.toUpperCase().replace(/[-_]/g, ''));
result[newKey] = (0, exports.recursiveToCamel)(value);
});
return result;
};
exports.recursiveToCamel = recursiveToCamel;
/**
* Determine if input is a plain object
* An object is plain if it's created by either {}, new Object(), or Object.create(null)
* source: https://github.com/sindresorhus/is-plain-obj
*/
const isPlainObject = (value) => {
if (typeof value !== 'object' || value === null) {
return false;
}
const prototype = Object.getPrototypeOf(value);
return ((prototype === null ||
prototype === Object.prototype ||
Object.getPrototypeOf(prototype) === null) &&
!(Symbol.toStringTag in value) &&
!(Symbol.iterator in value));
};
exports.isPlainObject = isPlainObject;
//# sourceMappingURL=helpers.js.map
@@ -1,3 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map
@@ -1,6 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = void 0;
// generated by genversion
exports.version = '2.11.0';
//# sourceMappingURL=version.js.map
@@ -1,178 +0,0 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const constants_1 = require("../lib/constants");
const errors_1 = require("../lib/errors");
const fetch_1 = require("../lib/fetch");
const helpers_1 = require("../lib/helpers");
class StorageBucketApi {
constructor(url, headers = {}, fetch, opts) {
const baseUrl = new URL(url);
// if legacy uri is used, replace with new storage host (disables request buffering to allow > 50GB uploads)
// "project-ref.supabase.co" becomes "project-ref.storage.supabase.co"
if (opts === null || opts === void 0 ? void 0 : opts.useNewHostname) {
const isSupabaseHost = /supabase\.(co|in|red)$/.test(baseUrl.hostname);
if (isSupabaseHost && !baseUrl.hostname.includes('storage.supabase.')) {
baseUrl.hostname = baseUrl.hostname.replace('supabase.', 'storage.supabase.');
}
}
this.url = baseUrl.href;
this.headers = Object.assign(Object.assign({}, constants_1.DEFAULT_HEADERS), headers);
this.fetch = (0, helpers_1.resolveFetch)(fetch);
}
/**
* Retrieves the details of all Storage buckets within an existing project.
*/
listBuckets() {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.get)(this.fetch, `${this.url}/bucket`, { headers: this.headers });
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Retrieves the details of an existing Storage bucket.
*
* @param id The unique identifier of the bucket you would like to retrieve.
*/
getBucket(id) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.get)(this.fetch, `${this.url}/bucket/${id}`, { headers: this.headers });
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Creates a new Storage bucket
*
* @param id A unique identifier for the bucket you are creating.
* @param options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations. By default, buckets are private.
* @param options.fileSizeLimit specifies the max file size in bytes that can be uploaded to this bucket.
* The global file size limit takes precedence over this value.
* The default value is null, which doesn't set a per bucket file size limit.
* @param options.allowedMimeTypes specifies the allowed mime types that this bucket can accept during upload.
* The default value is null, which allows files with all mime types to be uploaded.
* Each mime type specified can be a wildcard, e.g. image/*, or a specific mime type, e.g. image/png.
* @returns newly created bucket id
* @param options.type (private-beta) specifies the bucket type. see `BucketType` for more details.
* - default bucket type is `STANDARD`
*/
createBucket(id, options = {
public: false,
}) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.post)(this.fetch, `${this.url}/bucket`, {
id,
name: id,
type: options.type,
public: options.public,
file_size_limit: options.fileSizeLimit,
allowed_mime_types: options.allowedMimeTypes,
}, { headers: this.headers });
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Updates a Storage bucket
*
* @param id A unique identifier for the bucket you are updating.
* @param options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations.
* @param options.fileSizeLimit specifies the max file size in bytes that can be uploaded to this bucket.
* The global file size limit takes precedence over this value.
* The default value is null, which doesn't set a per bucket file size limit.
* @param options.allowedMimeTypes specifies the allowed mime types that this bucket can accept during upload.
* The default value is null, which allows files with all mime types to be uploaded.
* Each mime type specified can be a wildcard, e.g. image/*, or a specific mime type, e.g. image/png.
*/
updateBucket(id, options) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.put)(this.fetch, `${this.url}/bucket/${id}`, {
id,
name: id,
public: options.public,
file_size_limit: options.fileSizeLimit,
allowed_mime_types: options.allowedMimeTypes,
}, { headers: this.headers });
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Removes all objects inside a single bucket.
*
* @param id The unique identifier of the bucket you would like to empty.
*/
emptyBucket(id) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.post)(this.fetch, `${this.url}/bucket/${id}/empty`, {}, { headers: this.headers });
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Deletes an existing bucket. A bucket can't be deleted with existing objects inside it.
* You must first `empty()` the bucket.
*
* @param id The unique identifier of the bucket you would like to delete.
*/
deleteBucket(id) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.remove)(this.fetch, `${this.url}/bucket/${id}`, {}, { headers: this.headers });
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
}
exports.default = StorageBucketApi;
//# sourceMappingURL=StorageBucketApi.js.map
@@ -1,556 +0,0 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const errors_1 = require("../lib/errors");
const fetch_1 = require("../lib/fetch");
const helpers_1 = require("../lib/helpers");
const DEFAULT_SEARCH_OPTIONS = {
limit: 100,
offset: 0,
sortBy: {
column: 'name',
order: 'asc',
},
};
const DEFAULT_FILE_OPTIONS = {
cacheControl: '3600',
contentType: 'text/plain;charset=UTF-8',
upsert: false,
};
class StorageFileApi {
constructor(url, headers = {}, bucketId, fetch) {
this.url = url;
this.headers = headers;
this.bucketId = bucketId;
this.fetch = (0, helpers_1.resolveFetch)(fetch);
}
/**
* Uploads a file to an existing bucket or replaces an existing file at the specified path with a new one.
*
* @param method HTTP method.
* @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
* @param fileBody The body of the file to be stored in the bucket.
*/
uploadOrUpdate(method, path, fileBody, fileOptions) {
return __awaiter(this, void 0, void 0, function* () {
try {
let body;
const options = Object.assign(Object.assign({}, DEFAULT_FILE_OPTIONS), fileOptions);
let headers = Object.assign(Object.assign({}, this.headers), (method === 'POST' && { 'x-upsert': String(options.upsert) }));
const metadata = options.metadata;
if (typeof Blob !== 'undefined' && fileBody instanceof Blob) {
body = new FormData();
body.append('cacheControl', options.cacheControl);
if (metadata) {
body.append('metadata', this.encodeMetadata(metadata));
}
body.append('', fileBody);
}
else if (typeof FormData !== 'undefined' && fileBody instanceof FormData) {
body = fileBody;
body.append('cacheControl', options.cacheControl);
if (metadata) {
body.append('metadata', this.encodeMetadata(metadata));
}
}
else {
body = fileBody;
headers['cache-control'] = `max-age=${options.cacheControl}`;
headers['content-type'] = options.contentType;
if (metadata) {
headers['x-metadata'] = this.toBase64(this.encodeMetadata(metadata));
}
}
if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) {
headers = Object.assign(Object.assign({}, headers), fileOptions.headers);
}
const cleanPath = this._removeEmptyFolders(path);
const _path = this._getFinalPath(cleanPath);
const data = yield (method == 'PUT' ? fetch_1.put : fetch_1.post)(this.fetch, `${this.url}/object/${_path}`, body, Object.assign({ headers }, ((options === null || options === void 0 ? void 0 : options.duplex) ? { duplex: options.duplex } : {})));
return {
data: { path: cleanPath, id: data.Id, fullPath: data.Key },
error: null,
};
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Uploads a file to an existing bucket.
*
* @param path The file path, including the file name. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
* @param fileBody The body of the file to be stored in the bucket.
*/
upload(path, fileBody, fileOptions) {
return __awaiter(this, void 0, void 0, function* () {
return this.uploadOrUpdate('POST', path, fileBody, fileOptions);
});
}
/**
* Upload a file with a token generated from `createSignedUploadUrl`.
* @param path The file path, including the file name. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
* @param token The token generated from `createSignedUploadUrl`
* @param fileBody The body of the file to be stored in the bucket.
*/
uploadToSignedUrl(path, token, fileBody, fileOptions) {
return __awaiter(this, void 0, void 0, function* () {
const cleanPath = this._removeEmptyFolders(path);
const _path = this._getFinalPath(cleanPath);
const url = new URL(this.url + `/object/upload/sign/${_path}`);
url.searchParams.set('token', token);
try {
let body;
const options = Object.assign({ upsert: DEFAULT_FILE_OPTIONS.upsert }, fileOptions);
const headers = Object.assign(Object.assign({}, this.headers), { 'x-upsert': String(options.upsert) });
if (typeof Blob !== 'undefined' && fileBody instanceof Blob) {
body = new FormData();
body.append('cacheControl', options.cacheControl);
body.append('', fileBody);
}
else if (typeof FormData !== 'undefined' && fileBody instanceof FormData) {
body = fileBody;
body.append('cacheControl', options.cacheControl);
}
else {
body = fileBody;
headers['cache-control'] = `max-age=${options.cacheControl}`;
headers['content-type'] = options.contentType;
}
const data = yield (0, fetch_1.put)(this.fetch, url.toString(), body, { headers });
return {
data: { path: cleanPath, fullPath: data.Key },
error: null,
};
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Creates a signed upload URL.
* Signed upload URLs can be used to upload files to the bucket without further authentication.
* They are valid for 2 hours.
* @param path The file path, including the current file name. For example `folder/image.png`.
* @param options.upsert If set to true, allows the file to be overwritten if it already exists.
*/
createSignedUploadUrl(path, options) {
return __awaiter(this, void 0, void 0, function* () {
try {
let _path = this._getFinalPath(path);
const headers = Object.assign({}, this.headers);
if (options === null || options === void 0 ? void 0 : options.upsert) {
headers['x-upsert'] = 'true';
}
const data = yield (0, fetch_1.post)(this.fetch, `${this.url}/object/upload/sign/${_path}`, {}, { headers });
const url = new URL(this.url + data.url);
const token = url.searchParams.get('token');
if (!token) {
throw new errors_1.StorageError('No token returned by API');
}
return { data: { signedUrl: url.toString(), path, token }, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Replaces an existing file at the specified path with a new one.
*
* @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to update.
* @param fileBody The body of the file to be stored in the bucket.
*/
update(path, fileBody, fileOptions) {
return __awaiter(this, void 0, void 0, function* () {
return this.uploadOrUpdate('PUT', path, fileBody, fileOptions);
});
}
/**
* Moves an existing file to a new path in the same bucket.
*
* @param fromPath The original file path, including the current file name. For example `folder/image.png`.
* @param toPath The new file path, including the new file name. For example `folder/image-new.png`.
* @param options The destination options.
*/
move(fromPath, toPath, options) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.post)(this.fetch, `${this.url}/object/move`, {
bucketId: this.bucketId,
sourceKey: fromPath,
destinationKey: toPath,
destinationBucket: options === null || options === void 0 ? void 0 : options.destinationBucket,
}, { headers: this.headers });
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Copies an existing file to a new path in the same bucket.
*
* @param fromPath The original file path, including the current file name. For example `folder/image.png`.
* @param toPath The new file path, including the new file name. For example `folder/image-copy.png`.
* @param options The destination options.
*/
copy(fromPath, toPath, options) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.post)(this.fetch, `${this.url}/object/copy`, {
bucketId: this.bucketId,
sourceKey: fromPath,
destinationKey: toPath,
destinationBucket: options === null || options === void 0 ? void 0 : options.destinationBucket,
}, { headers: this.headers });
return { data: { path: data.Key }, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Creates a signed URL. Use a signed URL to share a file for a fixed amount of time.
*
* @param path The file path, including the current file name. For example `folder/image.png`.
* @param expiresIn The number of seconds until the signed URL expires. For example, `60` for a URL which is valid for one minute.
* @param options.download triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.
* @param options.transform Transform the asset before serving it to the client.
*/
createSignedUrl(path, expiresIn, options) {
return __awaiter(this, void 0, void 0, function* () {
try {
let _path = this._getFinalPath(path);
let data = yield (0, fetch_1.post)(this.fetch, `${this.url}/object/sign/${_path}`, Object.assign({ expiresIn }, ((options === null || options === void 0 ? void 0 : options.transform) ? { transform: options.transform } : {})), { headers: this.headers });
const downloadQueryParam = (options === null || options === void 0 ? void 0 : options.download)
? `&download=${options.download === true ? '' : options.download}`
: '';
const signedUrl = encodeURI(`${this.url}${data.signedURL}${downloadQueryParam}`);
data = { signedUrl };
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Creates multiple signed URLs. Use a signed URL to share a file for a fixed amount of time.
*
* @param paths The file paths to be downloaded, including the current file names. For example `['folder/image.png', 'folder2/image2.png']`.
* @param expiresIn The number of seconds until the signed URLs expire. For example, `60` for URLs which are valid for one minute.
* @param options.download triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.
*/
createSignedUrls(paths, expiresIn, options) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.post)(this.fetch, `${this.url}/object/sign/${this.bucketId}`, { expiresIn, paths }, { headers: this.headers });
const downloadQueryParam = (options === null || options === void 0 ? void 0 : options.download)
? `&download=${options.download === true ? '' : options.download}`
: '';
return {
data: data.map((datum) => (Object.assign(Object.assign({}, datum), { signedUrl: datum.signedURL
? encodeURI(`${this.url}${datum.signedURL}${downloadQueryParam}`)
: null }))),
error: null,
};
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Downloads a file from a private bucket. For public buckets, make a request to the URL returned from `getPublicUrl` instead.
*
* @param path The full path and file name of the file to be downloaded. For example `folder/image.png`.
* @param options.transform Transform the asset before serving it to the client.
*/
download(path, options) {
return __awaiter(this, void 0, void 0, function* () {
const wantsTransformation = typeof (options === null || options === void 0 ? void 0 : options.transform) !== 'undefined';
const renderPath = wantsTransformation ? 'render/image/authenticated' : 'object';
const transformationQuery = this.transformOptsToQueryString((options === null || options === void 0 ? void 0 : options.transform) || {});
const queryString = transformationQuery ? `?${transformationQuery}` : '';
try {
const _path = this._getFinalPath(path);
const res = yield (0, fetch_1.get)(this.fetch, `${this.url}/${renderPath}/${_path}${queryString}`, {
headers: this.headers,
noResolveJson: true,
});
const data = yield res.blob();
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Retrieves the details of an existing file.
* @param path
*/
info(path) {
return __awaiter(this, void 0, void 0, function* () {
const _path = this._getFinalPath(path);
try {
const data = yield (0, fetch_1.get)(this.fetch, `${this.url}/object/info/${_path}`, {
headers: this.headers,
});
return { data: (0, helpers_1.recursiveToCamel)(data), error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Checks the existence of a file.
* @param path
*/
exists(path) {
return __awaiter(this, void 0, void 0, function* () {
const _path = this._getFinalPath(path);
try {
yield (0, fetch_1.head)(this.fetch, `${this.url}/object/${_path}`, {
headers: this.headers,
});
return { data: true, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error) && error instanceof errors_1.StorageUnknownError) {
const originalError = error.originalError;
if ([400, 404].includes(originalError === null || originalError === void 0 ? void 0 : originalError.status)) {
return { data: false, error };
}
}
throw error;
}
});
}
/**
* A simple convenience function to get the URL for an asset in a public bucket. If you do not want to use this function, you can construct the public URL by concatenating the bucket URL with the path to the asset.
* This function does not verify if the bucket is public. If a public URL is created for a bucket which is not public, you will not be able to download the asset.
*
* @param path The path and name of the file to generate the public URL for. For example `folder/image.png`.
* @param options.download Triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename.
* @param options.transform Transform the asset before serving it to the client.
*/
getPublicUrl(path, options) {
const _path = this._getFinalPath(path);
const _queryString = [];
const downloadQueryParam = (options === null || options === void 0 ? void 0 : options.download)
? `download=${options.download === true ? '' : options.download}`
: '';
if (downloadQueryParam !== '') {
_queryString.push(downloadQueryParam);
}
const wantsTransformation = typeof (options === null || options === void 0 ? void 0 : options.transform) !== 'undefined';
const renderPath = wantsTransformation ? 'render/image' : 'object';
const transformationQuery = this.transformOptsToQueryString((options === null || options === void 0 ? void 0 : options.transform) || {});
if (transformationQuery !== '') {
_queryString.push(transformationQuery);
}
let queryString = _queryString.join('&');
if (queryString !== '') {
queryString = `?${queryString}`;
}
return {
data: { publicUrl: encodeURI(`${this.url}/${renderPath}/public/${_path}${queryString}`) },
};
}
/**
* Deletes files within the same bucket
*
* @param paths An array of files to delete, including the path and file name. For example [`'folder/image.png'`].
*/
remove(paths) {
return __awaiter(this, void 0, void 0, function* () {
try {
const data = yield (0, fetch_1.remove)(this.fetch, `${this.url}/object/${this.bucketId}`, { prefixes: paths }, { headers: this.headers });
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* Get file metadata
* @param id the file id to retrieve metadata
*/
// async getMetadata(
// id: string
// ): Promise<
// | {
// data: Metadata
// error: null
// }
// | {
// data: null
// error: StorageError
// }
// > {
// try {
// const data = await get(this.fetch, `${this.url}/metadata/${id}`, { headers: this.headers })
// return { data, error: null }
// } catch (error) {
// if (isStorageError(error)) {
// return { data: null, error }
// }
// throw error
// }
// }
/**
* Update file metadata
* @param id the file id to update metadata
* @param meta the new file metadata
*/
// async updateMetadata(
// id: string,
// meta: Metadata
// ): Promise<
// | {
// data: Metadata
// error: null
// }
// | {
// data: null
// error: StorageError
// }
// > {
// try {
// const data = await post(
// this.fetch,
// `${this.url}/metadata/${id}`,
// { ...meta },
// { headers: this.headers }
// )
// return { data, error: null }
// } catch (error) {
// if (isStorageError(error)) {
// return { data: null, error }
// }
// throw error
// }
// }
/**
* Lists all the files within a bucket.
* @param path The folder path.
* @param options Search options including limit (defaults to 100), offset, sortBy, and search
*/
list(path, options, parameters) {
return __awaiter(this, void 0, void 0, function* () {
try {
const body = Object.assign(Object.assign(Object.assign({}, DEFAULT_SEARCH_OPTIONS), options), { prefix: path || '' });
const data = yield (0, fetch_1.post)(this.fetch, `${this.url}/object/list/${this.bucketId}`, body, { headers: this.headers }, parameters);
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
/**
* @experimental this method signature might change in the future
* @param options search options
* @param parameters
*/
listV2(options, parameters) {
return __awaiter(this, void 0, void 0, function* () {
try {
const body = Object.assign({}, options);
const data = yield (0, fetch_1.post)(this.fetch, `${this.url}/object/list-v2/${this.bucketId}`, body, { headers: this.headers }, parameters);
return { data, error: null };
}
catch (error) {
if ((0, errors_1.isStorageError)(error)) {
return { data: null, error };
}
throw error;
}
});
}
encodeMetadata(metadata) {
return JSON.stringify(metadata);
}
toBase64(data) {
if (typeof Buffer !== 'undefined') {
return Buffer.from(data).toString('base64');
}
return btoa(data);
}
_getFinalPath(path) {
return `${this.bucketId}/${path.replace(/^\/+/, '')}`;
}
_removeEmptyFolders(path) {
return path.replace(/^\/|\/$/g, '').replace(/\/+/g, '/');
}
transformOptsToQueryString(transform) {
const params = [];
if (transform.width) {
params.push(`width=${transform.width}`);
}
if (transform.height) {
params.push(`height=${transform.height}`);
}
if (transform.resize) {
params.push(`resize=${transform.resize}`);
}
if (transform.format) {
params.push(`format=${transform.format}`);
}
if (transform.quality) {
params.push(`quality=${transform.quality}`);
}
return params.join('&');
}
}
exports.default = StorageFileApi;
//# sourceMappingURL=StorageFileApi.js.map
-70
View File
@@ -1,70 +0,0 @@
{
"name": "@supabase/storage-js",
"version": "2.11.0",
"description": "Isomorphic storage client for Supabase.",
"keywords": [
"javascript",
"typescript",
"supabase"
],
"homepage": "https://github.com/supabase/storage-js",
"bugs": "https://github.com/supabase/storage-js/issues",
"license": "MIT",
"author": "Supabase",
"files": [
"dist",
"src"
],
"main": "dist/main/index.js",
"module": "dist/module/index.js",
"types": "dist/module/index.d.ts",
"sideEffects": false,
"repository": "supabase/storage-js",
"scripts": {
"clean": "rimraf dist docs/v2",
"format": "prettier --write \"{src,test}/**/*.ts\"",
"build": "genversion src/lib/version.ts --es6 && run-s clean format build:*",
"build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json",
"build:umd": "webpack",
"types-generate": "dts-gen -m '@supabase/storage-js' -s",
"test": "run-s test:clean test:infra test:suite test:clean",
"test:suite": "jest --runInBand --coverage",
"test:infra": "cd infra && docker compose down && docker compose up -d --build && sleep 10",
"test:clean": "cd infra && docker compose down --remove-orphans",
"docs": "typedoc --entryPoints src/index.ts --out docs/v2 --entryPoints src/packages/* --excludePrivate --excludeProtected",
"docs:json": "typedoc --json docs/v2/spec.json --entryPoints src/index.ts --entryPoints src/packages/* --excludePrivate --excludeExternals --excludeProtected"
},
"dependencies": {
"@supabase/node-fetch": "^2.6.14"
},
"devDependencies": {
"@types/jest": "^26.0.13",
"form-data": "^4.0.0",
"genversion": "^3.0.1",
"husky": "^4.3.0",
"jest": "^29.0.0",
"jest-environment-jsdom": "^29.5.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.2",
"pretty-quick": "^3.1.0",
"rimraf": "^3.0.2",
"semantic-release-plugin-update-version-in-files": "^1.1.0",
"ts-jest": "^29.0.0",
"ts-loader": "^9.4.2",
"typedoc": "^0.22.16",
"typescript": "^4.6.3",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
},
"jsdelivr": "dist/umd/supabase.js",
"unpkg": "dist/umd/supabase.js",
"publishConfig": {
"access": "public"
}
}
@@ -1,229 +0,0 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const functions_js_1 = require("@supabase/functions-js");
const postgrest_js_1 = require("@supabase/postgrest-js");
const realtime_js_1 = require("@supabase/realtime-js");
const storage_js_1 = require("@supabase/storage-js");
const constants_1 = require("./lib/constants");
const fetch_1 = require("./lib/fetch");
const helpers_1 = require("./lib/helpers");
const SupabaseAuthClient_1 = require("./lib/SupabaseAuthClient");
/**
* Supabase Client.
*
* An isomorphic Javascript client for interacting with Postgres.
*/
class SupabaseClient {
/**
* Create a new client for use in the browser.
* @param supabaseUrl The unique Supabase URL which is supplied when you create a new project in your project dashboard.
* @param supabaseKey The unique Supabase Key which is supplied when you create a new project in your project dashboard.
* @param options.db.schema You can switch in between schemas. The schema needs to be on the list of exposed schemas inside Supabase.
* @param options.auth.autoRefreshToken Set to "true" if you want to automatically refresh the token before expiring.
* @param options.auth.persistSession Set to "true" if you want to automatically save the user session into local storage.
* @param options.auth.detectSessionInUrl Set to "true" if you want to automatically detects OAuth grants in the URL and signs in the user.
* @param options.realtime Options passed along to realtime-js constructor.
* @param options.storage Options passed along to the storage-js constructor.
* @param options.global.fetch A custom fetch implementation.
* @param options.global.headers Any additional headers to send with each network request.
*/
constructor(supabaseUrl, supabaseKey, options) {
var _a, _b, _c;
this.supabaseUrl = supabaseUrl;
this.supabaseKey = supabaseKey;
if (!supabaseUrl)
throw new Error('supabaseUrl is required.');
if (!supabaseKey)
throw new Error('supabaseKey is required.');
const _supabaseUrl = (0, helpers_1.ensureTrailingSlash)(supabaseUrl);
const baseUrl = new URL(_supabaseUrl);
this.realtimeUrl = new URL('realtime/v1', baseUrl);
this.realtimeUrl.protocol = this.realtimeUrl.protocol.replace('http', 'ws');
this.authUrl = new URL('auth/v1', baseUrl);
this.storageUrl = new URL('storage/v1', baseUrl);
this.functionsUrl = new URL('functions/v1', baseUrl);
// default storage key uses the supabase project ref as a namespace
const defaultStorageKey = `sb-${baseUrl.hostname.split('.')[0]}-auth-token`;
const DEFAULTS = {
db: constants_1.DEFAULT_DB_OPTIONS,
realtime: constants_1.DEFAULT_REALTIME_OPTIONS,
auth: Object.assign(Object.assign({}, constants_1.DEFAULT_AUTH_OPTIONS), { storageKey: defaultStorageKey }),
global: constants_1.DEFAULT_GLOBAL_OPTIONS,
};
const settings = (0, helpers_1.applySettingDefaults)(options !== null && options !== void 0 ? options : {}, DEFAULTS);
this.storageKey = (_a = settings.auth.storageKey) !== null && _a !== void 0 ? _a : '';
this.headers = (_b = settings.global.headers) !== null && _b !== void 0 ? _b : {};
if (!settings.accessToken) {
this.auth = this._initSupabaseAuthClient((_c = settings.auth) !== null && _c !== void 0 ? _c : {}, this.headers, settings.global.fetch);
}
else {
this.accessToken = settings.accessToken;
this.auth = new Proxy({}, {
get: (_, prop) => {
throw new Error(`@supabase/supabase-js: Supabase Client is configured with the accessToken option, accessing supabase.auth.${String(prop)} is not possible`);
},
});
}
this.fetch = (0, fetch_1.fetchWithAuth)(supabaseKey, this._getAccessToken.bind(this), settings.global.fetch);
this.realtime = this._initRealtimeClient(Object.assign({ headers: this.headers, accessToken: this._getAccessToken.bind(this) }, settings.realtime));
this.rest = new postgrest_js_1.PostgrestClient(new URL('rest/v1', baseUrl).href, {
headers: this.headers,
schema: settings.db.schema,
fetch: this.fetch,
});
this.storage = new storage_js_1.StorageClient(this.storageUrl.href, this.headers, this.fetch, options === null || options === void 0 ? void 0 : options.storage);
if (!settings.accessToken) {
this._listenForAuthEvents();
}
}
/**
* Supabase Functions allows you to deploy and invoke edge functions.
*/
get functions() {
return new functions_js_1.FunctionsClient(this.functionsUrl.href, {
headers: this.headers,
customFetch: this.fetch,
});
}
/**
* Perform a query on a table or a view.
*
* @param relation - The table or view name to query
*/
from(relation) {
return this.rest.from(relation);
}
// NOTE: signatures must be kept in sync with PostgrestClient.schema
/**
* 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 this.rest.schema(schema);
}
// NOTE: signatures must be kept in sync with PostgrestClient.rpc
/**
* 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.
*/
rpc(fn, args = {}, options = {}) {
return this.rest.rpc(fn, args, options);
}
/**
* Creates a Realtime channel with Broadcast, Presence, and Postgres Changes.
*
* @param {string} name - The name of the Realtime channel.
* @param {Object} opts - The options to pass to the Realtime channel.
*
*/
channel(name, opts = { config: {} }) {
return this.realtime.channel(name, opts);
}
/**
* Returns all Realtime channels.
*/
getChannels() {
return this.realtime.getChannels();
}
/**
* Unsubscribes and removes Realtime channel from Realtime client.
*
* @param {RealtimeChannel} channel - The name of the Realtime channel.
*
*/
removeChannel(channel) {
return this.realtime.removeChannel(channel);
}
/**
* Unsubscribes and removes all Realtime channels from Realtime client.
*/
removeAllChannels() {
return this.realtime.removeAllChannels();
}
_getAccessToken() {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
if (this.accessToken) {
return yield this.accessToken();
}
const { data } = yield this.auth.getSession();
return (_b = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token) !== null && _b !== void 0 ? _b : this.supabaseKey;
});
}
_initSupabaseAuthClient({ autoRefreshToken, persistSession, detectSessionInUrl, storage, storageKey, flowType, lock, debug, }, headers, fetch) {
const authHeaders = {
Authorization: `Bearer ${this.supabaseKey}`,
apikey: `${this.supabaseKey}`,
};
return new SupabaseAuthClient_1.SupabaseAuthClient({
url: this.authUrl.href,
headers: Object.assign(Object.assign({}, authHeaders), headers),
storageKey: storageKey,
autoRefreshToken,
persistSession,
detectSessionInUrl,
storage,
flowType,
lock,
debug,
fetch,
// auth checks if there is a custom authorizaiton header using this flag
// so it knows whether to return an error when getUser is called with no session
hasCustomAuthorizationHeader: 'Authorization' in this.headers,
});
}
_initRealtimeClient(options) {
return new realtime_js_1.RealtimeClient(this.realtimeUrl.href, Object.assign(Object.assign({}, options), { params: Object.assign({ apikey: this.supabaseKey }, options === null || options === void 0 ? void 0 : options.params) }));
}
_listenForAuthEvents() {
let data = this.auth.onAuthStateChange((event, session) => {
this._handleTokenChanged(event, 'CLIENT', session === null || session === void 0 ? void 0 : session.access_token);
});
return data;
}
_handleTokenChanged(event, source, token) {
if ((event === 'TOKEN_REFRESHED' || event === 'SIGNED_IN') &&
this.changedAccessToken !== token) {
this.changedAccessToken = token;
}
else if (event === 'SIGNED_OUT') {
this.realtime.setAuth();
if (source == 'STORAGE')
this.auth.signOut();
this.changedAccessToken = undefined;
}
}
}
exports.default = SupabaseClient;
//# sourceMappingURL=SupabaseClient.js.map
-68
View File
@@ -1,68 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createClient = exports.SupabaseClient = exports.FunctionRegion = exports.FunctionsError = exports.FunctionsRelayError = exports.FunctionsFetchError = exports.FunctionsHttpError = exports.PostgrestError = void 0;
const SupabaseClient_1 = __importDefault(require("./SupabaseClient"));
__exportStar(require("@supabase/auth-js"), exports);
var postgrest_js_1 = require("@supabase/postgrest-js");
Object.defineProperty(exports, "PostgrestError", { enumerable: true, get: function () { return postgrest_js_1.PostgrestError; } });
var functions_js_1 = require("@supabase/functions-js");
Object.defineProperty(exports, "FunctionsHttpError", { enumerable: true, get: function () { return functions_js_1.FunctionsHttpError; } });
Object.defineProperty(exports, "FunctionsFetchError", { enumerable: true, get: function () { return functions_js_1.FunctionsFetchError; } });
Object.defineProperty(exports, "FunctionsRelayError", { enumerable: true, get: function () { return functions_js_1.FunctionsRelayError; } });
Object.defineProperty(exports, "FunctionsError", { enumerable: true, get: function () { return functions_js_1.FunctionsError; } });
Object.defineProperty(exports, "FunctionRegion", { enumerable: true, get: function () { return functions_js_1.FunctionRegion; } });
__exportStar(require("@supabase/realtime-js"), exports);
var SupabaseClient_2 = require("./SupabaseClient");
Object.defineProperty(exports, "SupabaseClient", { enumerable: true, get: function () { return __importDefault(SupabaseClient_2).default; } });
/**
* Creates a new Supabase Client.
*/
const createClient = (supabaseUrl, supabaseKey, options) => {
return new SupabaseClient_1.default(supabaseUrl, supabaseKey, options);
};
exports.createClient = createClient;
// Check for Node.js <= 18 deprecation
function shouldShowDeprecationWarning() {
// Skip in browser environments
if (typeof window !== 'undefined') {
return false;
}
// Skip if process is not available (e.g., Edge Runtime)
if (typeof process === 'undefined') {
return false;
}
// Use dynamic property access to avoid Next.js Edge Runtime static analysis warnings
const processVersion = process['version'];
if (processVersion === undefined || processVersion === null) {
return false;
}
const versionMatch = processVersion.match(/^v(\d+)\./);
if (!versionMatch) {
return false;
}
const majorVersion = parseInt(versionMatch[1], 10);
return majorVersion <= 18;
}
if (shouldShowDeprecationWarning()) {
console.warn(`⚠️ Node.js 18 and below are deprecated and will no longer be supported in future versions of @supabase/supabase-js. ` +
`Please upgrade to Node.js 20 or later. ` +
`For more information, visit: https://github.com/orgs/supabase/discussions/37217`);
}
//# sourceMappingURL=index.js.map
@@ -1,11 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SupabaseAuthClient = void 0;
const auth_js_1 = require("@supabase/auth-js");
class SupabaseAuthClient extends auth_js_1.AuthClient {
constructor(options) {
super(options);
}
}
exports.SupabaseAuthClient = SupabaseAuthClient;
//# sourceMappingURL=SupabaseAuthClient.js.map
@@ -1,33 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_REALTIME_OPTIONS = exports.DEFAULT_AUTH_OPTIONS = exports.DEFAULT_DB_OPTIONS = exports.DEFAULT_GLOBAL_OPTIONS = exports.DEFAULT_HEADERS = void 0;
const version_1 = require("./version");
let JS_ENV = '';
// @ts-ignore
if (typeof Deno !== 'undefined') {
JS_ENV = 'deno';
}
else if (typeof document !== 'undefined') {
JS_ENV = 'web';
}
else if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
JS_ENV = 'react-native';
}
else {
JS_ENV = 'node';
}
exports.DEFAULT_HEADERS = { 'X-Client-Info': `supabase-js-${JS_ENV}/${version_1.version}` };
exports.DEFAULT_GLOBAL_OPTIONS = {
headers: exports.DEFAULT_HEADERS,
};
exports.DEFAULT_DB_OPTIONS = {
schema: 'public',
};
exports.DEFAULT_AUTH_OPTIONS = {
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true,
flowType: 'implicit',
};
exports.DEFAULT_REALTIME_OPTIONS = {};
//# sourceMappingURL=constants.js.map
@@ -1,76 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchWithAuth = exports.resolveHeadersConstructor = exports.resolveFetch = void 0;
// @ts-ignore
const node_fetch_1 = __importStar(require("@supabase/node-fetch"));
const resolveFetch = (customFetch) => {
let _fetch;
if (customFetch) {
_fetch = customFetch;
}
else if (typeof fetch === 'undefined') {
_fetch = node_fetch_1.default;
}
else {
_fetch = fetch;
}
return (...args) => _fetch(...args);
};
exports.resolveFetch = resolveFetch;
const resolveHeadersConstructor = () => {
if (typeof Headers === 'undefined') {
return node_fetch_1.Headers;
}
return Headers;
};
exports.resolveHeadersConstructor = resolveHeadersConstructor;
const fetchWithAuth = (supabaseKey, getAccessToken, customFetch) => {
const fetch = (0, exports.resolveFetch)(customFetch);
const HeadersConstructor = (0, exports.resolveHeadersConstructor)();
return (input, init) => __awaiter(void 0, void 0, void 0, function* () {
var _a;
const accessToken = (_a = (yield getAccessToken())) !== null && _a !== void 0 ? _a : supabaseKey;
let headers = new HeadersConstructor(init === null || init === void 0 ? void 0 : init.headers);
if (!headers.has('apikey')) {
headers.set('apikey', supabaseKey);
}
if (!headers.has('Authorization')) {
headers.set('Authorization', `Bearer ${accessToken}`);
}
return fetch(input, Object.assign(Object.assign({}, init), { headers }));
});
};
exports.fetchWithAuth = fetchWithAuth;
//# sourceMappingURL=fetch.js.map
@@ -1,48 +0,0 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.applySettingDefaults = exports.isBrowser = exports.ensureTrailingSlash = exports.uuid = void 0;
function uuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
exports.uuid = uuid;
function ensureTrailingSlash(url) {
return url.endsWith('/') ? url : url + '/';
}
exports.ensureTrailingSlash = ensureTrailingSlash;
const isBrowser = () => typeof window !== 'undefined';
exports.isBrowser = isBrowser;
function applySettingDefaults(options, defaults) {
var _a, _b;
const { db: dbOptions, auth: authOptions, realtime: realtimeOptions, global: globalOptions, } = options;
const { db: DEFAULT_DB_OPTIONS, auth: DEFAULT_AUTH_OPTIONS, realtime: DEFAULT_REALTIME_OPTIONS, global: DEFAULT_GLOBAL_OPTIONS, } = defaults;
const result = {
db: Object.assign(Object.assign({}, DEFAULT_DB_OPTIONS), dbOptions),
auth: Object.assign(Object.assign({}, DEFAULT_AUTH_OPTIONS), authOptions),
realtime: Object.assign(Object.assign({}, DEFAULT_REALTIME_OPTIONS), realtimeOptions),
storage: {},
global: Object.assign(Object.assign(Object.assign({}, DEFAULT_GLOBAL_OPTIONS), globalOptions), { headers: Object.assign(Object.assign({}, ((_a = DEFAULT_GLOBAL_OPTIONS === null || DEFAULT_GLOBAL_OPTIONS === void 0 ? void 0 : DEFAULT_GLOBAL_OPTIONS.headers) !== null && _a !== void 0 ? _a : {})), ((_b = globalOptions === null || globalOptions === void 0 ? void 0 : globalOptions.headers) !== null && _b !== void 0 ? _b : {})) }),
accessToken: () => __awaiter(this, void 0, void 0, function* () { return ''; }),
};
if (options.accessToken) {
result.accessToken = options.accessToken;
}
else {
// hack around Required<>
delete result.accessToken;
}
return result;
}
exports.applySettingDefaults = applySettingDefaults;
//# sourceMappingURL=helpers.js.map
@@ -1,5 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = void 0;
exports.version = '2.55.0';
//# sourceMappingURL=version.js.map
-90
View File
@@ -1,90 +0,0 @@
{
"name": "@supabase/supabase-js",
"version": "2.55.0",
"description": "Isomorphic Javascript client for Supabase",
"keywords": [
"javascript",
"typescript",
"supabase"
],
"homepage": "https://github.com/supabase/supabase-js",
"bugs": "https://github.com/supabase/supabase-js/issues",
"license": "MIT",
"author": "Supabase",
"files": [
"dist",
"src"
],
"main": "dist/main/index.js",
"module": "dist/module/index.js",
"types": "dist/module/index.d.ts",
"sideEffects": false,
"repository": "supabase/supabase-js",
"scripts": {
"clean": "rimraf dist docs/v2",
"format": "prettier --write \"{src,test}/**/*.ts\"",
"build": "run-s clean format build:*",
"build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json",
"build:umd": "webpack --env mode=production",
"types-generate": "dts-gen -m '@supabase/supabase-js' -s",
"test": "run-s test:types test:run",
"test:all": "run-s test:types test:run test:integration test:integration:browser",
"test:run": "jest --runInBand --detectOpenHandles",
"test:unit": "jest --runInBand --detectOpenHandles test/unit",
"test:coverage": "jest --runInBand --coverage --testPathIgnorePatterns=\"test/integration|test/deno\"",
"test:integration": "jest --runInBand --detectOpenHandles test/integration.test.ts",
"test:integration:browser": "deno test --allow-all test/integration.browser.test.ts",
"test:edge-functions": "deno test --allow-all --no-check test/deno/edge-functions-integration.test.ts",
"test:watch": "jest --watch --verbose false --silent false",
"test:node:playwright": "cd test/integration/node-browser && npm install && cp ../../../dist/umd/supabase.js . && npm run test",
"test:bun": "cd test/integration/bun && bun install && bun test",
"test:types": "run-s build:module && tsd --files test/types/*.test-d.ts && jsr publish --dry-run",
"docs": "typedoc --entryPoints src/index.ts --out docs/v2 --includes src/**/*.ts",
"docs:json": "typedoc --entryPoints src/index.ts --includes src/**/*.ts --json docs/v2/spec.json --excludeExternals",
"serve:coverage": "npm run test:coverage && serve test/coverage",
"update:test-deps": "npm run build && npm pack && cp supabase-supabase-js-*.tgz test/integration/expo/supabase-supabase-js-0.0.0-automated.tgz && cp supabase-supabase-js-*.tgz test/integration/next/supabase-supabase-js-0.0.0-automated.tgz && cp supabase-supabase-js-*.tgz test/deno/supabase-supabase-js-0.0.0-automated.tgz && cp supabase-supabase-js-*.tgz test/integration/bun/supabase-supabase-js-0.0.0-automated.tgz && cd test/integration/expo && npm install && cd ../next && npm install --legacy-peer-deps && cd ../../deno && npm install && cd ../integration/bun && bun install",
"update:test-deps:expo": "npm run build && npm pack && cp supabase-supabase-js-*.tgz test/integration/expo/supabase-supabase-js-0.0.0-automated.tgz && cd test/integration/expo && npm install",
"update:test-deps:next": "npm run build && npm pack && cp supabase-supabase-js-*.tgz test/integration/next/supabase-supabase-js-0.0.0-automated.tgz && cd test/integration/next && npm install --legacy-peer-deps",
"update:test-deps:deno": "npm run build && npm pack && cp supabase-supabase-js-*.tgz test/deno/supabase-supabase-js-0.0.0-automated.tgz && cd test/deno && npm install",
"update:test-deps:bun": "npm run build && npm pack && cp supabase-supabase-js-*.tgz test/integration/bun/supabase-supabase-js-0.0.0-automated.tgz && cd test/integration/bun && bun install"
},
"dependencies": {
"@supabase/auth-js": "2.71.1",
"@supabase/functions-js": "2.4.5",
"@supabase/node-fetch": "2.6.15",
"@supabase/postgrest-js": "1.19.4",
"@supabase/realtime-js": "2.15.1",
"@supabase/storage-js": "^2.10.4"
},
"devDependencies": {
"@sebbo2002/semantic-release-jsr": "^1.0.0",
"@solana/wallet-standard-features": "^1.3.0",
"@types/jest": "^29.2.5",
"husky": "^4.3.8",
"jest": "^29.3.1",
"jsr": "^0.13.5",
"npm-run-all": "^4.1.5",
"prettier": "^2.5.1",
"pretty-quick": "^3.1.3",
"puppeteer": "^24.9.0",
"rimraf": "^3.0.2",
"semantic-release-plugin-update-version-in-files": "^1.1.0",
"serve": "^14.2.1",
"ts-jest": "^29.0.5",
"ts-loader": "^8.0.11",
"ts-node": "^10.9.1",
"tsd": "^0.30.4",
"typedoc": "^0.22.16",
"typescript": "^4.5.5",
"webpack": "^5.69.1",
"webpack-cli": "^4.9.2"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
},
"jsdelivr": "dist/umd/supabase.js",
"unpkg": "dist/umd/supabase.js"
}