@redbase/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +204 -0
- package/dist/index.cjs +1709 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +165 -0
- package/dist/index.d.ts +165 -0
- package/dist/index.js +1669 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1709 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var supabaseJs = require('@supabase/supabase-js');
|
|
4
|
+
|
|
5
|
+
// src/client.ts
|
|
6
|
+
|
|
7
|
+
// src/email.ts
|
|
8
|
+
function createEmailClient(redbaseUrl, apiKey) {
|
|
9
|
+
const baseUrl = redbaseUrl.replace(/\/$/, "");
|
|
10
|
+
return {
|
|
11
|
+
async send(options) {
|
|
12
|
+
const url = `${baseUrl}/email/v1/send`;
|
|
13
|
+
try {
|
|
14
|
+
const response = await fetch(url, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: {
|
|
17
|
+
Authorization: `Bearer ${apiKey}`,
|
|
18
|
+
apikey: apiKey,
|
|
19
|
+
"Content-Type": "application/json"
|
|
20
|
+
},
|
|
21
|
+
body: JSON.stringify({
|
|
22
|
+
to: Array.isArray(options.to) ? options.to : [options.to],
|
|
23
|
+
subject: options.subject,
|
|
24
|
+
html: options.html,
|
|
25
|
+
text: options.text,
|
|
26
|
+
reply_to: options.replyTo,
|
|
27
|
+
cc: options.cc ? Array.isArray(options.cc) ? options.cc : [options.cc] : void 0,
|
|
28
|
+
bcc: options.bcc ? Array.isArray(options.bcc) ? options.bcc : [options.bcc] : void 0
|
|
29
|
+
})
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const errorBody = await response.text();
|
|
33
|
+
let errorMessage;
|
|
34
|
+
try {
|
|
35
|
+
const parsed = JSON.parse(errorBody);
|
|
36
|
+
errorMessage = parsed.error || parsed.message || errorBody;
|
|
37
|
+
} catch {
|
|
38
|
+
errorMessage = errorBody || `HTTP ${response.status}`;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
error: errorMessage
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const data = await response.json();
|
|
46
|
+
return {
|
|
47
|
+
success: true,
|
|
48
|
+
messageId: data.message_id || data.messageId
|
|
49
|
+
};
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return {
|
|
52
|
+
success: false,
|
|
53
|
+
error: error instanceof Error ? error.message : "Unknown error sending email"
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/client.ts
|
|
61
|
+
function createClient(redbaseUrl, redbaseKey, options) {
|
|
62
|
+
const supabase = supabaseJs.createClient(
|
|
63
|
+
redbaseUrl,
|
|
64
|
+
redbaseKey,
|
|
65
|
+
options
|
|
66
|
+
);
|
|
67
|
+
const email = createEmailClient(redbaseUrl, redbaseKey);
|
|
68
|
+
return Object.assign(supabase, { email });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// node_modules/@supabase/auth-js/dist/module/lib/errors.js
|
|
72
|
+
var AuthError = class extends Error {
|
|
73
|
+
constructor(message, status, code) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.__isAuthError = true;
|
|
76
|
+
this.name = "AuthError";
|
|
77
|
+
this.status = status;
|
|
78
|
+
this.code = code;
|
|
79
|
+
}
|
|
80
|
+
toJSON() {
|
|
81
|
+
return {
|
|
82
|
+
name: this.name,
|
|
83
|
+
message: this.message,
|
|
84
|
+
status: this.status,
|
|
85
|
+
code: this.code
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var AuthApiError = class extends AuthError {
|
|
90
|
+
constructor(message, status, code) {
|
|
91
|
+
super(message, status, code);
|
|
92
|
+
this.name = "AuthApiError";
|
|
93
|
+
this.status = status;
|
|
94
|
+
this.code = code;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// node_modules/@supabase/auth-js/dist/module/lib/base64url.js
|
|
99
|
+
var TO_BASE64URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".split("");
|
|
100
|
+
var IGNORE_BASE64URL = " \n\r=".split("");
|
|
101
|
+
(() => {
|
|
102
|
+
const charMap = new Array(128);
|
|
103
|
+
for (let i = 0; i < charMap.length; i += 1) {
|
|
104
|
+
charMap[i] = -1;
|
|
105
|
+
}
|
|
106
|
+
for (let i = 0; i < IGNORE_BASE64URL.length; i += 1) {
|
|
107
|
+
charMap[IGNORE_BASE64URL[i].charCodeAt(0)] = -2;
|
|
108
|
+
}
|
|
109
|
+
for (let i = 0; i < TO_BASE64URL.length; i += 1) {
|
|
110
|
+
charMap[TO_BASE64URL[i].charCodeAt(0)] = i;
|
|
111
|
+
}
|
|
112
|
+
return charMap;
|
|
113
|
+
})();
|
|
114
|
+
var isBrowser = () => typeof window !== "undefined" && typeof document !== "undefined";
|
|
115
|
+
var localStorageWriteTests = {
|
|
116
|
+
tested: false,
|
|
117
|
+
writable: false
|
|
118
|
+
};
|
|
119
|
+
var supportsLocalStorage = () => {
|
|
120
|
+
if (!isBrowser()) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
if (typeof globalThis.localStorage !== "object") {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
} catch (e) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
if (localStorageWriteTests.tested) {
|
|
131
|
+
return localStorageWriteTests.writable;
|
|
132
|
+
}
|
|
133
|
+
const randomKey = `lswt-${Math.random()}${Math.random()}`;
|
|
134
|
+
try {
|
|
135
|
+
globalThis.localStorage.setItem(randomKey, randomKey);
|
|
136
|
+
globalThis.localStorage.removeItem(randomKey);
|
|
137
|
+
localStorageWriteTests.tested = true;
|
|
138
|
+
localStorageWriteTests.writable = true;
|
|
139
|
+
} catch (e) {
|
|
140
|
+
localStorageWriteTests.tested = true;
|
|
141
|
+
localStorageWriteTests.writable = false;
|
|
142
|
+
}
|
|
143
|
+
return localStorageWriteTests.writable;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// node_modules/@supabase/auth-js/dist/module/lib/locks.js
|
|
147
|
+
({
|
|
148
|
+
/**
|
|
149
|
+
* @experimental
|
|
150
|
+
*/
|
|
151
|
+
debug: !!(globalThis && supportsLocalStorage() && globalThis.localStorage && globalThis.localStorage.getItem("supabase.gotrue-js.locks.debug") === "true")
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// node_modules/@supabase/auth-js/dist/module/lib/polyfills.js
|
|
155
|
+
function polyfillGlobalThis() {
|
|
156
|
+
if (typeof globalThis === "object")
|
|
157
|
+
return;
|
|
158
|
+
try {
|
|
159
|
+
Object.defineProperty(Object.prototype, "__magic__", {
|
|
160
|
+
get: function() {
|
|
161
|
+
return this;
|
|
162
|
+
},
|
|
163
|
+
configurable: true
|
|
164
|
+
});
|
|
165
|
+
__magic__.globalThis = __magic__;
|
|
166
|
+
delete Object.prototype.__magic__;
|
|
167
|
+
} catch (e) {
|
|
168
|
+
if (typeof self !== "undefined") {
|
|
169
|
+
self.globalThis = self;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// node_modules/@supabase/auth-js/dist/module/GoTrueClient.js
|
|
175
|
+
polyfillGlobalThis();
|
|
176
|
+
var DEFAULT_POSTGRES_CHANGES_WAIT_TIMEOUT = 15e3;
|
|
177
|
+
var POSTGRES_CHANGES_WAIT_ERROR_GRACE = 1e4;
|
|
178
|
+
var MAX_PUSH_BUFFER_SIZE = 100;
|
|
179
|
+
var CHANNEL_STATES = {
|
|
180
|
+
closed: "closed",
|
|
181
|
+
errored: "errored",
|
|
182
|
+
joined: "joined",
|
|
183
|
+
joining: "joining",
|
|
184
|
+
leaving: "leaving"
|
|
185
|
+
};
|
|
186
|
+
var CHANNEL_EVENTS = {
|
|
187
|
+
close: "phx_close",
|
|
188
|
+
error: "phx_error",
|
|
189
|
+
join: "phx_join",
|
|
190
|
+
leave: "phx_leave"};
|
|
191
|
+
|
|
192
|
+
// node_modules/@supabase/realtime-js/dist/module/lib/transformers.js
|
|
193
|
+
var PostgresTypes;
|
|
194
|
+
(function(PostgresTypes2) {
|
|
195
|
+
PostgresTypes2["abstime"] = "abstime";
|
|
196
|
+
PostgresTypes2["bool"] = "bool";
|
|
197
|
+
PostgresTypes2["date"] = "date";
|
|
198
|
+
PostgresTypes2["daterange"] = "daterange";
|
|
199
|
+
PostgresTypes2["float4"] = "float4";
|
|
200
|
+
PostgresTypes2["float8"] = "float8";
|
|
201
|
+
PostgresTypes2["int2"] = "int2";
|
|
202
|
+
PostgresTypes2["int4"] = "int4";
|
|
203
|
+
PostgresTypes2["int4range"] = "int4range";
|
|
204
|
+
PostgresTypes2["int8"] = "int8";
|
|
205
|
+
PostgresTypes2["int8range"] = "int8range";
|
|
206
|
+
PostgresTypes2["json"] = "json";
|
|
207
|
+
PostgresTypes2["jsonb"] = "jsonb";
|
|
208
|
+
PostgresTypes2["money"] = "money";
|
|
209
|
+
PostgresTypes2["numeric"] = "numeric";
|
|
210
|
+
PostgresTypes2["oid"] = "oid";
|
|
211
|
+
PostgresTypes2["reltime"] = "reltime";
|
|
212
|
+
PostgresTypes2["text"] = "text";
|
|
213
|
+
PostgresTypes2["time"] = "time";
|
|
214
|
+
PostgresTypes2["timestamp"] = "timestamp";
|
|
215
|
+
PostgresTypes2["timestamptz"] = "timestamptz";
|
|
216
|
+
PostgresTypes2["timetz"] = "timetz";
|
|
217
|
+
PostgresTypes2["tsrange"] = "tsrange";
|
|
218
|
+
PostgresTypes2["tstzrange"] = "tstzrange";
|
|
219
|
+
})(PostgresTypes || (PostgresTypes = {}));
|
|
220
|
+
var convertChangeData = (columns, record, options = {}) => {
|
|
221
|
+
var _a;
|
|
222
|
+
const skipTypes = (_a = options.skipTypes) !== null && _a !== void 0 ? _a : [];
|
|
223
|
+
if (!record) {
|
|
224
|
+
return {};
|
|
225
|
+
}
|
|
226
|
+
return Object.keys(record).reduce((acc, rec_key) => {
|
|
227
|
+
acc[rec_key] = convertColumn(rec_key, columns, record, skipTypes);
|
|
228
|
+
return acc;
|
|
229
|
+
}, {});
|
|
230
|
+
};
|
|
231
|
+
var convertColumn = (columnName, columns, record, skipTypes) => {
|
|
232
|
+
const column = columns.find((x) => x.name === columnName);
|
|
233
|
+
const colType = column === null || column === void 0 ? void 0 : column.type;
|
|
234
|
+
const value = record[columnName];
|
|
235
|
+
if (colType && !skipTypes.includes(colType)) {
|
|
236
|
+
return convertCell(colType, value);
|
|
237
|
+
}
|
|
238
|
+
return noop(value);
|
|
239
|
+
};
|
|
240
|
+
var convertCell = (type, value) => {
|
|
241
|
+
if (type.charAt(0) === "_") {
|
|
242
|
+
const dataType = type.slice(1, type.length);
|
|
243
|
+
return toArray(value, dataType);
|
|
244
|
+
}
|
|
245
|
+
switch (type) {
|
|
246
|
+
case PostgresTypes.bool:
|
|
247
|
+
return toBoolean(value);
|
|
248
|
+
case PostgresTypes.float4:
|
|
249
|
+
case PostgresTypes.float8:
|
|
250
|
+
case PostgresTypes.int2:
|
|
251
|
+
case PostgresTypes.int4:
|
|
252
|
+
case PostgresTypes.int8:
|
|
253
|
+
case PostgresTypes.numeric:
|
|
254
|
+
case PostgresTypes.oid:
|
|
255
|
+
return toNumber(value);
|
|
256
|
+
case PostgresTypes.json:
|
|
257
|
+
case PostgresTypes.jsonb:
|
|
258
|
+
return toJson(value);
|
|
259
|
+
case PostgresTypes.timestamp:
|
|
260
|
+
return toTimestampString(value);
|
|
261
|
+
// Format to be consistent with PostgREST
|
|
262
|
+
case PostgresTypes.abstime:
|
|
263
|
+
// To allow users to cast it based on Timezone
|
|
264
|
+
case PostgresTypes.date:
|
|
265
|
+
// To allow users to cast it based on Timezone
|
|
266
|
+
case PostgresTypes.daterange:
|
|
267
|
+
case PostgresTypes.int4range:
|
|
268
|
+
case PostgresTypes.int8range:
|
|
269
|
+
case PostgresTypes.money:
|
|
270
|
+
case PostgresTypes.reltime:
|
|
271
|
+
// To allow users to cast it based on Timezone
|
|
272
|
+
case PostgresTypes.text:
|
|
273
|
+
case PostgresTypes.time:
|
|
274
|
+
// To allow users to cast it based on Timezone
|
|
275
|
+
case PostgresTypes.timestamptz:
|
|
276
|
+
// To allow users to cast it based on Timezone
|
|
277
|
+
case PostgresTypes.timetz:
|
|
278
|
+
// To allow users to cast it based on Timezone
|
|
279
|
+
case PostgresTypes.tsrange:
|
|
280
|
+
case PostgresTypes.tstzrange:
|
|
281
|
+
return noop(value);
|
|
282
|
+
default:
|
|
283
|
+
return noop(value);
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
var noop = (value) => {
|
|
287
|
+
return value;
|
|
288
|
+
};
|
|
289
|
+
var toBoolean = (value) => {
|
|
290
|
+
switch (value) {
|
|
291
|
+
case "t":
|
|
292
|
+
return true;
|
|
293
|
+
case "f":
|
|
294
|
+
return false;
|
|
295
|
+
default:
|
|
296
|
+
return value;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
var toNumber = (value) => {
|
|
300
|
+
if (typeof value === "string") {
|
|
301
|
+
const parsedValue = parseFloat(value);
|
|
302
|
+
if (!Number.isNaN(parsedValue)) {
|
|
303
|
+
return parsedValue;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return value;
|
|
307
|
+
};
|
|
308
|
+
var toJson = (value) => {
|
|
309
|
+
if (typeof value === "string") {
|
|
310
|
+
try {
|
|
311
|
+
return JSON.parse(value);
|
|
312
|
+
} catch (_a) {
|
|
313
|
+
return value;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return value;
|
|
317
|
+
};
|
|
318
|
+
var toArray = (value, type) => {
|
|
319
|
+
if (typeof value !== "string") {
|
|
320
|
+
return value;
|
|
321
|
+
}
|
|
322
|
+
const lastIdx = value.length - 1;
|
|
323
|
+
const closeBrace = value[lastIdx];
|
|
324
|
+
const openBrace = value[0];
|
|
325
|
+
if (openBrace === "{" && closeBrace === "}") {
|
|
326
|
+
let arr;
|
|
327
|
+
const valTrim = value.slice(1, lastIdx);
|
|
328
|
+
try {
|
|
329
|
+
arr = JSON.parse("[" + valTrim + "]");
|
|
330
|
+
} catch (_) {
|
|
331
|
+
arr = valTrim ? valTrim.split(",") : [];
|
|
332
|
+
}
|
|
333
|
+
return arr.map((val) => convertCell(type, val));
|
|
334
|
+
}
|
|
335
|
+
return value;
|
|
336
|
+
};
|
|
337
|
+
var toTimestampString = (value) => {
|
|
338
|
+
if (typeof value === "string") {
|
|
339
|
+
return value.replace(" ", "T");
|
|
340
|
+
}
|
|
341
|
+
return value;
|
|
342
|
+
};
|
|
343
|
+
var httpEndpointURL = (socketUrl) => {
|
|
344
|
+
const wsUrl = new URL(socketUrl);
|
|
345
|
+
wsUrl.protocol = wsUrl.protocol.replace(/^ws/i, "http");
|
|
346
|
+
wsUrl.pathname = wsUrl.pathname.replace(/\/+$/, "").replace(/\/socket\/websocket$/i, "").replace(/\/socket$/i, "").replace(/\/websocket$/i, "");
|
|
347
|
+
if (wsUrl.pathname === "" || wsUrl.pathname === "/") {
|
|
348
|
+
wsUrl.pathname = "/api/broadcast";
|
|
349
|
+
} else {
|
|
350
|
+
wsUrl.pathname = wsUrl.pathname + "/api/broadcast";
|
|
351
|
+
}
|
|
352
|
+
return wsUrl.href;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// node_modules/@supabase/phoenix/priv/static/phoenix.mjs
|
|
356
|
+
var Presence = class _Presence {
|
|
357
|
+
/**
|
|
358
|
+
* Initializes the Presence
|
|
359
|
+
* @param {Channel} channel - The Channel
|
|
360
|
+
* @param {PresenceOptions} [opts] - The options, for example `{events: {state: "state", diff: "diff"}}`
|
|
361
|
+
*/
|
|
362
|
+
constructor(channel, opts = {}) {
|
|
363
|
+
let events = opts.events || /** @type {PresenceEvents} */
|
|
364
|
+
{ state: "presence_state", diff: "presence_diff" };
|
|
365
|
+
this.state = /* @__PURE__ */ Object.create(null);
|
|
366
|
+
this.pendingDiffs = [];
|
|
367
|
+
this.channel = channel;
|
|
368
|
+
this.joinRef = null;
|
|
369
|
+
this.caller = {
|
|
370
|
+
onJoin: function() {
|
|
371
|
+
},
|
|
372
|
+
onLeave: function() {
|
|
373
|
+
},
|
|
374
|
+
onSync: function() {
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
this.channel.on(events.state, (newState) => {
|
|
378
|
+
let { onJoin, onLeave, onSync } = this.caller;
|
|
379
|
+
this.joinRef = this.channel.joinRef();
|
|
380
|
+
this.state = _Presence.syncState(this.state, newState, onJoin, onLeave);
|
|
381
|
+
this.pendingDiffs.forEach((diff) => {
|
|
382
|
+
this.state = _Presence.syncDiff(this.state, diff, onJoin, onLeave);
|
|
383
|
+
});
|
|
384
|
+
this.pendingDiffs = [];
|
|
385
|
+
onSync();
|
|
386
|
+
});
|
|
387
|
+
this.channel.on(events.diff, (diff) => {
|
|
388
|
+
let { onJoin, onLeave, onSync } = this.caller;
|
|
389
|
+
if (this.inPendingSyncState()) {
|
|
390
|
+
this.pendingDiffs.push(diff);
|
|
391
|
+
} else {
|
|
392
|
+
this.state = _Presence.syncDiff(this.state, diff, onJoin, onLeave);
|
|
393
|
+
onSync();
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* @param {PresenceOnJoin} callback
|
|
399
|
+
*/
|
|
400
|
+
onJoin(callback) {
|
|
401
|
+
this.caller.onJoin = callback;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* @param {PresenceOnLeave} callback
|
|
405
|
+
*/
|
|
406
|
+
onLeave(callback) {
|
|
407
|
+
this.caller.onLeave = callback;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* @param {PresenceOnSync} callback
|
|
411
|
+
*/
|
|
412
|
+
onSync(callback) {
|
|
413
|
+
this.caller.onSync = callback;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Returns the array of presences, with selected metadata.
|
|
417
|
+
*
|
|
418
|
+
* @template [T=PresenceState]
|
|
419
|
+
* @param {((key: string, obj: PresenceState) => T)} [by]
|
|
420
|
+
*
|
|
421
|
+
* @returns {T[]}
|
|
422
|
+
*/
|
|
423
|
+
list(by) {
|
|
424
|
+
return _Presence.list(this.state, by);
|
|
425
|
+
}
|
|
426
|
+
inPendingSyncState() {
|
|
427
|
+
return !this.joinRef || this.joinRef !== this.channel.joinRef();
|
|
428
|
+
}
|
|
429
|
+
// lower-level public static API
|
|
430
|
+
/**
|
|
431
|
+
* Used to sync the list of presences on the server
|
|
432
|
+
* with the client's state. An optional `onJoin` and `onLeave` callback can
|
|
433
|
+
* be provided to react to changes in the client's local presences across
|
|
434
|
+
* disconnects and reconnects with the server.
|
|
435
|
+
*
|
|
436
|
+
* @param {Record<string, PresenceState>} currentState
|
|
437
|
+
* @param {Record<string, PresenceState>} newState
|
|
438
|
+
* @param {PresenceOnJoin} onJoin
|
|
439
|
+
* @param {PresenceOnLeave} onLeave
|
|
440
|
+
*
|
|
441
|
+
* @returns {Record<string, PresenceState>}
|
|
442
|
+
*/
|
|
443
|
+
static syncState(currentState, newState, onJoin, onLeave) {
|
|
444
|
+
let state = this.toNullProtoObj(this.clone(currentState));
|
|
445
|
+
newState = this.toNullProtoObj(newState);
|
|
446
|
+
let joins = /* @__PURE__ */ Object.create(null);
|
|
447
|
+
let leaves = /* @__PURE__ */ Object.create(null);
|
|
448
|
+
this.map(state, (key, presence) => {
|
|
449
|
+
if (!newState[key]) {
|
|
450
|
+
leaves[key] = presence;
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
this.map(newState, (key, newPresence) => {
|
|
454
|
+
let currentPresence = state[key];
|
|
455
|
+
if (currentPresence) {
|
|
456
|
+
let newRefs = newPresence.metas.map((m) => m.phx_ref);
|
|
457
|
+
let curRefs = currentPresence.metas.map((m) => m.phx_ref);
|
|
458
|
+
let joinedMetas = newPresence.metas.filter((m) => curRefs.indexOf(m.phx_ref) < 0);
|
|
459
|
+
let leftMetas = currentPresence.metas.filter((m) => newRefs.indexOf(m.phx_ref) < 0);
|
|
460
|
+
if (joinedMetas.length > 0) {
|
|
461
|
+
joins[key] = newPresence;
|
|
462
|
+
joins[key].metas = joinedMetas;
|
|
463
|
+
}
|
|
464
|
+
if (leftMetas.length > 0) {
|
|
465
|
+
leaves[key] = this.clone(currentPresence);
|
|
466
|
+
leaves[key].metas = leftMetas;
|
|
467
|
+
}
|
|
468
|
+
} else {
|
|
469
|
+
joins[key] = newPresence;
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
return this.syncDiff(state, { joins, leaves }, onJoin, onLeave);
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
*
|
|
476
|
+
* Used to sync a diff of presence join and leave
|
|
477
|
+
* events from the server, as they happen. Like `syncState`, `syncDiff`
|
|
478
|
+
* accepts optional `onJoin` and `onLeave` callbacks to react to a user
|
|
479
|
+
* joining or leaving from a device.
|
|
480
|
+
*
|
|
481
|
+
* @param {Record<string, PresenceState>} state
|
|
482
|
+
* @param {PresenceDiff} diff
|
|
483
|
+
* @param {PresenceOnJoin} onJoin
|
|
484
|
+
* @param {PresenceOnLeave} onLeave
|
|
485
|
+
*
|
|
486
|
+
* @returns {Record<string, PresenceState>}
|
|
487
|
+
*/
|
|
488
|
+
static syncDiff(state, diff, onJoin, onLeave) {
|
|
489
|
+
state = this.toNullProtoObj(state);
|
|
490
|
+
let { joins, leaves } = this.clone(diff);
|
|
491
|
+
if (!onJoin) {
|
|
492
|
+
onJoin = function() {
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
if (!onLeave) {
|
|
496
|
+
onLeave = function() {
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
this.map(joins, (key, newPresence) => {
|
|
500
|
+
let currentPresence = state[key];
|
|
501
|
+
state[key] = this.clone(newPresence);
|
|
502
|
+
if (currentPresence) {
|
|
503
|
+
let joinedRefs = state[key].metas.map((m) => m.phx_ref);
|
|
504
|
+
let curMetas = currentPresence.metas.filter((m) => joinedRefs.indexOf(m.phx_ref) < 0);
|
|
505
|
+
state[key].metas.unshift(...curMetas);
|
|
506
|
+
}
|
|
507
|
+
onJoin(key, currentPresence, newPresence);
|
|
508
|
+
});
|
|
509
|
+
this.map(leaves, (key, leftPresence) => {
|
|
510
|
+
let currentPresence = state[key];
|
|
511
|
+
if (!currentPresence) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
let refsToRemove = leftPresence.metas.map((m) => m.phx_ref);
|
|
515
|
+
currentPresence.metas = currentPresence.metas.filter((p) => {
|
|
516
|
+
return refsToRemove.indexOf(p.phx_ref) < 0;
|
|
517
|
+
});
|
|
518
|
+
onLeave(key, currentPresence, leftPresence);
|
|
519
|
+
if (currentPresence.metas.length === 0) {
|
|
520
|
+
delete state[key];
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
return state;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Returns the array of presences, with selected metadata.
|
|
527
|
+
*
|
|
528
|
+
* @template [T=PresenceState]
|
|
529
|
+
* @param {Record<string, PresenceState>} presences
|
|
530
|
+
* @param {((key: string, obj: PresenceState) => T)} [chooser]
|
|
531
|
+
*
|
|
532
|
+
* @returns {T[]}
|
|
533
|
+
*/
|
|
534
|
+
static list(presences, chooser) {
|
|
535
|
+
if (!chooser) {
|
|
536
|
+
chooser = function(key, pres) {
|
|
537
|
+
return pres;
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
return this.map(presences, (key, presence) => {
|
|
541
|
+
return chooser(key, presence);
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
// private
|
|
545
|
+
/**
|
|
546
|
+
* @template T
|
|
547
|
+
* @param {Record<string, PresenceState>} obj
|
|
548
|
+
* @param {(key: string, obj: PresenceState) => T} func
|
|
549
|
+
*/
|
|
550
|
+
static map(obj, func) {
|
|
551
|
+
return Object.getOwnPropertyNames(obj).map((key) => func(key, obj[key]));
|
|
552
|
+
}
|
|
553
|
+
// Presence keys are chosen on the server and may collide with
|
|
554
|
+
// Object.prototype properties ("__proto__", "constructor", ...), so any
|
|
555
|
+
// object indexed by presence key must not have a prototype chain
|
|
556
|
+
//
|
|
557
|
+
// TODO: replace the null-prototype objects with Maps in Phoenix 2.0
|
|
558
|
+
// (breaking change for the lower-level static API)
|
|
559
|
+
static toNullProtoObj(obj) {
|
|
560
|
+
if (Object.getPrototypeOf(obj) === null) {
|
|
561
|
+
return obj;
|
|
562
|
+
}
|
|
563
|
+
let cleaned = /* @__PURE__ */ Object.create(null);
|
|
564
|
+
Object.getOwnPropertyNames(obj).forEach((key) => {
|
|
565
|
+
cleaned[key] = obj[key];
|
|
566
|
+
});
|
|
567
|
+
return cleaned;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* @template T
|
|
571
|
+
* @param {T} obj
|
|
572
|
+
* @returns {T}
|
|
573
|
+
*/
|
|
574
|
+
static clone(obj) {
|
|
575
|
+
return JSON.parse(JSON.stringify(obj));
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
// node_modules/@supabase/realtime-js/dist/module/phoenix/presenceAdapter.js
|
|
580
|
+
var PresenceAdapter = class _PresenceAdapter {
|
|
581
|
+
constructor(channel, opts) {
|
|
582
|
+
const phoenixOptions = phoenixPresenceOptions(opts);
|
|
583
|
+
this.presence = new Presence(channel.getChannel(), phoenixOptions);
|
|
584
|
+
this.presence.onJoin((key, currentPresence, newPresence) => {
|
|
585
|
+
const onJoinPayload = _PresenceAdapter.onJoinPayload(key, currentPresence, newPresence);
|
|
586
|
+
channel.getChannel().trigger("presence", onJoinPayload);
|
|
587
|
+
});
|
|
588
|
+
this.presence.onLeave((key, currentPresence, leftPresence) => {
|
|
589
|
+
const onLeavePayload = _PresenceAdapter.onLeavePayload(key, currentPresence, leftPresence);
|
|
590
|
+
channel.getChannel().trigger("presence", onLeavePayload);
|
|
591
|
+
});
|
|
592
|
+
this.presence.onSync(() => {
|
|
593
|
+
channel.getChannel().trigger("presence", { event: "sync" });
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
get state() {
|
|
597
|
+
return _PresenceAdapter.transformState(this.presence.state);
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* @private
|
|
601
|
+
* Remove 'metas' key
|
|
602
|
+
* Change 'phx_ref' to 'presence_ref'
|
|
603
|
+
* Remove 'phx_ref' and 'phx_ref_prev'
|
|
604
|
+
*
|
|
605
|
+
* @example Transform state
|
|
606
|
+
* // returns {
|
|
607
|
+
* abc123: [
|
|
608
|
+
* { presence_ref: '2', user_id: 1 },
|
|
609
|
+
* { presence_ref: '3', user_id: 2 }
|
|
610
|
+
* ]
|
|
611
|
+
* }
|
|
612
|
+
* RealtimePresence.transformState({
|
|
613
|
+
* abc123: {
|
|
614
|
+
* metas: [
|
|
615
|
+
* { phx_ref: '2', phx_ref_prev: '1' user_id: 1 },
|
|
616
|
+
* { phx_ref: '3', user_id: 2 }
|
|
617
|
+
* ]
|
|
618
|
+
* }
|
|
619
|
+
* })
|
|
620
|
+
*
|
|
621
|
+
*/
|
|
622
|
+
static transformState(state) {
|
|
623
|
+
state = cloneState(state);
|
|
624
|
+
return Object.getOwnPropertyNames(state).reduce((newState, key) => {
|
|
625
|
+
const presences = state[key];
|
|
626
|
+
newState[key] = transformState(presences);
|
|
627
|
+
return newState;
|
|
628
|
+
}, {});
|
|
629
|
+
}
|
|
630
|
+
static onJoinPayload(key, currentPresence, newPresence) {
|
|
631
|
+
const currentPresences = parseCurrentPresences(currentPresence);
|
|
632
|
+
const newPresences = transformState(newPresence);
|
|
633
|
+
return {
|
|
634
|
+
event: "join",
|
|
635
|
+
key,
|
|
636
|
+
currentPresences,
|
|
637
|
+
newPresences
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
static onLeavePayload(key, currentPresence, leftPresence) {
|
|
641
|
+
const currentPresences = parseCurrentPresences(currentPresence);
|
|
642
|
+
const leftPresences = transformState(leftPresence);
|
|
643
|
+
return {
|
|
644
|
+
event: "leave",
|
|
645
|
+
key,
|
|
646
|
+
currentPresences,
|
|
647
|
+
leftPresences
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
function transformState(presences) {
|
|
652
|
+
return presences.metas.map((presence) => {
|
|
653
|
+
const descriptors = Object.getOwnPropertyDescriptors(presence);
|
|
654
|
+
const transformedPresence = Object.defineProperties({}, descriptors);
|
|
655
|
+
transformedPresence["presence_ref"] = transformedPresence["phx_ref"];
|
|
656
|
+
delete transformedPresence["phx_ref"];
|
|
657
|
+
delete transformedPresence["phx_ref_prev"];
|
|
658
|
+
return transformedPresence;
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
function cloneState(state) {
|
|
662
|
+
return JSON.parse(JSON.stringify(state));
|
|
663
|
+
}
|
|
664
|
+
function phoenixPresenceOptions(opts) {
|
|
665
|
+
return (opts === null || opts === void 0 ? void 0 : opts.events) && { events: opts.events };
|
|
666
|
+
}
|
|
667
|
+
function parseCurrentPresences(currentPresences) {
|
|
668
|
+
return (currentPresences === null || currentPresences === void 0 ? void 0 : currentPresences.metas) ? transformState(currentPresences) : [];
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// node_modules/@supabase/realtime-js/dist/module/RealtimePresence.js
|
|
672
|
+
exports.REALTIME_PRESENCE_LISTEN_EVENTS = void 0;
|
|
673
|
+
(function(REALTIME_PRESENCE_LISTEN_EVENTS2) {
|
|
674
|
+
REALTIME_PRESENCE_LISTEN_EVENTS2["SYNC"] = "sync";
|
|
675
|
+
REALTIME_PRESENCE_LISTEN_EVENTS2["JOIN"] = "join";
|
|
676
|
+
REALTIME_PRESENCE_LISTEN_EVENTS2["LEAVE"] = "leave";
|
|
677
|
+
})(exports.REALTIME_PRESENCE_LISTEN_EVENTS || (exports.REALTIME_PRESENCE_LISTEN_EVENTS = {}));
|
|
678
|
+
var RealtimePresence = class {
|
|
679
|
+
get state() {
|
|
680
|
+
return this.presenceAdapter.state;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Creates a Presence helper that keeps the local presence state in sync with the server.
|
|
684
|
+
*
|
|
685
|
+
* @param channel - The realtime channel to bind to.
|
|
686
|
+
* @param opts - Optional custom event names, e.g. `{ events: { state: 'state', diff: 'diff' } }`.
|
|
687
|
+
*
|
|
688
|
+
* @category Realtime
|
|
689
|
+
*
|
|
690
|
+
* @example Example for a presence channel
|
|
691
|
+
* ```ts
|
|
692
|
+
* const presence = new RealtimePresence(channel)
|
|
693
|
+
*
|
|
694
|
+
* channel.on('presence', ({ event, key }) => {
|
|
695
|
+
* console.log(`Presence ${event} on ${key}`)
|
|
696
|
+
* })
|
|
697
|
+
* ```
|
|
698
|
+
*/
|
|
699
|
+
constructor(channel, opts) {
|
|
700
|
+
this.channel = channel;
|
|
701
|
+
this.presenceAdapter = new PresenceAdapter(this.channel.channelAdapter, opts);
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
// node_modules/@supabase/realtime-js/dist/module/lib/normalizeChannelError.js
|
|
706
|
+
function normalizeChannelError(reason) {
|
|
707
|
+
if (reason instanceof Error) {
|
|
708
|
+
return reason;
|
|
709
|
+
}
|
|
710
|
+
if (typeof reason === "string") {
|
|
711
|
+
return new Error(reason);
|
|
712
|
+
}
|
|
713
|
+
if (reason && typeof reason === "object") {
|
|
714
|
+
const obj = reason;
|
|
715
|
+
if (typeof obj.code === "number") {
|
|
716
|
+
const detail = typeof obj.reason === "string" && obj.reason ? ` (${obj.reason})` : "";
|
|
717
|
+
return new Error(`socket closed: ${obj.code}${detail}`, { cause: reason });
|
|
718
|
+
}
|
|
719
|
+
return new Error("channel error: transport failure", { cause: reason });
|
|
720
|
+
}
|
|
721
|
+
return new Error("channel error: connection lost");
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// node_modules/@supabase/realtime-js/dist/module/phoenix/channelAdapter.js
|
|
725
|
+
var ChannelAdapter = class {
|
|
726
|
+
constructor(socket, topic, params) {
|
|
727
|
+
const phoenixParams = phoenixChannelParams(params);
|
|
728
|
+
this.channel = socket.getSocket().channel(topic, phoenixParams);
|
|
729
|
+
this.socket = socket;
|
|
730
|
+
}
|
|
731
|
+
get state() {
|
|
732
|
+
return this.channel.state;
|
|
733
|
+
}
|
|
734
|
+
set state(state) {
|
|
735
|
+
this.channel.state = state;
|
|
736
|
+
}
|
|
737
|
+
get joinedOnce() {
|
|
738
|
+
return this.channel.joinedOnce;
|
|
739
|
+
}
|
|
740
|
+
get joinPush() {
|
|
741
|
+
return this.channel.joinPush;
|
|
742
|
+
}
|
|
743
|
+
get rejoinTimer() {
|
|
744
|
+
return this.channel.rejoinTimer;
|
|
745
|
+
}
|
|
746
|
+
on(event, callback) {
|
|
747
|
+
return this.channel.on(event, callback);
|
|
748
|
+
}
|
|
749
|
+
off(event, refNumber) {
|
|
750
|
+
this.channel.off(event, refNumber);
|
|
751
|
+
}
|
|
752
|
+
subscribe(timeout) {
|
|
753
|
+
return this.channel.join(timeout);
|
|
754
|
+
}
|
|
755
|
+
unsubscribe(timeout) {
|
|
756
|
+
return this.channel.leave(timeout);
|
|
757
|
+
}
|
|
758
|
+
teardown() {
|
|
759
|
+
this.channel.teardown();
|
|
760
|
+
}
|
|
761
|
+
onClose(callback) {
|
|
762
|
+
this.channel.onClose(callback);
|
|
763
|
+
}
|
|
764
|
+
onError(callback) {
|
|
765
|
+
return this.channel.onError(callback);
|
|
766
|
+
}
|
|
767
|
+
push(event, payload, timeout) {
|
|
768
|
+
let push;
|
|
769
|
+
try {
|
|
770
|
+
push = this.channel.push(event, payload, timeout);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
throw new Error(`tried to push '${event}' to '${this.channel.topic}' before joining. Use channel.subscribe() before pushing events`);
|
|
773
|
+
}
|
|
774
|
+
if (this.channel.pushBuffer.length > MAX_PUSH_BUFFER_SIZE) {
|
|
775
|
+
const removedPush = this.channel.pushBuffer.shift();
|
|
776
|
+
removedPush.cancelTimeout();
|
|
777
|
+
this.socket.log("channel", `discarded push due to buffer overflow: ${removedPush.event}`, removedPush.payload());
|
|
778
|
+
}
|
|
779
|
+
return push;
|
|
780
|
+
}
|
|
781
|
+
updateJoinPayload(payload) {
|
|
782
|
+
const oldPayload = this.channel.joinPush.payload();
|
|
783
|
+
this.channel.joinPush.payload = () => Object.assign(Object.assign({}, oldPayload), payload);
|
|
784
|
+
}
|
|
785
|
+
canPush() {
|
|
786
|
+
return this.socket.isConnected() && this.state === CHANNEL_STATES.joined;
|
|
787
|
+
}
|
|
788
|
+
isJoined() {
|
|
789
|
+
return this.state === CHANNEL_STATES.joined;
|
|
790
|
+
}
|
|
791
|
+
isJoining() {
|
|
792
|
+
return this.state === CHANNEL_STATES.joining;
|
|
793
|
+
}
|
|
794
|
+
isClosed() {
|
|
795
|
+
return this.state === CHANNEL_STATES.closed;
|
|
796
|
+
}
|
|
797
|
+
isLeaving() {
|
|
798
|
+
return this.state === CHANNEL_STATES.leaving;
|
|
799
|
+
}
|
|
800
|
+
updateFilterBindings(filterBindings) {
|
|
801
|
+
this.channel.filterBindings = filterBindings;
|
|
802
|
+
}
|
|
803
|
+
updatePayloadTransform(callback) {
|
|
804
|
+
this.channel.onMessage = callback;
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* @internal
|
|
808
|
+
*/
|
|
809
|
+
getChannel() {
|
|
810
|
+
return this.channel;
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
function phoenixChannelParams(options) {
|
|
814
|
+
return {
|
|
815
|
+
config: Object.assign({
|
|
816
|
+
broadcast: { ack: false, self: false },
|
|
817
|
+
presence: { key: "", enabled: false },
|
|
818
|
+
private: false
|
|
819
|
+
}, options.config)
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// node_modules/@supabase/realtime-js/dist/module/RealtimePostgresFilterBuilder.js
|
|
824
|
+
var PostgrestReservedCharsRegexp = /[,()"\\]/;
|
|
825
|
+
var needsQuoting = (value) => PostgrestReservedCharsRegexp.test(value) || value !== value.trim();
|
|
826
|
+
var quote = (value) => `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
827
|
+
var serializeScalar = (value) => {
|
|
828
|
+
const serialized = value === null ? "null" : String(value);
|
|
829
|
+
return needsQuoting(serialized) ? quote(serialized) : serialized;
|
|
830
|
+
};
|
|
831
|
+
var serializeIsValue = (value) => value === null ? "null" : String(value);
|
|
832
|
+
var serialize = (operator, value) => {
|
|
833
|
+
if (operator === "in") {
|
|
834
|
+
const values = Array.isArray(value) ? value : [value];
|
|
835
|
+
if (values.length === 0) {
|
|
836
|
+
throw new Error("Realtime `in` filter requires at least one value.");
|
|
837
|
+
}
|
|
838
|
+
const items = Array.from(new Set(values)).map((v) => serializeScalar(v)).join(",");
|
|
839
|
+
return `in.(${items})`;
|
|
840
|
+
}
|
|
841
|
+
if (operator === "is") {
|
|
842
|
+
return `is.${serializeIsValue(value)}`;
|
|
843
|
+
}
|
|
844
|
+
return `${operator}.${serializeScalar(value)}`;
|
|
845
|
+
};
|
|
846
|
+
var RealtimePostgresFilterBuilder = class {
|
|
847
|
+
constructor() {
|
|
848
|
+
this.filters = [];
|
|
849
|
+
}
|
|
850
|
+
add(column, operator, value, negate = false) {
|
|
851
|
+
const prefix = negate ? "not." : "";
|
|
852
|
+
this.filters.push(`${column}=${prefix}${serialize(operator, value)}`);
|
|
853
|
+
return this;
|
|
854
|
+
}
|
|
855
|
+
/** Match rows where `column` equals `value` (`column=eq.value`). */
|
|
856
|
+
eq(column, value) {
|
|
857
|
+
return this.add(column, "eq", value);
|
|
858
|
+
}
|
|
859
|
+
/** Match rows where `column` does not equal `value` (`column=neq.value`). */
|
|
860
|
+
neq(column, value) {
|
|
861
|
+
return this.add(column, "neq", value);
|
|
862
|
+
}
|
|
863
|
+
/** Match rows where `column` is greater than `value` (`column=gt.value`). */
|
|
864
|
+
gt(column, value) {
|
|
865
|
+
return this.add(column, "gt", value);
|
|
866
|
+
}
|
|
867
|
+
/** Match rows where `column` is greater than or equal to `value` (`column=gte.value`). */
|
|
868
|
+
gte(column, value) {
|
|
869
|
+
return this.add(column, "gte", value);
|
|
870
|
+
}
|
|
871
|
+
/** Match rows where `column` is less than `value` (`column=lt.value`). */
|
|
872
|
+
lt(column, value) {
|
|
873
|
+
return this.add(column, "lt", value);
|
|
874
|
+
}
|
|
875
|
+
/** Match rows where `column` is less than or equal to `value` (`column=lte.value`). */
|
|
876
|
+
lte(column, value) {
|
|
877
|
+
return this.add(column, "lte", value);
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Match rows where `column` is one of `values` (`column=in.(a,b,c)`).
|
|
881
|
+
* Requires at least one value; duplicates are removed. An element containing a
|
|
882
|
+
* reserved character is double-quoted (`in.("a,b",c)`), so commas inside an
|
|
883
|
+
* element are preserved. `null` is intentionally not accepted (`IN (null)`
|
|
884
|
+
* never matches in SQL) — use `is`/`not('col','is',null)` for null checks.
|
|
885
|
+
*/
|
|
886
|
+
in(column, values) {
|
|
887
|
+
return this.add(column, "in", values);
|
|
888
|
+
}
|
|
889
|
+
/** Match rows where `column` matches the case-sensitive `pattern` (`column=like.pattern`). */
|
|
890
|
+
like(column, pattern) {
|
|
891
|
+
return this.add(column, "like", pattern);
|
|
892
|
+
}
|
|
893
|
+
/** Match rows where `column` matches the case-insensitive `pattern` (`column=ilike.pattern`). */
|
|
894
|
+
ilike(column, pattern) {
|
|
895
|
+
return this.add(column, "ilike", pattern);
|
|
896
|
+
}
|
|
897
|
+
/** Match rows where `column` matches the POSIX regex `pattern` (`column=match.pattern`). */
|
|
898
|
+
match(column, pattern) {
|
|
899
|
+
return this.add(column, "match", pattern);
|
|
900
|
+
}
|
|
901
|
+
/** Match rows where `column` matches the case-insensitive POSIX regex `pattern` (`column=imatch.pattern`). */
|
|
902
|
+
imatch(column, pattern) {
|
|
903
|
+
return this.add(column, "imatch", pattern);
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Match rows where `column` `IS` the given value (`column=is.null`).
|
|
907
|
+
* Accepts `null`, a boolean, or the keywords `'null' | 'true' | 'false' | 'unknown'`.
|
|
908
|
+
*/
|
|
909
|
+
is(column, value) {
|
|
910
|
+
return this.add(column, "is", value);
|
|
911
|
+
}
|
|
912
|
+
/** Match rows where `column` is distinct from `value` (`column=isdistinct.value`). NULL-safe inequality. */
|
|
913
|
+
isDistinct(column, value) {
|
|
914
|
+
return this.add(column, "isdistinct", value);
|
|
915
|
+
}
|
|
916
|
+
not(column, operator, value) {
|
|
917
|
+
return this.add(column, operator, value, true);
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Serialize all conditions into the comma-separated (AND) filter string.
|
|
921
|
+
*
|
|
922
|
+
* Conditions are joined by commas, which the server applies as `AND`. A scalar
|
|
923
|
+
* value (or single `in` element) that contains a reserved character — `,`,
|
|
924
|
+
* `(`, `)`, `"`, `\` — or surrounding whitespace is double-quoted and escaped
|
|
925
|
+
* the way PostgREST does, so commas inside a value are preserved rather than
|
|
926
|
+
* read as a condition boundary.
|
|
927
|
+
*/
|
|
928
|
+
build() {
|
|
929
|
+
return this.filters.join(",");
|
|
930
|
+
}
|
|
931
|
+
/** Alias for {@link build}; lets the builder be used wherever a string is expected. */
|
|
932
|
+
toString() {
|
|
933
|
+
return this.build();
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
// node_modules/@supabase/realtime-js/dist/module/RealtimeChannel.js
|
|
938
|
+
exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = void 0;
|
|
939
|
+
(function(REALTIME_POSTGRES_CHANGES_LISTEN_EVENT2) {
|
|
940
|
+
REALTIME_POSTGRES_CHANGES_LISTEN_EVENT2["ALL"] = "*";
|
|
941
|
+
REALTIME_POSTGRES_CHANGES_LISTEN_EVENT2["INSERT"] = "INSERT";
|
|
942
|
+
REALTIME_POSTGRES_CHANGES_LISTEN_EVENT2["UPDATE"] = "UPDATE";
|
|
943
|
+
REALTIME_POSTGRES_CHANGES_LISTEN_EVENT2["DELETE"] = "DELETE";
|
|
944
|
+
})(exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT || (exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = {}));
|
|
945
|
+
exports.REALTIME_LISTEN_TYPES = void 0;
|
|
946
|
+
(function(REALTIME_LISTEN_TYPES2) {
|
|
947
|
+
REALTIME_LISTEN_TYPES2["BROADCAST"] = "broadcast";
|
|
948
|
+
REALTIME_LISTEN_TYPES2["PRESENCE"] = "presence";
|
|
949
|
+
REALTIME_LISTEN_TYPES2["POSTGRES_CHANGES"] = "postgres_changes";
|
|
950
|
+
REALTIME_LISTEN_TYPES2["SYSTEM"] = "system";
|
|
951
|
+
})(exports.REALTIME_LISTEN_TYPES || (exports.REALTIME_LISTEN_TYPES = {}));
|
|
952
|
+
exports.REALTIME_SUBSCRIBE_STATES = void 0;
|
|
953
|
+
(function(REALTIME_SUBSCRIBE_STATES2) {
|
|
954
|
+
REALTIME_SUBSCRIBE_STATES2["SUBSCRIBED"] = "SUBSCRIBED";
|
|
955
|
+
REALTIME_SUBSCRIBE_STATES2["TIMED_OUT"] = "TIMED_OUT";
|
|
956
|
+
REALTIME_SUBSCRIBE_STATES2["CLOSED"] = "CLOSED";
|
|
957
|
+
REALTIME_SUBSCRIBE_STATES2["CHANNEL_ERROR"] = "CHANNEL_ERROR";
|
|
958
|
+
})(exports.REALTIME_SUBSCRIBE_STATES || (exports.REALTIME_SUBSCRIBE_STATES = {}));
|
|
959
|
+
var RealtimeChannel = class _RealtimeChannel {
|
|
960
|
+
get state() {
|
|
961
|
+
return this.channelAdapter.state;
|
|
962
|
+
}
|
|
963
|
+
set state(state) {
|
|
964
|
+
this.channelAdapter.state = state;
|
|
965
|
+
}
|
|
966
|
+
get joinedOnce() {
|
|
967
|
+
return this.channelAdapter.joinedOnce;
|
|
968
|
+
}
|
|
969
|
+
get timeout() {
|
|
970
|
+
return this.socket.timeout;
|
|
971
|
+
}
|
|
972
|
+
get joinPush() {
|
|
973
|
+
return this.channelAdapter.joinPush;
|
|
974
|
+
}
|
|
975
|
+
get rejoinTimer() {
|
|
976
|
+
return this.channelAdapter.rejoinTimer;
|
|
977
|
+
}
|
|
978
|
+
/**
|
|
979
|
+
* Creates a channel that can broadcast messages, sync presence, and listen to Postgres changes.
|
|
980
|
+
*
|
|
981
|
+
* The topic determines which realtime stream you are subscribing to. Config options let you
|
|
982
|
+
* enable acknowledgement for broadcasts, presence tracking, or private channels.
|
|
983
|
+
*
|
|
984
|
+
* @category Realtime
|
|
985
|
+
*
|
|
986
|
+
* @example Using supabase-js (recommended)
|
|
987
|
+
* ```ts
|
|
988
|
+
* import { createClient } from '@supabase/supabase-js'
|
|
989
|
+
*
|
|
990
|
+
* const supabase = createClient('https://xyzcompany.supabase.co', 'your-publishable-key')
|
|
991
|
+
* const channel = supabase.channel('room1')
|
|
992
|
+
* channel
|
|
993
|
+
* .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload))
|
|
994
|
+
* .subscribe()
|
|
995
|
+
* ```
|
|
996
|
+
*
|
|
997
|
+
* @example Standalone import for bundle-sensitive environments
|
|
998
|
+
* ```ts
|
|
999
|
+
* import RealtimeClient from '@supabase/realtime-js'
|
|
1000
|
+
*
|
|
1001
|
+
* const client = new RealtimeClient('https://xyzcompany.supabase.co/realtime/v1', {
|
|
1002
|
+
* params: { apikey: 'your-publishable-key' },
|
|
1003
|
+
* })
|
|
1004
|
+
* const channel = new RealtimeChannel('realtime:public:messages', { config: {} }, client)
|
|
1005
|
+
* ```
|
|
1006
|
+
*/
|
|
1007
|
+
constructor(topic, params = { config: {} }, socket) {
|
|
1008
|
+
var _a, _b;
|
|
1009
|
+
this.topic = topic;
|
|
1010
|
+
this.params = params;
|
|
1011
|
+
this.socket = socket;
|
|
1012
|
+
this.bindings = {};
|
|
1013
|
+
this.subTopic = topic.replace(/^realtime:/i, "");
|
|
1014
|
+
this.params.config = Object.assign({
|
|
1015
|
+
broadcast: { ack: false, self: false },
|
|
1016
|
+
presence: { key: "", enabled: false },
|
|
1017
|
+
private: false
|
|
1018
|
+
}, params.config);
|
|
1019
|
+
this.channelAdapter = new ChannelAdapter(this.socket.socketAdapter, topic, this.params);
|
|
1020
|
+
this.presence = new RealtimePresence(this);
|
|
1021
|
+
this._onClose(() => {
|
|
1022
|
+
this.socket._remove(this);
|
|
1023
|
+
});
|
|
1024
|
+
this._updateFilterTransform();
|
|
1025
|
+
this.broadcastEndpointURL = httpEndpointURL(this.socket.socketAdapter.endPointURL());
|
|
1026
|
+
this.private = this.params.config.private || false;
|
|
1027
|
+
if (!this.private && ((_b = (_a = this.params.config) === null || _a === void 0 ? void 0 : _a.broadcast) === null || _b === void 0 ? void 0 : _b.replay)) {
|
|
1028
|
+
throw new Error(`tried to use replay on public channel '${this.topic}'. It must be a private channel.`);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Subscribe registers your client with the server.
|
|
1033
|
+
*
|
|
1034
|
+
* The optional `callback` receives a `status` and, on failure, an `err` argument.
|
|
1035
|
+
* Log the full `err` so its `cause`, `name`, and any structured fields aren't hidden
|
|
1036
|
+
* behind `err.message`.
|
|
1037
|
+
*
|
|
1038
|
+
* @category Realtime
|
|
1039
|
+
*
|
|
1040
|
+
* @example Handling errors
|
|
1041
|
+
* ```js
|
|
1042
|
+
* supabase.channel('room1').subscribe((status, err) => {
|
|
1043
|
+
* if (status === 'CHANNEL_ERROR' || status === 'TIMED_OUT') {
|
|
1044
|
+
* // Log the full error: its `cause` often holds the underlying reason.
|
|
1045
|
+
* console.error(status, err)
|
|
1046
|
+
* }
|
|
1047
|
+
* })
|
|
1048
|
+
* ```
|
|
1049
|
+
*/
|
|
1050
|
+
subscribe(callback, timeout = this.timeout) {
|
|
1051
|
+
var _a, _b, _c, _d;
|
|
1052
|
+
if (!this.socket.isConnected()) {
|
|
1053
|
+
this.socket.connect();
|
|
1054
|
+
}
|
|
1055
|
+
if (this.channelAdapter.isClosed()) {
|
|
1056
|
+
const { config: { broadcast, presence, private: isPrivate, postgres_changes_options } } = this.params;
|
|
1057
|
+
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 : [];
|
|
1058
|
+
const presence_enabled = !!this.bindings[exports.REALTIME_LISTEN_TYPES.PRESENCE] && this.bindings[exports.REALTIME_LISTEN_TYPES.PRESENCE].length > 0 || ((_c = this.params.config.presence) === null || _c === void 0 ? void 0 : _c.enabled) === true;
|
|
1059
|
+
const accessTokenPayload = {};
|
|
1060
|
+
const config = Object.assign({ broadcast, presence: Object.assign(Object.assign({}, presence), { enabled: presence_enabled }), postgres_changes, private: isPrivate }, postgres_changes_options ? { postgres_changes_options } : {});
|
|
1061
|
+
if (this.socket.accessTokenValue) {
|
|
1062
|
+
accessTokenPayload.access_token = this.socket.accessTokenValue;
|
|
1063
|
+
}
|
|
1064
|
+
this._onError((reason) => {
|
|
1065
|
+
callback === null || callback === void 0 ? void 0 : callback(exports.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, normalizeChannelError(reason));
|
|
1066
|
+
});
|
|
1067
|
+
this._onClose(() => callback === null || callback === void 0 ? void 0 : callback(exports.REALTIME_SUBSCRIBE_STATES.CLOSED));
|
|
1068
|
+
this.updateJoinPayload(Object.assign({ config }, accessTokenPayload));
|
|
1069
|
+
this._updateFilterMessage();
|
|
1070
|
+
const joinTimeout = (postgres_changes_options === null || postgres_changes_options === void 0 ? void 0 : postgres_changes_options.wait) && postgres_changes.length > 0 ? Math.max(timeout, ((_d = postgres_changes_options.timeout) !== null && _d !== void 0 ? _d : DEFAULT_POSTGRES_CHANGES_WAIT_TIMEOUT) + POSTGRES_CHANGES_WAIT_ERROR_GRACE) : timeout;
|
|
1071
|
+
this.channelAdapter.subscribe(joinTimeout).receive("ok", async ({ postgres_changes: postgres_changes2 }) => {
|
|
1072
|
+
if (!this.socket._isManualToken()) {
|
|
1073
|
+
this.socket.setAuth();
|
|
1074
|
+
}
|
|
1075
|
+
if (postgres_changes2 === void 0) {
|
|
1076
|
+
callback === null || callback === void 0 ? void 0 : callback(exports.REALTIME_SUBSCRIBE_STATES.SUBSCRIBED);
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
this._updatePostgresBindings(postgres_changes2, callback);
|
|
1080
|
+
}).receive("error", (error) => {
|
|
1081
|
+
this.state = CHANNEL_STATES.errored;
|
|
1082
|
+
const message = Object.values(error).join(", ") || "error";
|
|
1083
|
+
callback === null || callback === void 0 ? void 0 : callback(exports.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error(message, { cause: error }));
|
|
1084
|
+
}).receive("timeout", () => {
|
|
1085
|
+
callback === null || callback === void 0 ? void 0 : callback(exports.REALTIME_SUBSCRIBE_STATES.TIMED_OUT);
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
return this;
|
|
1089
|
+
}
|
|
1090
|
+
_updatePostgresBindings(postgres_changes, callback) {
|
|
1091
|
+
var _a;
|
|
1092
|
+
const clientPostgresBindings = this.bindings.postgres_changes;
|
|
1093
|
+
const bindingsLen = (_a = clientPostgresBindings === null || clientPostgresBindings === void 0 ? void 0 : clientPostgresBindings.length) !== null && _a !== void 0 ? _a : 0;
|
|
1094
|
+
const newPostgresBindings = [];
|
|
1095
|
+
for (let i = 0; i < bindingsLen; i++) {
|
|
1096
|
+
const clientPostgresBinding = clientPostgresBindings[i];
|
|
1097
|
+
const { filter: { event, schema, table, filter } } = clientPostgresBinding;
|
|
1098
|
+
const serverPostgresFilter = postgres_changes && postgres_changes[i];
|
|
1099
|
+
if (serverPostgresFilter && serverPostgresFilter.event === event && _RealtimeChannel.isFilterValueEqual(serverPostgresFilter.schema, schema) && _RealtimeChannel.isFilterValueEqual(serverPostgresFilter.table, table) && _RealtimeChannel.isFilterValueEqual(serverPostgresFilter.filter, filter)) {
|
|
1100
|
+
newPostgresBindings.push(Object.assign(Object.assign({}, clientPostgresBinding), { id: serverPostgresFilter.id }));
|
|
1101
|
+
} else {
|
|
1102
|
+
this.unsubscribe();
|
|
1103
|
+
this.state = CHANNEL_STATES.errored;
|
|
1104
|
+
callback === null || callback === void 0 ? void 0 : callback(exports.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error("mismatch between server and client bindings for postgres changes"));
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
this.bindings.postgres_changes = newPostgresBindings;
|
|
1109
|
+
if (this.state != CHANNEL_STATES.errored && callback) {
|
|
1110
|
+
callback(exports.REALTIME_SUBSCRIBE_STATES.SUBSCRIBED);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Returns the current presence state for this channel.
|
|
1115
|
+
*
|
|
1116
|
+
* The shape is a map keyed by presence key (for example a user id) where each entry contains the
|
|
1117
|
+
* tracked metadata for that user.
|
|
1118
|
+
*
|
|
1119
|
+
* @category Realtime
|
|
1120
|
+
*/
|
|
1121
|
+
presenceState() {
|
|
1122
|
+
return this.presence.state;
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* Sends the supplied payload to the presence tracker so other subscribers can see that this
|
|
1126
|
+
* client is online. Use `untrack` to stop broadcasting presence for the same key.
|
|
1127
|
+
*
|
|
1128
|
+
* Tracking makes this client visible to other subscribers immediately, regardless of this
|
|
1129
|
+
* channel's `config.presence.enabled` setting or whether it has a `presence` listener — that
|
|
1130
|
+
* flag only affects whether *this* client receives presence updates from others (and, on
|
|
1131
|
+
* RLS-protected channels, whether it's authorized to do so).
|
|
1132
|
+
*
|
|
1133
|
+
* @category Realtime
|
|
1134
|
+
*/
|
|
1135
|
+
async track(payload, opts = {}) {
|
|
1136
|
+
return await this.send({
|
|
1137
|
+
type: "presence",
|
|
1138
|
+
event: "track",
|
|
1139
|
+
payload
|
|
1140
|
+
}, opts);
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Removes the current presence state for this client.
|
|
1144
|
+
*
|
|
1145
|
+
* @category Realtime
|
|
1146
|
+
*/
|
|
1147
|
+
async untrack(opts = {}) {
|
|
1148
|
+
return await this.send({
|
|
1149
|
+
type: "presence",
|
|
1150
|
+
event: "untrack"
|
|
1151
|
+
}, opts);
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Listen to realtime events on this channel.
|
|
1155
|
+
* @category Realtime
|
|
1156
|
+
*
|
|
1157
|
+
* @remarks
|
|
1158
|
+
* - By default, Broadcast and Presence are enabled for all projects.
|
|
1159
|
+
* - By default, listening to database changes is disabled for new projects due to database performance and security concerns. You can turn it on by managing Realtime's [replication](/docs/guides/api#realtime-api-overview).
|
|
1160
|
+
* - You can receive the "previous" data for updates and deletes by setting the table's `REPLICA IDENTITY` to `FULL` (e.g., `ALTER TABLE your_table REPLICA IDENTITY FULL;`).
|
|
1161
|
+
* - Row level security is not applied to delete statements. When RLS is enabled and replica identity is set to full, only the primary key is sent to clients.
|
|
1162
|
+
*
|
|
1163
|
+
* @example Listen to broadcast messages
|
|
1164
|
+
* ```js
|
|
1165
|
+
* const channel = supabase.channel("room1")
|
|
1166
|
+
*
|
|
1167
|
+
* channel.on("broadcast", { event: "cursor-pos" }, (payload) => {
|
|
1168
|
+
* console.log("Cursor position received!", payload);
|
|
1169
|
+
* }).subscribe((status) => {
|
|
1170
|
+
* if (status === "SUBSCRIBED") {
|
|
1171
|
+
* channel.send({
|
|
1172
|
+
* type: "broadcast",
|
|
1173
|
+
* event: "cursor-pos",
|
|
1174
|
+
* payload: { x: Math.random(), y: Math.random() },
|
|
1175
|
+
* });
|
|
1176
|
+
* }
|
|
1177
|
+
* });
|
|
1178
|
+
* ```
|
|
1179
|
+
*
|
|
1180
|
+
* @example Listen to presence sync
|
|
1181
|
+
* ```js
|
|
1182
|
+
* const channel = supabase.channel('room1')
|
|
1183
|
+
* channel
|
|
1184
|
+
* .on('presence', { event: 'sync' }, () => {
|
|
1185
|
+
* console.log('Synced presence state: ', channel.presenceState())
|
|
1186
|
+
* })
|
|
1187
|
+
* .subscribe(async (status) => {
|
|
1188
|
+
* if (status === 'SUBSCRIBED') {
|
|
1189
|
+
* await channel.track({ online_at: new Date().toISOString() })
|
|
1190
|
+
* }
|
|
1191
|
+
* })
|
|
1192
|
+
* ```
|
|
1193
|
+
*
|
|
1194
|
+
* @example Listen to presence join
|
|
1195
|
+
* ```js
|
|
1196
|
+
* const channel = supabase.channel('room1')
|
|
1197
|
+
* channel
|
|
1198
|
+
* .on('presence', { event: 'join' }, ({ newPresences }) => {
|
|
1199
|
+
* console.log('Newly joined presences: ', newPresences)
|
|
1200
|
+
* })
|
|
1201
|
+
* .subscribe(async (status) => {
|
|
1202
|
+
* if (status === 'SUBSCRIBED') {
|
|
1203
|
+
* await channel.track({ online_at: new Date().toISOString() })
|
|
1204
|
+
* }
|
|
1205
|
+
* })
|
|
1206
|
+
* ```
|
|
1207
|
+
*
|
|
1208
|
+
* @example Listen to presence leave
|
|
1209
|
+
* ```js
|
|
1210
|
+
* const channel = supabase.channel('room1')
|
|
1211
|
+
* channel
|
|
1212
|
+
* .on('presence', { event: 'leave' }, ({ leftPresences }) => {
|
|
1213
|
+
* console.log('Newly left presences: ', leftPresences)
|
|
1214
|
+
* })
|
|
1215
|
+
* .subscribe(async (status) => {
|
|
1216
|
+
* if (status === 'SUBSCRIBED') {
|
|
1217
|
+
* await channel.track({ online_at: new Date().toISOString() })
|
|
1218
|
+
* await channel.untrack()
|
|
1219
|
+
* }
|
|
1220
|
+
* })
|
|
1221
|
+
* ```
|
|
1222
|
+
*
|
|
1223
|
+
* Registering the same `postgres_changes` filter more than once on a channel is a no-op: the
|
|
1224
|
+
* duplicate is ignored and an error is logged, since the server only ever creates one
|
|
1225
|
+
* subscription per distinct filter.
|
|
1226
|
+
*
|
|
1227
|
+
* @example Listen to all database changes
|
|
1228
|
+
* ```js
|
|
1229
|
+
* supabase
|
|
1230
|
+
* .channel('room1')
|
|
1231
|
+
* .on('postgres_changes', { event: '*', schema: '*' }, payload => {
|
|
1232
|
+
* console.log('Change received!', payload)
|
|
1233
|
+
* })
|
|
1234
|
+
* .subscribe()
|
|
1235
|
+
* ```
|
|
1236
|
+
*
|
|
1237
|
+
* @example Listen to a specific table
|
|
1238
|
+
* ```js
|
|
1239
|
+
* supabase
|
|
1240
|
+
* .channel('room1')
|
|
1241
|
+
* .on('postgres_changes', { event: '*', schema: 'public', table: 'countries' }, payload => {
|
|
1242
|
+
* console.log('Change received!', payload)
|
|
1243
|
+
* })
|
|
1244
|
+
* .subscribe()
|
|
1245
|
+
* ```
|
|
1246
|
+
*
|
|
1247
|
+
* @example Listen to inserts
|
|
1248
|
+
* ```js
|
|
1249
|
+
* supabase
|
|
1250
|
+
* .channel('room1')
|
|
1251
|
+
* .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'countries' }, payload => {
|
|
1252
|
+
* console.log('Change received!', payload)
|
|
1253
|
+
* })
|
|
1254
|
+
* .subscribe()
|
|
1255
|
+
* ```
|
|
1256
|
+
*
|
|
1257
|
+
* @exampleDescription Listen to updates
|
|
1258
|
+
* By default, Supabase will send only the updated record. If you want to receive the previous values as well you can
|
|
1259
|
+
* enable full replication for the table you are listening to:
|
|
1260
|
+
*
|
|
1261
|
+
* ```sql
|
|
1262
|
+
* alter table "your_table" replica identity full;
|
|
1263
|
+
* ```
|
|
1264
|
+
*
|
|
1265
|
+
* @example Listen to updates
|
|
1266
|
+
* ```js
|
|
1267
|
+
* supabase
|
|
1268
|
+
* .channel('room1')
|
|
1269
|
+
* .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'countries' }, payload => {
|
|
1270
|
+
* console.log('Change received!', payload)
|
|
1271
|
+
* })
|
|
1272
|
+
* .subscribe()
|
|
1273
|
+
* ```
|
|
1274
|
+
*
|
|
1275
|
+
* @exampleDescription Listen to deletes
|
|
1276
|
+
* By default, Supabase does not send deleted records. If you want to receive the deleted record you can
|
|
1277
|
+
* enable full replication for the table you are listening to:
|
|
1278
|
+
*
|
|
1279
|
+
* ```sql
|
|
1280
|
+
* alter table "your_table" replica identity full;
|
|
1281
|
+
* ```
|
|
1282
|
+
*
|
|
1283
|
+
* @example Listen to deletes
|
|
1284
|
+
* ```js
|
|
1285
|
+
* supabase
|
|
1286
|
+
* .channel('room1')
|
|
1287
|
+
* .on('postgres_changes', { event: 'DELETE', schema: 'public', table: 'countries' }, payload => {
|
|
1288
|
+
* console.log('Change received!', payload)
|
|
1289
|
+
* })
|
|
1290
|
+
* .subscribe()
|
|
1291
|
+
* ```
|
|
1292
|
+
*
|
|
1293
|
+
* @exampleDescription Listen to multiple events
|
|
1294
|
+
* You can chain listeners if you want to listen to multiple events for each table.
|
|
1295
|
+
*
|
|
1296
|
+
* @example Listen to multiple events
|
|
1297
|
+
* ```js
|
|
1298
|
+
* supabase
|
|
1299
|
+
* .channel('room1')
|
|
1300
|
+
* .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'countries' }, handleRecordInserted)
|
|
1301
|
+
* .on('postgres_changes', { event: 'DELETE', schema: 'public', table: 'countries' }, handleRecordDeleted)
|
|
1302
|
+
* .subscribe()
|
|
1303
|
+
* ```
|
|
1304
|
+
*
|
|
1305
|
+
* @exampleDescription Listen to row level changes
|
|
1306
|
+
* You can listen to individual rows using the format `{table}:{col}=eq.{val}` - where `{col}` is the column name, and `{val}` is the value which you want to match.
|
|
1307
|
+
*
|
|
1308
|
+
* @example Listen to row level changes
|
|
1309
|
+
* ```js
|
|
1310
|
+
* supabase
|
|
1311
|
+
* .channel('room1')
|
|
1312
|
+
* .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'countries', filter: 'id=eq.200' }, handleRecordUpdated)
|
|
1313
|
+
* .subscribe()
|
|
1314
|
+
* ```
|
|
1315
|
+
*/
|
|
1316
|
+
on(type, filter, callback) {
|
|
1317
|
+
const stateCheck = this.channelAdapter.isJoined() || this.channelAdapter.isJoining();
|
|
1318
|
+
const typeCheck = type === exports.REALTIME_LISTEN_TYPES.PRESENCE || type === exports.REALTIME_LISTEN_TYPES.POSTGRES_CHANGES;
|
|
1319
|
+
if (stateCheck && typeCheck) {
|
|
1320
|
+
this.socket.log("channel", `cannot add \`${type}\` callbacks for ${this.topic} after \`subscribe()\`.`);
|
|
1321
|
+
throw new Error(`cannot add \`${type}\` callbacks for ${this.topic} after \`subscribe()\`.`);
|
|
1322
|
+
}
|
|
1323
|
+
return this._on(type, filter, callback);
|
|
1324
|
+
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Sends a broadcast message explicitly via REST API.
|
|
1327
|
+
*
|
|
1328
|
+
* This method always uses the REST API endpoint regardless of WebSocket connection state.
|
|
1329
|
+
* Useful when you want to guarantee REST delivery or when gradually migrating from implicit REST fallback.
|
|
1330
|
+
*
|
|
1331
|
+
* Payloads that are `ArrayBuffer` or `ArrayBufferView` (e.g. `Uint8Array`) are sent as
|
|
1332
|
+
* `application/octet-stream`; all other payloads are JSON-encoded.
|
|
1333
|
+
*
|
|
1334
|
+
* @param event The name of the broadcast event
|
|
1335
|
+
* @param payload Payload to be sent (required)
|
|
1336
|
+
* @param opts Options including timeout
|
|
1337
|
+
* @returns Promise resolving to object with success status, and error details if failed
|
|
1338
|
+
*
|
|
1339
|
+
* @category Realtime
|
|
1340
|
+
*/
|
|
1341
|
+
async httpSend(event, payload, opts = {}) {
|
|
1342
|
+
var _a;
|
|
1343
|
+
if (payload === void 0 || payload === null) {
|
|
1344
|
+
return Promise.reject(new Error("Payload is required for httpSend()"));
|
|
1345
|
+
}
|
|
1346
|
+
const isBinary = payload instanceof ArrayBuffer || ArrayBuffer.isView(payload);
|
|
1347
|
+
const headers = {
|
|
1348
|
+
apikey: this.socket.apiKey ? this.socket.apiKey : "",
|
|
1349
|
+
"Content-Type": isBinary ? "application/octet-stream" : "application/json"
|
|
1350
|
+
};
|
|
1351
|
+
if (this.socket.accessTokenValue) {
|
|
1352
|
+
headers["Authorization"] = `Bearer ${this.socket.accessTokenValue}`;
|
|
1353
|
+
}
|
|
1354
|
+
const url = new URL(this.broadcastEndpointURL);
|
|
1355
|
+
url.pathname += `/${encodeURIComponent(this.subTopic)}/events/${encodeURIComponent(event)}`;
|
|
1356
|
+
if (this.private) {
|
|
1357
|
+
url.searchParams.set("private", "true");
|
|
1358
|
+
}
|
|
1359
|
+
const options = {
|
|
1360
|
+
method: "POST",
|
|
1361
|
+
headers,
|
|
1362
|
+
body: isBinary ? payload : JSON.stringify(payload)
|
|
1363
|
+
};
|
|
1364
|
+
const response = await this._fetchWithTimeout(url.toString(), options, (_a = opts.timeout) !== null && _a !== void 0 ? _a : this.timeout);
|
|
1365
|
+
if (response.status === 202) {
|
|
1366
|
+
return { success: true };
|
|
1367
|
+
}
|
|
1368
|
+
if (response.status === 404) {
|
|
1369
|
+
return Promise.reject(new Error("httpSend() requires Realtime server v2.97.0 or newer; the endpoint returned 404. Update your Supabase CLI to a recent version, or upgrade the Realtime server in your self-hosted setup. See https://github.com/supabase/supabase-js/blob/master/packages/core/realtime-js/migrations/httpsend-server-version.md"));
|
|
1370
|
+
}
|
|
1371
|
+
let errorMessage = response.statusText;
|
|
1372
|
+
try {
|
|
1373
|
+
const errorBody = await response.json();
|
|
1374
|
+
errorMessage = errorBody.error || errorBody.message || errorMessage;
|
|
1375
|
+
} catch (_b) {
|
|
1376
|
+
}
|
|
1377
|
+
return Promise.reject(new Error(errorMessage));
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Sends a message into the channel.
|
|
1381
|
+
*
|
|
1382
|
+
* @param args Arguments to send to channel
|
|
1383
|
+
* @param args.type The type of event to send
|
|
1384
|
+
* @param args.event The name of the event being sent
|
|
1385
|
+
* @param args.payload Payload to be sent
|
|
1386
|
+
* @param opts Options to be used during the send process
|
|
1387
|
+
*
|
|
1388
|
+
* @category Realtime
|
|
1389
|
+
*
|
|
1390
|
+
* @remarks
|
|
1391
|
+
* - When using REST you don't need to subscribe to the channel
|
|
1392
|
+
* - REST calls are only available from 2.37.0 onwards
|
|
1393
|
+
* - If you create a channel only to send a REST broadcast, remove it from
|
|
1394
|
+
* the client when the send completes
|
|
1395
|
+
*
|
|
1396
|
+
* @example Send a message via websocket
|
|
1397
|
+
* ```js
|
|
1398
|
+
* const channel = supabase.channel('room1')
|
|
1399
|
+
*
|
|
1400
|
+
* channel.subscribe((status) => {
|
|
1401
|
+
* if (status === 'SUBSCRIBED') {
|
|
1402
|
+
* channel.send({
|
|
1403
|
+
* type: 'broadcast',
|
|
1404
|
+
* event: 'cursor-pos',
|
|
1405
|
+
* payload: { x: Math.random(), y: Math.random() },
|
|
1406
|
+
* })
|
|
1407
|
+
* }
|
|
1408
|
+
* })
|
|
1409
|
+
* ```
|
|
1410
|
+
*
|
|
1411
|
+
* @exampleResponse Send a message via websocket
|
|
1412
|
+
* ```js
|
|
1413
|
+
* ok | timed out | error
|
|
1414
|
+
* ```
|
|
1415
|
+
*
|
|
1416
|
+
* @example Send a message via REST
|
|
1417
|
+
* ```js
|
|
1418
|
+
* const channel = supabase.channel('room1')
|
|
1419
|
+
*
|
|
1420
|
+
* try {
|
|
1421
|
+
* await channel.httpSend('cursor-pos', { x: Math.random(), y: Math.random() })
|
|
1422
|
+
* } finally {
|
|
1423
|
+
* await supabase.removeChannel(channel)
|
|
1424
|
+
* }
|
|
1425
|
+
* ```
|
|
1426
|
+
*/
|
|
1427
|
+
async send(args, opts = {}) {
|
|
1428
|
+
var _a, _b;
|
|
1429
|
+
if (!this.channelAdapter.canPush() && args.type === "broadcast") {
|
|
1430
|
+
const fallbackWarning = "Realtime send() is automatically falling back to REST API. This behavior will be deprecated in the future. Please use httpSend() explicitly for REST delivery.";
|
|
1431
|
+
if (this.socket.hasLogger()) {
|
|
1432
|
+
this.socket.log("channel", fallbackWarning);
|
|
1433
|
+
} else {
|
|
1434
|
+
console.warn(fallbackWarning);
|
|
1435
|
+
}
|
|
1436
|
+
const { event, payload: endpoint_payload } = args;
|
|
1437
|
+
const headers = {
|
|
1438
|
+
apikey: this.socket.apiKey ? this.socket.apiKey : "",
|
|
1439
|
+
"Content-Type": "application/json"
|
|
1440
|
+
};
|
|
1441
|
+
if (this.socket.accessTokenValue) {
|
|
1442
|
+
headers["Authorization"] = `Bearer ${this.socket.accessTokenValue}`;
|
|
1443
|
+
}
|
|
1444
|
+
const options = {
|
|
1445
|
+
method: "POST",
|
|
1446
|
+
headers,
|
|
1447
|
+
body: JSON.stringify({
|
|
1448
|
+
messages: [
|
|
1449
|
+
{
|
|
1450
|
+
topic: this.subTopic,
|
|
1451
|
+
event,
|
|
1452
|
+
payload: endpoint_payload,
|
|
1453
|
+
private: this.private
|
|
1454
|
+
}
|
|
1455
|
+
]
|
|
1456
|
+
})
|
|
1457
|
+
};
|
|
1458
|
+
try {
|
|
1459
|
+
const response = await this._fetchWithTimeout(this.broadcastEndpointURL, options, (_a = opts.timeout) !== null && _a !== void 0 ? _a : this.timeout);
|
|
1460
|
+
await ((_b = response.body) === null || _b === void 0 ? void 0 : _b.cancel());
|
|
1461
|
+
return response.ok ? "ok" : "error";
|
|
1462
|
+
} catch (error) {
|
|
1463
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
1464
|
+
return "timed out";
|
|
1465
|
+
} else {
|
|
1466
|
+
return "error";
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
} else {
|
|
1470
|
+
return new Promise((resolve) => {
|
|
1471
|
+
var _a2, _b2, _c;
|
|
1472
|
+
const push = this.channelAdapter.push(args.type, args, opts.timeout || this.timeout);
|
|
1473
|
+
if (args.type === "broadcast" && !((_c = (_b2 = (_a2 = this.params) === null || _a2 === void 0 ? void 0 : _a2.config) === null || _b2 === void 0 ? void 0 : _b2.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) {
|
|
1474
|
+
resolve("ok");
|
|
1475
|
+
}
|
|
1476
|
+
push.receive("ok", () => resolve("ok"));
|
|
1477
|
+
push.receive("error", () => resolve("error"));
|
|
1478
|
+
push.receive("timeout", () => resolve("timed out"));
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Updates the payload that will be sent the next time the channel joins (reconnects).
|
|
1484
|
+
* Useful for rotating access tokens or updating config without re-creating the channel.
|
|
1485
|
+
*
|
|
1486
|
+
* @category Realtime
|
|
1487
|
+
*/
|
|
1488
|
+
updateJoinPayload(payload) {
|
|
1489
|
+
this.channelAdapter.updateJoinPayload(payload);
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Leaves the channel.
|
|
1493
|
+
*
|
|
1494
|
+
* Unsubscribes from server events, and instructs channel to terminate on server.
|
|
1495
|
+
* Triggers onClose() hooks.
|
|
1496
|
+
*
|
|
1497
|
+
* To receive leave acknowledgements, use the a `receive` hook to bind to the server ack, ie:
|
|
1498
|
+
* channel.unsubscribe().receive("ok", () => alert("left!") )
|
|
1499
|
+
*
|
|
1500
|
+
* @category Realtime
|
|
1501
|
+
*/
|
|
1502
|
+
async unsubscribe(timeout = this.timeout) {
|
|
1503
|
+
return new Promise((resolve) => {
|
|
1504
|
+
this.channelAdapter.unsubscribe(timeout).receive("ok", () => resolve("ok")).receive("timeout", () => resolve("timed out")).receive("error", () => resolve("error"));
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Destroys and stops related timers.
|
|
1509
|
+
*
|
|
1510
|
+
* @category Realtime
|
|
1511
|
+
*/
|
|
1512
|
+
teardown() {
|
|
1513
|
+
this.channelAdapter.teardown();
|
|
1514
|
+
}
|
|
1515
|
+
/** @internal */
|
|
1516
|
+
async _fetchWithTimeout(url, options, timeout) {
|
|
1517
|
+
const controller = new AbortController();
|
|
1518
|
+
const id = setTimeout(() => controller.abort(), timeout);
|
|
1519
|
+
const response = await this.socket.fetch(url, Object.assign(Object.assign({}, options), { signal: controller.signal }));
|
|
1520
|
+
clearTimeout(id);
|
|
1521
|
+
return response;
|
|
1522
|
+
}
|
|
1523
|
+
/** @internal */
|
|
1524
|
+
_on(type, filter, callback) {
|
|
1525
|
+
var _a;
|
|
1526
|
+
const typeLower = type.toLocaleLowerCase();
|
|
1527
|
+
const filterValue = filter === null || filter === void 0 ? void 0 : filter.filter;
|
|
1528
|
+
if (filterValue instanceof RealtimePostgresFilterBuilder || typeof filterValue === "object" && filterValue !== null && typeof filterValue.build === "function") {
|
|
1529
|
+
filter = Object.assign(Object.assign({}, filter), { filter: filterValue.build() });
|
|
1530
|
+
}
|
|
1531
|
+
if (typeLower === exports.REALTIME_LISTEN_TYPES.POSTGRES_CHANGES) {
|
|
1532
|
+
const duplicate = (_a = this.bindings[typeLower]) === null || _a === void 0 ? void 0 : _a.find((bind) => _RealtimeChannel.isSamePostgresFilter(bind.filter, filter));
|
|
1533
|
+
if (duplicate) {
|
|
1534
|
+
this.socket.log("error", `duplicate \`postgres_changes\` binding for ${this.topic} ignored`, filter);
|
|
1535
|
+
return this;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
const ref = this.channelAdapter.on(type, callback);
|
|
1539
|
+
const binding = {
|
|
1540
|
+
type: typeLower,
|
|
1541
|
+
filter,
|
|
1542
|
+
callback,
|
|
1543
|
+
ref
|
|
1544
|
+
};
|
|
1545
|
+
if (this.bindings[typeLower]) {
|
|
1546
|
+
this.bindings[typeLower].push(binding);
|
|
1547
|
+
} else {
|
|
1548
|
+
this.bindings[typeLower] = [binding];
|
|
1549
|
+
}
|
|
1550
|
+
this._updateFilterMessage();
|
|
1551
|
+
return this;
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Registers a callback that will be executed when the channel closes.
|
|
1555
|
+
*
|
|
1556
|
+
* @internal
|
|
1557
|
+
*/
|
|
1558
|
+
_onClose(callback) {
|
|
1559
|
+
this.channelAdapter.onClose(callback);
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* Registers a callback that will be executed when the channel encounteres an error.
|
|
1563
|
+
*
|
|
1564
|
+
* @internal
|
|
1565
|
+
*/
|
|
1566
|
+
_onError(callback) {
|
|
1567
|
+
this.channelAdapter.onError(callback);
|
|
1568
|
+
}
|
|
1569
|
+
/** @internal */
|
|
1570
|
+
_updateFilterMessage() {
|
|
1571
|
+
this.channelAdapter.updateFilterBindings((binding, payload, ref) => {
|
|
1572
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1573
|
+
const typeLower = binding.event.toLocaleLowerCase();
|
|
1574
|
+
if (this._notThisChannelEvent(typeLower, ref)) {
|
|
1575
|
+
return false;
|
|
1576
|
+
}
|
|
1577
|
+
const bind = (_a = this.bindings[typeLower]) === null || _a === void 0 ? void 0 : _a.find((bind2) => bind2.ref === binding.ref);
|
|
1578
|
+
if (!bind) {
|
|
1579
|
+
return true;
|
|
1580
|
+
}
|
|
1581
|
+
if (["broadcast", "presence", "postgres_changes"].includes(typeLower)) {
|
|
1582
|
+
if ("id" in bind) {
|
|
1583
|
+
const bindId = bind.id;
|
|
1584
|
+
const bindEvent = (_b = bind.filter) === null || _b === void 0 ? void 0 : _b.event;
|
|
1585
|
+
return bindId && ((_c = payload.ids) === null || _c === void 0 ? void 0 : _c.includes(bindId)) && (bindEvent === "*" || (bindEvent === null || bindEvent === void 0 ? void 0 : bindEvent.toLocaleLowerCase()) === ((_d = payload.data) === null || _d === void 0 ? void 0 : _d.type.toLocaleLowerCase()));
|
|
1586
|
+
} else {
|
|
1587
|
+
const bindEvent = (_f = (_e = bind === null || bind === void 0 ? void 0 : bind.filter) === null || _e === void 0 ? void 0 : _e.event) === null || _f === void 0 ? void 0 : _f.toLocaleLowerCase();
|
|
1588
|
+
return bindEvent === "*" || bindEvent === ((_g = payload === null || payload === void 0 ? void 0 : payload.event) === null || _g === void 0 ? void 0 : _g.toLocaleLowerCase());
|
|
1589
|
+
}
|
|
1590
|
+
} else {
|
|
1591
|
+
return bind.type.toLocaleLowerCase() === typeLower;
|
|
1592
|
+
}
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
/** @internal */
|
|
1596
|
+
_notThisChannelEvent(event, ref) {
|
|
1597
|
+
const { close, error, leave, join } = CHANNEL_EVENTS;
|
|
1598
|
+
const events = [close, error, leave, join];
|
|
1599
|
+
return ref && events.includes(event) && ref !== this.joinPush.ref;
|
|
1600
|
+
}
|
|
1601
|
+
/** @internal */
|
|
1602
|
+
_updateFilterTransform() {
|
|
1603
|
+
this.channelAdapter.updatePayloadTransform((event, payload, ref) => {
|
|
1604
|
+
if (typeof payload === "object" && "ids" in payload) {
|
|
1605
|
+
const postgresChanges = payload.data;
|
|
1606
|
+
const { schema, table, commit_timestamp, type, errors } = postgresChanges;
|
|
1607
|
+
const enrichedPayload = {
|
|
1608
|
+
schema,
|
|
1609
|
+
table,
|
|
1610
|
+
commit_timestamp,
|
|
1611
|
+
eventType: type,
|
|
1612
|
+
new: {},
|
|
1613
|
+
old: {},
|
|
1614
|
+
errors
|
|
1615
|
+
};
|
|
1616
|
+
return Object.assign(Object.assign({}, enrichedPayload), this._getPayloadRecords(postgresChanges));
|
|
1617
|
+
}
|
|
1618
|
+
return payload;
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
copyBindings(other) {
|
|
1622
|
+
if (this.joinedOnce) {
|
|
1623
|
+
throw new Error("cannot copy bindings into joined channel");
|
|
1624
|
+
}
|
|
1625
|
+
for (const kind in other.bindings) {
|
|
1626
|
+
for (const binding of other.bindings[kind]) {
|
|
1627
|
+
this._on(binding.type, binding.filter, binding.callback);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Compares two optional filter values for equality.
|
|
1633
|
+
* Treats undefined, null, and empty string as equivalent empty values.
|
|
1634
|
+
* @internal
|
|
1635
|
+
*/
|
|
1636
|
+
static isFilterValueEqual(serverValue, clientValue) {
|
|
1637
|
+
const normalizedServer = serverValue !== null && serverValue !== void 0 ? serverValue : void 0;
|
|
1638
|
+
const normalizedClient = clientValue !== null && clientValue !== void 0 ? clientValue : void 0;
|
|
1639
|
+
return normalizedServer === normalizedClient;
|
|
1640
|
+
}
|
|
1641
|
+
/**
|
|
1642
|
+
* Two `postgres_changes` filters are the same when the server would collapse them into a single
|
|
1643
|
+
* subscription.
|
|
1644
|
+
* @internal
|
|
1645
|
+
*/
|
|
1646
|
+
static isSamePostgresFilter(a, b) {
|
|
1647
|
+
var _a, _b, _c, _d;
|
|
1648
|
+
const selectA = (_b = (_a = a === null || a === void 0 ? void 0 : a.select) === null || _a === void 0 ? void 0 : _a.join()) !== null && _b !== void 0 ? _b : void 0;
|
|
1649
|
+
const selectB = (_d = (_c = b === null || b === void 0 ? void 0 : b.select) === null || _c === void 0 ? void 0 : _c.join()) !== null && _d !== void 0 ? _d : void 0;
|
|
1650
|
+
return (a === null || a === void 0 ? void 0 : a.event) === (b === null || b === void 0 ? void 0 : b.event) && _RealtimeChannel.isFilterValueEqual(a === null || a === void 0 ? void 0 : a.schema, b === null || b === void 0 ? void 0 : b.schema) && _RealtimeChannel.isFilterValueEqual(a === null || a === void 0 ? void 0 : a.table, b === null || b === void 0 ? void 0 : b.table) && _RealtimeChannel.isFilterValueEqual(a === null || a === void 0 ? void 0 : a.filter, b === null || b === void 0 ? void 0 : b.filter) && selectA === selectB;
|
|
1651
|
+
}
|
|
1652
|
+
/** @internal */
|
|
1653
|
+
_getPayloadRecords(payload) {
|
|
1654
|
+
const records = {
|
|
1655
|
+
new: {},
|
|
1656
|
+
old: {}
|
|
1657
|
+
};
|
|
1658
|
+
if (payload.type === "INSERT" || payload.type === "UPDATE") {
|
|
1659
|
+
records.new = convertChangeData(payload.columns, payload.record);
|
|
1660
|
+
}
|
|
1661
|
+
if (payload.type === "UPDATE" || payload.type === "DELETE") {
|
|
1662
|
+
records.old = convertChangeData(payload.columns, payload.old_record);
|
|
1663
|
+
}
|
|
1664
|
+
return records;
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
|
|
1668
|
+
Object.defineProperty(exports, "FunctionRegion", {
|
|
1669
|
+
enumerable: true,
|
|
1670
|
+
get: function () { return supabaseJs.FunctionRegion; }
|
|
1671
|
+
});
|
|
1672
|
+
Object.defineProperty(exports, "FunctionsError", {
|
|
1673
|
+
enumerable: true,
|
|
1674
|
+
get: function () { return supabaseJs.FunctionsError; }
|
|
1675
|
+
});
|
|
1676
|
+
Object.defineProperty(exports, "FunctionsFetchError", {
|
|
1677
|
+
enumerable: true,
|
|
1678
|
+
get: function () { return supabaseJs.FunctionsFetchError; }
|
|
1679
|
+
});
|
|
1680
|
+
Object.defineProperty(exports, "FunctionsHttpError", {
|
|
1681
|
+
enumerable: true,
|
|
1682
|
+
get: function () { return supabaseJs.FunctionsHttpError; }
|
|
1683
|
+
});
|
|
1684
|
+
Object.defineProperty(exports, "FunctionsRelayError", {
|
|
1685
|
+
enumerable: true,
|
|
1686
|
+
get: function () { return supabaseJs.FunctionsRelayError; }
|
|
1687
|
+
});
|
|
1688
|
+
Object.defineProperty(exports, "PostgrestError", {
|
|
1689
|
+
enumerable: true,
|
|
1690
|
+
get: function () { return supabaseJs.PostgrestError; }
|
|
1691
|
+
});
|
|
1692
|
+
Object.defineProperty(exports, "StorageApiError", {
|
|
1693
|
+
enumerable: true,
|
|
1694
|
+
get: function () { return supabaseJs.StorageApiError; }
|
|
1695
|
+
});
|
|
1696
|
+
Object.defineProperty(exports, "SupabaseClient", {
|
|
1697
|
+
enumerable: true,
|
|
1698
|
+
get: function () { return supabaseJs.SupabaseClient; }
|
|
1699
|
+
});
|
|
1700
|
+
Object.defineProperty(exports, "createSupabaseClient", {
|
|
1701
|
+
enumerable: true,
|
|
1702
|
+
get: function () { return supabaseJs.createClient; }
|
|
1703
|
+
});
|
|
1704
|
+
exports.AuthApiError = AuthApiError;
|
|
1705
|
+
exports.AuthError = AuthError;
|
|
1706
|
+
exports.RealtimeChannel = RealtimeChannel;
|
|
1707
|
+
exports.createClient = createClient;
|
|
1708
|
+
//# sourceMappingURL=index.cjs.map
|
|
1709
|
+
//# sourceMappingURL=index.cjs.map
|