This commit is contained in:
MarcWieland
2026-07-26 23:57:23 +02:00
commit 8b613ec0bc
6300 changed files with 1257646 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
import type { SocketState, ChannelState, ChannelEvent as PhoenixChannelEvent, Transport, Vsn } from '../phoenix/types';
export type { SocketState, ChannelState, Transport };
export declare const DEFAULT_VERSION = "realtime-js/2.110.8";
export declare const VSN_1_0_0: Vsn;
export declare const VSN_2_0_0: Vsn;
export declare const DEFAULT_VSN: Vsn;
export declare const VERSION = "2.110.8";
export declare const DEFAULT_TIMEOUT = 10000;
export declare const WS_CLOSE_NORMAL = 1000;
export declare const MAX_PUSH_BUFFER_SIZE = 100;
export declare const SOCKET_STATES: {
readonly connecting: 0;
readonly open: 1;
readonly closing: 2;
readonly closed: 3;
};
export declare const CHANNEL_STATES: {
readonly closed: "closed";
readonly errored: "errored";
readonly joined: "joined";
readonly joining: "joining";
readonly leaving: "leaving";
};
export type ChannelEvent = PhoenixChannelEvent | 'access_token';
export declare const CHANNEL_EVENTS: {
readonly close: "phx_close";
readonly error: "phx_error";
readonly join: "phx_join";
readonly reply: "phx_reply";
readonly leave: "phx_leave";
readonly access_token: "access_token";
};
export declare const TRANSPORTS: {
readonly websocket: "websocket";
};
export type ConnectionState = 'connecting' | 'open' | 'closing' | 'closed' | (string & {});
export declare const CONNECTION_STATE: {
readonly connecting: "connecting";
readonly open: "open";
readonly closing: "closing";
readonly closed: "closed";
};
//# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,YAAY,IAAI,mBAAmB,EACnC,SAAS,EACT,GAAG,EACJ,MAAM,kBAAkB,CAAA;AAEzB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,CAAA;AAEpD,eAAO,MAAM,eAAe,wBAA2B,CAAA;AAEvD,eAAO,MAAM,SAAS,EAAE,GAAa,CAAA;AACrC,eAAO,MAAM,SAAS,EAAE,GAAa,CAAA;AACrC,eAAO,MAAM,WAAW,EAAE,GAAe,CAAA;AAEzC,eAAO,MAAM,OAAO,YAAU,CAAA;AAE9B,eAAO,MAAM,eAAe,QAAQ,CAAA;AAEpC,eAAO,MAAM,eAAe,OAAO,CAAA;AACnC,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC,eAAO,MAAM,aAAa;;;;;CAKhB,CAAA;AAEV,eAAO,MAAM,cAAc;;;;;;CAMjB,CAAA;AAEV,MAAM,MAAM,YAAY,GAAG,mBAAmB,GAAG,cAAc,CAAA;AAE/D,eAAO,MAAM,cAAc;;;;;;;CAOjB,CAAA;AAEV,eAAO,MAAM,UAAU;;CAEb,CAAA;AAEV,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAE1F,eAAO,MAAM,gBAAgB;;;;;CAKnB,CAAA"}
+40
View File
@@ -0,0 +1,40 @@
import { version } from './version';
export const DEFAULT_VERSION = `realtime-js/${version}`;
export const VSN_1_0_0 = '1.0.0';
export const VSN_2_0_0 = '2.0.0';
export const DEFAULT_VSN = VSN_2_0_0;
export const VERSION = version;
export const DEFAULT_TIMEOUT = 10000;
export const WS_CLOSE_NORMAL = 1000;
export const MAX_PUSH_BUFFER_SIZE = 100;
export const SOCKET_STATES = {
connecting: 0,
open: 1,
closing: 2,
closed: 3,
};
export const CHANNEL_STATES = {
closed: 'closed',
errored: 'errored',
joined: 'joined',
joining: 'joining',
leaving: 'leaving',
};
export const CHANNEL_EVENTS = {
close: 'phx_close',
error: 'phx_error',
join: 'phx_join',
reply: 'phx_reply',
leave: 'phx_leave',
access_token: 'access_token',
};
export const TRANSPORTS = {
websocket: 'websocket',
};
export const CONNECTION_STATE = {
connecting: 'connecting',
open: 'open',
closing: 'closing',
closed: 'closed',
};
//# sourceMappingURL=constants.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAWnC,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,OAAO,EAAE,CAAA;AAEvD,MAAM,CAAC,MAAM,SAAS,GAAQ,OAAO,CAAA;AACrC,MAAM,CAAC,MAAM,SAAS,GAAQ,OAAO,CAAA;AACrC,MAAM,CAAC,MAAM,WAAW,GAAQ,SAAS,CAAA;AAEzC,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAA;AAE9B,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAA;AAEpC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAA;AACnC,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAA;AAEvC,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,UAAU,EAAE,CAAC;IACb,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,CAAC;CACD,CAAA;AAEV,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;CACV,CAAA;AAIV,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,WAAW;IAClB,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,WAAW;IAClB,KAAK,EAAE,WAAW;IAClB,YAAY,EAAE,cAAc;CACpB,CAAA;AAEV,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,WAAW;CACd,CAAA;AAIV,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU,EAAE,YAAY;IACxB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;CACR,CAAA"}
@@ -0,0 +1,10 @@
/**
* Normalize the various shapes a channel error reason can take into a real `Error`.
*
* Transport-level channel errors arrive as a `CloseEvent`, a transport `Event`, an `Error`,
* a string, or `undefined` depending on which path in the underlying socket fired. Server-reply
* errors arrive as a payload object. This helper produces a consistent `Error` for every case
* and preserves the original via `cause` so callers can still inspect the raw event.
*/
export declare function normalizeChannelError(reason: unknown): Error;
//# sourceMappingURL=normalizeChannelError.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"normalizeChannelError.d.ts","sourceRoot":"","sources":["../../../src/lib/normalizeChannelError.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,CAqB5D"}
@@ -0,0 +1,26 @@
/**
* Normalize the various shapes a channel error reason can take into a real `Error`.
*
* Transport-level channel errors arrive as a `CloseEvent`, a transport `Event`, an `Error`,
* a string, or `undefined` depending on which path in the underlying socket fired. Server-reply
* errors arrive as a payload object. This helper produces a consistent `Error` for every case
* and preserves the original via `cause` so callers can still inspect the raw event.
*/
export function normalizeChannelError(reason) {
if (reason instanceof Error) {
return reason;
}
if (typeof reason === 'string') {
return new Error(reason);
}
if (reason && typeof reason === 'object') {
const obj = reason;
if (typeof obj.code === 'number') {
const detail = typeof obj.reason === 'string' && obj.reason ? ` (${obj.reason})` : '';
return new Error(`socket closed: ${obj.code}${detail}`, { cause: reason });
}
return new Error('channel error: transport failure', { cause: reason });
}
return new Error('channel error: connection lost');
}
//# sourceMappingURL=normalizeChannelError.js.map
@@ -0,0 +1 @@
{"version":3,"file":"normalizeChannelError.js","sourceRoot":"","sources":["../../../src/lib/normalizeChannelError.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAe;IACnD,IAAI,MAAM,YAAY,KAAK,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1B,CAAC;IAED,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,MAAiC,CAAA;QAE7C,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;YACrF,OAAO,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,IAAI,GAAG,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAC5E,CAAC;QAED,OAAO,IAAI,KAAK,CAAC,kCAAkC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IACzE,CAAC;IAED,OAAO,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;AACpD,CAAC"}
+33
View File
@@ -0,0 +1,33 @@
export type Msg<T> = {
join_ref?: string | null;
ref?: string | null;
topic: string;
event: string;
payload: T;
};
export default class Serializer {
HEADER_LENGTH: number;
USER_BROADCAST_PUSH_META_LENGTH: number;
KINDS: {
userBroadcastPush: number;
userBroadcast: number;
};
BINARY_ENCODING: number;
JSON_ENCODING: number;
BROADCAST_EVENT: string;
allowedMetadataKeys: string[];
constructor(allowedMetadataKeys?: string[] | null);
encode(msg: Msg<{
[key: string]: any;
}>, callback: (result: ArrayBuffer | string) => any): any;
private _binaryEncodeUserBroadcastPush;
private _encodeBinaryUserBroadcastPush;
private _encodeJsonUserBroadcastPush;
private _encodeUserBroadcastPush;
decode(rawPayload: ArrayBuffer | string, callback: Function): any;
private _binaryDecode;
private _decodeUserBroadcast;
private _isArrayBuffer;
private _pick;
}
//# sourceMappingURL=serializer.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../../../src/lib/serializer.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,CAAC,CAAA;CACX,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,aAAa,SAAI;IACjB,+BAA+B,SAAI;IACnC,KAAK;;;MAA6C;IAClD,eAAe,SAAI;IACnB,aAAa,SAAI;IACjB,eAAe,SAAc;IAE7B,mBAAmB,EAAE,MAAM,EAAE,CAAK;gBAEtB,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;IAIjD,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,KAAK,GAAG;IAexF,OAAO,CAAC,8BAA8B;IAQtC,OAAO,CAAC,8BAA8B;IAKtC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,wBAAwB;IA6EhC,MAAM,CAAC,UAAU,EAAE,WAAW,GAAG,MAAM,EAAE,QAAQ,EAAE,QAAQ;IAe3D,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,oBAAoB;IA0C5B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,KAAK;CAMd"}
+163
View File
@@ -0,0 +1,163 @@
export default class Serializer {
constructor(allowedMetadataKeys) {
this.HEADER_LENGTH = 1;
this.USER_BROADCAST_PUSH_META_LENGTH = 6;
this.KINDS = { userBroadcastPush: 3, userBroadcast: 4 };
this.BINARY_ENCODING = 0;
this.JSON_ENCODING = 1;
this.BROADCAST_EVENT = 'broadcast';
this.allowedMetadataKeys = [];
this.allowedMetadataKeys = allowedMetadataKeys !== null && allowedMetadataKeys !== void 0 ? allowedMetadataKeys : [];
}
encode(msg, callback) {
if (msg.event === this.BROADCAST_EVENT &&
!(msg.payload instanceof ArrayBuffer) &&
typeof msg.payload.event === 'string') {
return callback(this._binaryEncodeUserBroadcastPush(msg));
}
let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload];
return callback(JSON.stringify(payload));
}
_binaryEncodeUserBroadcastPush(message) {
var _a;
if (this._isArrayBuffer((_a = message.payload) === null || _a === void 0 ? void 0 : _a.payload)) {
return this._encodeBinaryUserBroadcastPush(message);
}
else {
return this._encodeJsonUserBroadcastPush(message);
}
}
_encodeBinaryUserBroadcastPush(message) {
var _a, _b;
const userPayload = (_b = (_a = message.payload) === null || _a === void 0 ? void 0 : _a.payload) !== null && _b !== void 0 ? _b : new ArrayBuffer(0);
return this._encodeUserBroadcastPush(message, this.BINARY_ENCODING, userPayload);
}
_encodeJsonUserBroadcastPush(message) {
var _a, _b;
const userPayload = (_b = (_a = message.payload) === null || _a === void 0 ? void 0 : _a.payload) !== null && _b !== void 0 ? _b : {};
const encoder = new TextEncoder();
const encodedUserPayload = encoder.encode(JSON.stringify(userPayload)).buffer;
return this._encodeUserBroadcastPush(message, this.JSON_ENCODING, encodedUserPayload);
}
_encodeUserBroadcastPush(message, encodingType, encodedPayload) {
var _a, _b;
// Encode each header field as UTF-8. The length prefixes are byte counts and
// the decode side uses TextDecoder (UTF-8), so measuring with String.length
// and writing with charCodeAt would corrupt any multi-byte character (e.g.
// accents or emoji) and desynchronize the buffer.
const encoder = new TextEncoder();
const topic = encoder.encode(message.topic);
const ref = encoder.encode((_a = message.ref) !== null && _a !== void 0 ? _a : '');
const joinRef = encoder.encode((_b = message.join_ref) !== null && _b !== void 0 ? _b : '');
const userEvent = encoder.encode(message.payload.event);
// Filter metadata based on allowed keys
const rest = this.allowedMetadataKeys
? this._pick(message.payload, this.allowedMetadataKeys)
: {};
const metadata = encoder.encode(Object.keys(rest).length === 0 ? '' : JSON.stringify(rest));
// Validate byte lengths don't exceed uint8 max value (255)
if (joinRef.length > 255) {
throw new Error(`joinRef length ${joinRef.length} exceeds maximum of 255`);
}
if (ref.length > 255) {
throw new Error(`ref length ${ref.length} exceeds maximum of 255`);
}
if (topic.length > 255) {
throw new Error(`topic length ${topic.length} exceeds maximum of 255`);
}
if (userEvent.length > 255) {
throw new Error(`userEvent length ${userEvent.length} exceeds maximum of 255`);
}
if (metadata.length > 255) {
throw new Error(`metadata length ${metadata.length} exceeds maximum of 255`);
}
const metaLength = this.USER_BROADCAST_PUSH_META_LENGTH +
joinRef.length +
ref.length +
topic.length +
userEvent.length +
metadata.length;
const header = new ArrayBuffer(this.HEADER_LENGTH + metaLength);
const view = new DataView(header);
const bytes = new Uint8Array(header);
let offset = 0;
view.setUint8(offset++, this.KINDS.userBroadcastPush); // kind
view.setUint8(offset++, joinRef.length);
view.setUint8(offset++, ref.length);
view.setUint8(offset++, topic.length);
view.setUint8(offset++, userEvent.length);
view.setUint8(offset++, metadata.length);
view.setUint8(offset++, encodingType);
bytes.set(joinRef, offset);
offset += joinRef.length;
bytes.set(ref, offset);
offset += ref.length;
bytes.set(topic, offset);
offset += topic.length;
bytes.set(userEvent, offset);
offset += userEvent.length;
bytes.set(metadata, offset);
offset += metadata.length;
var combined = new Uint8Array(header.byteLength + encodedPayload.byteLength);
combined.set(new Uint8Array(header), 0);
combined.set(new Uint8Array(encodedPayload), header.byteLength);
return combined.buffer;
}
decode(rawPayload, callback) {
if (this._isArrayBuffer(rawPayload)) {
let result = this._binaryDecode(rawPayload);
return callback(result);
}
if (typeof rawPayload === 'string') {
const jsonPayload = JSON.parse(rawPayload);
const [join_ref, ref, topic, event, payload] = jsonPayload;
return callback({ join_ref, ref, topic, event, payload });
}
return callback({});
}
_binaryDecode(buffer) {
const view = new DataView(buffer);
const kind = view.getUint8(0);
const decoder = new TextDecoder();
switch (kind) {
case this.KINDS.userBroadcast:
return this._decodeUserBroadcast(buffer, view, decoder);
}
}
_decodeUserBroadcast(buffer, view, decoder) {
const topicSize = view.getUint8(1);
const userEventSize = view.getUint8(2);
const metadataSize = view.getUint8(3);
const payloadEncoding = view.getUint8(4);
let offset = this.HEADER_LENGTH + 4;
const topic = decoder.decode(buffer.slice(offset, offset + topicSize));
offset = offset + topicSize;
const userEvent = decoder.decode(buffer.slice(offset, offset + userEventSize));
offset = offset + userEventSize;
const metadata = decoder.decode(buffer.slice(offset, offset + metadataSize));
offset = offset + metadataSize;
const payload = buffer.slice(offset, buffer.byteLength);
const parsedPayload = payloadEncoding === this.JSON_ENCODING ? JSON.parse(decoder.decode(payload)) : payload;
const data = {
type: this.BROADCAST_EVENT,
event: userEvent,
payload: parsedPayload,
};
// Metadata is optional and always JSON encoded
if (metadataSize > 0) {
data['meta'] = JSON.parse(metadata);
}
return { join_ref: null, ref: null, topic: topic, event: this.BROADCAST_EVENT, payload: data };
}
_isArrayBuffer(buffer) {
var _a;
return buffer instanceof ArrayBuffer || ((_a = buffer === null || buffer === void 0 ? void 0 : buffer.constructor) === null || _a === void 0 ? void 0 : _a.name) === 'ArrayBuffer';
}
_pick(obj, keys) {
if (!obj || typeof obj !== 'object') {
return {};
}
return Object.fromEntries(Object.entries(obj).filter(([key]) => keys.includes(key)));
}
}
//# sourceMappingURL=serializer.js.map
File diff suppressed because one or more lines are too long
+109
View File
@@ -0,0 +1,109 @@
/**
* Helpers to convert the change Payload into native JS types.
*/
export declare enum PostgresTypes {
abstime = "abstime",
bool = "bool",
date = "date",
daterange = "daterange",
float4 = "float4",
float8 = "float8",
int2 = "int2",
int4 = "int4",
int4range = "int4range",
int8 = "int8",
int8range = "int8range",
json = "json",
jsonb = "jsonb",
money = "money",
numeric = "numeric",
oid = "oid",
reltime = "reltime",
text = "text",
time = "time",
timestamp = "timestamp",
timestamptz = "timestamptz",
timetz = "timetz",
tsrange = "tsrange",
tstzrange = "tstzrange"
}
type Columns = {
name: string;
type: string;
flags?: string[];
type_modifier?: number;
}[];
type BaseValue = null | string | number | boolean;
type RecordValue = BaseValue | BaseValue[];
type Record = {
[key: string]: RecordValue;
};
/**
* 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 }
*/
export declare const convertChangeData: (columns: Columns, record: Record | null, options?: {
skipTypes?: string[];
}) => Record;
/**
* 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"
*/
export declare const convertColumn: (columnName: string, columns: Columns, record: Record, skipTypes: string[]) => RecordValue;
/**
* 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]
*/
export declare const convertCell: (type: string, value: RecordValue) => RecordValue;
export declare const toBoolean: (value: RecordValue) => RecordValue;
export declare const toNumber: (value: RecordValue) => RecordValue;
export declare const toJson: (value: RecordValue) => RecordValue;
/**
* 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]
*/
export declare const toArray: (value: RecordValue, type: string) => RecordValue;
/**
* 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'
*/
export declare const toTimestampString: (value: RecordValue) => RecordValue;
export declare const httpEndpointURL: (socketUrl: string) => string;
export {};
//# sourceMappingURL=transformers.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"transformers.d.ts","sourceRoot":"","sources":["../../../src/lib/transformers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,oBAAY,aAAa;IACvB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,SAAS,cAAc;CACxB;AAED,KAAK,OAAO,GAAG;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,EAAE,CAAA;AAEH,KAAK,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AACjD,KAAK,WAAW,GAAG,SAAS,GAAG,SAAS,EAAE,CAAA;AAE1C,KAAK,MAAM,GAAG;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;CAC3B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,GAC5B,SAAS,OAAO,EAChB,QAAQ,MAAM,GAAG,IAAI,EACrB,UAAS;IAAE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,KACrC,MAWF,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,GACxB,YAAY,MAAM,EAClB,SAAS,OAAO,EAChB,QAAQ,MAAM,EACd,WAAW,MAAM,EAAE,KAClB,WAUF,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,OAAO,WAAW,KAAG,WA0C9D,CAAA;AAKD,eAAO,MAAM,SAAS,GAAI,OAAO,WAAW,KAAG,WAS9C,CAAA;AACD,eAAO,MAAM,QAAQ,GAAI,OAAO,WAAW,KAAG,WAQ7C,CAAA;AACD,eAAO,MAAM,MAAM,GAAI,OAAO,WAAW,KAAG,WAS3C,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,WAAW,EAAE,MAAM,MAAM,KAAG,WA0B1D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,WAAW,KAAG,WAMtD,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,WAAW,MAAM,KAAG,MAkBnD,CAAA"}
+229
View File
@@ -0,0 +1,229 @@
/**
* Helpers to convert the change Payload into native JS types.
*/
// Adapted from epgsql (src/epgsql_binary.erl), this module licensed under
// 3-clause BSD found here: https://raw.githubusercontent.com/epgsql/epgsql/devel/LICENSE
export 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 || (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 }
*/
export const convertChangeData = (columns, record, options = {}) => {
var _a;
const skipTypes = (_a = options.skipTypes) !== null && _a !== void 0 ? _a : [];
if (!record) {
return {};
}
return Object.keys(record).reduce((acc, rec_key) => {
acc[rec_key] = convertColumn(rec_key, columns, record, skipTypes);
return acc;
}, {});
};
/**
* 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"
*/
export 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 convertCell(colType, value);
}
return noop(value);
};
/**
* 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]
*/
export const convertCell = (type, value) => {
// if data type is an array
if (type.charAt(0) === '_') {
const dataType = type.slice(1, type.length);
return toArray(value, dataType);
}
// If not null, convert to correct type.
switch (type) {
case PostgresTypes.bool:
return toBoolean(value);
case PostgresTypes.float4:
case PostgresTypes.float8:
case PostgresTypes.int2:
case PostgresTypes.int4:
case PostgresTypes.int8:
case PostgresTypes.numeric:
case PostgresTypes.oid:
return toNumber(value);
case PostgresTypes.json:
case PostgresTypes.jsonb:
return toJson(value);
case PostgresTypes.timestamp:
return 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);
}
};
const noop = (value) => {
return value;
};
export const toBoolean = (value) => {
switch (value) {
case 't':
return true;
case 'f':
return false;
default:
return value;
}
};
export const toNumber = (value) => {
if (typeof value === 'string') {
const parsedValue = parseFloat(value);
if (!Number.isNaN(parsedValue)) {
return parsedValue;
}
}
return value;
};
export const toJson = (value) => {
if (typeof value === 'string') {
try {
return JSON.parse(value);
}
catch (_a) {
return value;
}
}
return value;
};
/**
* 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]
*/
export 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) => convertCell(type, val));
}
return value;
};
/**
* 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'
*/
export const toTimestampString = (value) => {
if (typeof value === 'string') {
return value.replace(' ', 'T');
}
return value;
};
export const httpEndpointURL = (socketUrl) => {
const wsUrl = new URL(socketUrl);
wsUrl.protocol = wsUrl.protocol.replace(/^ws/i, 'http');
wsUrl.pathname = wsUrl.pathname
.replace(/\/+$/, '') // remove all trailing slashes
.replace(/\/socket\/websocket$/i, '') // remove the socket/websocket path
.replace(/\/socket$/i, '') // remove the socket path
.replace(/\/websocket$/i, ''); // remove the websocket path
if (wsUrl.pathname === '' || wsUrl.pathname === '/') {
wsUrl.pathname = '/api/broadcast';
}
else {
wsUrl.pathname = wsUrl.pathname + '/api/broadcast';
}
return wsUrl.href;
};
//# sourceMappingURL=transformers.js.map
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
export declare const version = "2.110.8";
//# sourceMappingURL=version.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/lib/version.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,OAAO,YAAY,CAAA"}
+8
View File
@@ -0,0 +1,8 @@
// Generated automatically during releases by scripts/update-version-files.ts
// This file provides runtime access to the package version for:
// - HTTP request headers (e.g., X-Client-Info header for API requests)
// - Debugging and support (identifying which version is running)
// - Telemetry and logging (version reporting in errors/analytics)
// - Ensuring build artifacts match the published package version
export const version = '2.110.8';
//# sourceMappingURL=version.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/lib/version.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gEAAgE;AAChE,uEAAuE;AACvE,iEAAiE;AACjE,kEAAkE;AAClE,iEAAiE;AACjE,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAA"}
@@ -0,0 +1,82 @@
export interface WebSocketLike {
readonly CONNECTING: number;
readonly OPEN: number;
readonly CLOSING: number;
readonly CLOSED: number;
readonly readyState: number;
readonly url: string;
readonly protocol: string;
/**
* Closes the socket, optionally providing a close code and reason.
*/
close(code?: number, reason?: string): void;
/**
* Sends data through the socket using the underlying implementation.
*/
send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;
onopen: ((this: any, ev: Event) => any) | null;
onmessage: ((this: any, ev: MessageEvent) => any) | null;
onclose: ((this: any, ev: CloseEvent) => any) | null;
onerror: ((this: any, ev: Event) => any) | null;
/**
* Registers an event listener on the socket (compatible with browser WebSocket API).
*/
addEventListener(type: string, listener: EventListener): void;
/**
* Removes a previously registered event listener.
*/
removeEventListener(type: string, listener: EventListener): void;
binaryType?: string;
bufferedAmount?: number;
extensions?: string;
dispatchEvent?: (event: Event) => boolean;
}
export interface WebSocketEnvironment {
type: 'native' | 'cloudflare' | 'unsupported';
/** WebSocket constructor for this environment, if available. */
wsConstructor?: typeof WebSocket;
error?: string;
workaround?: string;
}
/**
* Utilities for creating WebSocket instances across runtimes.
*/
export declare class WebSocketFactory {
/**
* Static-only utility prevent instantiation.
*/
private constructor();
private static detectEnvironment;
/**
* Returns the best available WebSocket constructor for the current runtime.
*
* @category Realtime
*
* @example Example with error handling
* ```ts
* try {
* const WS = WebSocketFactory.getWebSocketConstructor()
* const socket = new WS('wss://example.com/socket')
* } catch (error) {
* console.error('WebSocket not available in this environment.', error)
* }
* ```
*/
static getWebSocketConstructor(): typeof WebSocket;
/**
* Detects whether the runtime can establish WebSocket connections.
*
* @category Realtime
*
* @example Example in a Node.js script
* ```ts
* if (!WebSocketFactory.isWebSocketSupported()) {
* console.error('WebSockets are required for this script.')
* process.exitCode = 1
* }
* ```
*/
static isWebSocketSupported(): boolean;
}
export default WebSocketFactory;
//# sourceMappingURL=websocket-factory.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"websocket-factory.d.ts","sourceRoot":"","sources":["../../../src/lib/websocket-factory.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IAEzB;;OAEG;IACH,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3C;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,GAAG,eAAe,GAAG,IAAI,CAAA;IAEnE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,CAAA;IAC9C,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,KAAK,GAAG,CAAC,GAAG,IAAI,CAAA;IACxD,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,UAAU,KAAK,GAAG,CAAC,GAAG,IAAI,CAAA;IACpD,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,CAAA;IAE/C;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAA;IAC7D;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAA;IAGhE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,QAAQ,GAAG,YAAY,GAAG,aAAa,CAAA;IAC7C,gEAAgE;IAChE,aAAa,CAAC,EAAE,OAAO,SAAS,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAYD;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,OAAO;IACP,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAqEhC;;;;;;;;;;;;;;OAcG;WACW,uBAAuB,IAAI,OAAO,SAAS;IAYzD;;;;;;;;;;;;OAYG;WACW,oBAAoB,IAAI,OAAO;CAQ9C;AAED,eAAe,gBAAgB,CAAA"}
+109
View File
@@ -0,0 +1,109 @@
/**
* Utilities for creating WebSocket instances across runtimes.
*/
export class WebSocketFactory {
/**
* Static-only utility prevent instantiation.
*/
constructor() { }
static detectEnvironment() {
var _a;
if (typeof WebSocket !== 'undefined') {
return { type: 'native', wsConstructor: WebSocket };
}
const gt = globalThis;
if (typeof globalThis !== 'undefined' && typeof gt.WebSocket !== 'undefined') {
return { type: 'native', wsConstructor: gt.WebSocket };
}
const gl = typeof global !== 'undefined' ? global : undefined;
if (gl && typeof gl.WebSocket !== 'undefined') {
return { type: 'native', wsConstructor: gl.WebSocket };
}
if (typeof globalThis !== 'undefined' &&
typeof gt.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' && gt.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.',
};
}
// Use dynamic property access to avoid Next.js Edge Runtime static analysis warnings
const _process = globalThis['process'];
if (_process) {
const processVersions = _process['versions'];
if (processVersions && processVersions['node']) {
// Reaching here means an earlier check did not find a native WebSocket,
// so this Node.js process is missing the global WebSocket (Node.js 22+).
return {
type: 'unsupported',
error: 'Node.js detected but native WebSocket not found.',
workaround: 'Ensure you are running Node.js 22+ or provide a WebSocket implementation via the transport option.',
};
}
}
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.",
};
}
/**
* Returns the best available WebSocket constructor for the current runtime.
*
* @category Realtime
*
* @example Example with error handling
* ```ts
* try {
* const WS = WebSocketFactory.getWebSocketConstructor()
* const socket = new WS('wss://example.com/socket')
* } catch (error) {
* console.error('WebSocket not available in this environment.', error)
* }
* ```
*/
static getWebSocketConstructor() {
const env = this.detectEnvironment();
if (env.wsConstructor) {
return env.wsConstructor;
}
let errorMessage = env.error || 'WebSocket not supported in this environment.';
if (env.workaround) {
errorMessage += `\n\nSuggested solution: ${env.workaround}`;
}
throw new Error(errorMessage);
}
/**
* Detects whether the runtime can establish WebSocket connections.
*
* @category Realtime
*
* @example Example in a Node.js script
* ```ts
* if (!WebSocketFactory.isWebSocketSupported()) {
* console.error('WebSockets are required for this script.')
* process.exitCode = 1
* }
* ```
*/
static isWebSocketSupported() {
try {
const env = this.detectEnvironment();
return env.type === 'native';
}
catch (_a) {
return false;
}
}
}
export default WebSocketFactory;
//# sourceMappingURL=websocket-factory.js.map
@@ -0,0 +1 @@
{"version":3,"file":"websocket-factory.js","sourceRoot":"","sources":["../../../src/lib/websocket-factory.ts"],"names":[],"mappings":"AAyDA;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAC3B;;OAEG;IACH,gBAAuB,CAAC;IAChB,MAAM,CAAC,iBAAiB;;QAC9B,IAAI,OAAO,SAAS,KAAK,WAAW,EAAE,CAAC;YACrC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,CAAA;QACrD,CAAC;QAED,MAAM,EAAE,GAAG,UAAgD,CAAA;QAC3D,IAAI,OAAO,UAAU,KAAK,WAAW,IAAI,OAAO,EAAE,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAC7E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,CAAC,SAA6B,EAAE,CAAA;QAC5E,CAAC;QAED,MAAM,EAAE,GACN,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAE,MAAyC,CAAC,CAAC,CAAC,SAAS,CAAA;QACxF,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAC9C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,CAAC,SAA6B,EAAE,CAAA;QAC5E,CAAC;QAED,IACE,OAAO,UAAU,KAAK,WAAW;YACjC,OAAO,EAAE,CAAC,aAAa,KAAK,WAAW;YACvC,OAAO,UAAU,CAAC,SAAS,KAAK,WAAW,EAC3C,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,KAAK,EACH,yFAAyF;gBAC3F,UAAU,EACR,4GAA4G;aAC/G,CAAA;QACH,CAAC;QAED,IACE,CAAC,OAAO,UAAU,KAAK,WAAW,IAAI,EAAE,CAAC,WAAW,CAAC;YACrD,CAAC,OAAO,SAAS,KAAK,WAAW,KAAI,MAAA,SAAS,CAAC,SAAS,0CAAE,QAAQ,CAAC,aAAa,CAAC,CAAA,CAAC,EAClF,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,aAAa;gBACnB,KAAK,EACH,mGAAmG;gBACrG,UAAU,EACR,wFAAwF;aAC3F,CAAA;QACH,CAAC;QAED,qFAAqF;QACrF,MAAM,QAAQ,GAAI,UAAsC,CAAC,SAAS,CAErD,CAAA;QACb,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,eAAe,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;YAC5C,IAAI,eAAe,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/C,wEAAwE;gBACxE,yEAAyE;gBACzE,OAAO;oBACL,IAAI,EAAE,aAAa;oBACnB,KAAK,EAAE,kDAAkD;oBACzD,UAAU,EACR,oGAAoG;iBACvG,CAAA;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,uDAAuD;YAC9D,UAAU,EACR,yHAAyH;SAC5H,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACI,MAAM,CAAC,uBAAuB;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;QACpC,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;YACtB,OAAO,GAAG,CAAC,aAAa,CAAA;QAC1B,CAAC;QACD,IAAI,YAAY,GAAG,GAAG,CAAC,KAAK,IAAI,8CAA8C,CAAA;QAC9E,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YACnB,YAAY,IAAI,2BAA2B,GAAG,CAAC,UAAU,EAAE,CAAA;QAC7D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAA;IAC/B,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,MAAM,CAAC,oBAAoB;QAChC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;YACpC,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAA;QAC9B,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;CACF;AAED,eAAe,gBAAgB,CAAA"}