@uncorded/protocol 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/README.md +22 -0
- package/dist/branded.d.ts +29 -0
- package/dist/branded.d.ts.map +1 -0
- package/dist/branded.js +50 -0
- package/dist/branded.js.map +1 -0
- package/dist/close-codes.d.ts +21 -0
- package/dist/close-codes.d.ts.map +1 -0
- package/dist/close-codes.js +22 -0
- package/dist/close-codes.js.map +1 -0
- package/dist/codec.d.ts +12 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +41 -0
- package/dist/codec.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/opcodes.d.ts +81 -0
- package/dist/opcodes.d.ts.map +1 -0
- package/dist/opcodes.js +83 -0
- package/dist/opcodes.js.map +1 -0
- package/dist/schemas.d.ts +991 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +309 -0
- package/dist/schemas.js.map +1 -0
- package/dist/signaling.d.ts +92 -0
- package/dist/signaling.d.ts.map +1 -0
- package/dist/signaling.js +2 -0
- package/dist/signaling.js.map +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# @uncorded/protocol
|
|
2
|
+
|
|
3
|
+
Wire protocol for UnCorded — MessagePack codec, opcodes, and branded types.
|
|
4
|
+
|
|
5
|
+
> Internal dependency. Most plugin developers should install `@uncorded/plugin-server` or `@uncorded/plugin-client` instead.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bun add @uncorded/protocol
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What's Included
|
|
14
|
+
|
|
15
|
+
- **MessagePack codec** — `encode()` / `decode()` for binary WebSocket frames
|
|
16
|
+
- **Opcodes** and close codes for the WebSocket protocol
|
|
17
|
+
- **Branded types** — `UserId`, `ServerId`, `ChannelId`, `MessageId`, `PluginId`
|
|
18
|
+
- **Zod schemas** for runtime validation of protocol messages
|
|
19
|
+
|
|
20
|
+
## Docs
|
|
21
|
+
|
|
22
|
+
[uncorded.app/create-plugin/docs](https://uncorded.app/create-plugin/docs)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
type Brand<T, B extends string> = T & {
|
|
2
|
+
readonly __brand: B;
|
|
3
|
+
};
|
|
4
|
+
export type UserId = Brand<string, "UserId">;
|
|
5
|
+
export type ServerId = Brand<string, "ServerId">;
|
|
6
|
+
export type ChannelId = Brand<string, "ChannelId">;
|
|
7
|
+
export type MessageId = Brand<string, "MessageId">;
|
|
8
|
+
export type InviteCode = Brand<string, "InviteCode">;
|
|
9
|
+
export type FileReceiptId = Brand<string, "FileReceiptId">;
|
|
10
|
+
export type DmChannelId = Brand<string, "DmChannelId">;
|
|
11
|
+
/** Union type for any channel ID (server channel or DM channel) */
|
|
12
|
+
export type AnyChannelId = ChannelId | DmChannelId;
|
|
13
|
+
export type SubscriptionId = Brand<string, "SubscriptionId">;
|
|
14
|
+
export type ReportId = Brand<string, "ReportId">;
|
|
15
|
+
export type RoleId = Brand<string, "RoleId">;
|
|
16
|
+
export type PluginId = Brand<string, "PluginId">;
|
|
17
|
+
export declare function userId(raw: string): UserId;
|
|
18
|
+
export declare function serverId(raw: string): ServerId;
|
|
19
|
+
export declare function channelId(raw: string): ChannelId;
|
|
20
|
+
export declare function messageId(raw: string): MessageId;
|
|
21
|
+
export declare function inviteCode(raw: string): InviteCode;
|
|
22
|
+
export declare function fileReceiptId(raw: string): FileReceiptId;
|
|
23
|
+
export declare function dmChannelId(raw: string): DmChannelId;
|
|
24
|
+
export declare function subscriptionId(raw: string): SubscriptionId;
|
|
25
|
+
export declare function reportId(raw: string): ReportId;
|
|
26
|
+
export declare function roleId(raw: string): RoleId;
|
|
27
|
+
export declare function pluginId(raw: string): PluginId;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=branded.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branded.d.ts","sourceRoot":"","sources":["../src/branded.ts"],"names":[],"mappings":"AAAA,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC7C,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACjD,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACnD,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACnD,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AACrD,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAC3D,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AACvD,mEAAmE;AACnE,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,CAAC;AACnD,MAAM,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAC7D,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACjD,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC7C,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAOjD,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG1C;AACD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAG9C;AACD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAGhD;AACD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAGhD;AACD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAGlD;AACD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAGxD;AACD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAGpD;AACD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAG1D;AACD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAG9C;AACD,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG1C;AACD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAG9C"}
|
package/dist/branded.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Cast constructors (brand raw strings at application boundaries)
|
|
2
|
+
function assertNonEmpty(raw, label) {
|
|
3
|
+
if (!raw)
|
|
4
|
+
throw new Error(`${label} must not be empty`);
|
|
5
|
+
}
|
|
6
|
+
export function userId(raw) {
|
|
7
|
+
assertNonEmpty(raw, "UserId");
|
|
8
|
+
return raw;
|
|
9
|
+
}
|
|
10
|
+
export function serverId(raw) {
|
|
11
|
+
assertNonEmpty(raw, "ServerId");
|
|
12
|
+
return raw;
|
|
13
|
+
}
|
|
14
|
+
export function channelId(raw) {
|
|
15
|
+
assertNonEmpty(raw, "ChannelId");
|
|
16
|
+
return raw;
|
|
17
|
+
}
|
|
18
|
+
export function messageId(raw) {
|
|
19
|
+
assertNonEmpty(raw, "MessageId");
|
|
20
|
+
return raw;
|
|
21
|
+
}
|
|
22
|
+
export function inviteCode(raw) {
|
|
23
|
+
assertNonEmpty(raw, "InviteCode");
|
|
24
|
+
return raw;
|
|
25
|
+
}
|
|
26
|
+
export function fileReceiptId(raw) {
|
|
27
|
+
assertNonEmpty(raw, "FileReceiptId");
|
|
28
|
+
return raw;
|
|
29
|
+
}
|
|
30
|
+
export function dmChannelId(raw) {
|
|
31
|
+
assertNonEmpty(raw, "DmChannelId");
|
|
32
|
+
return raw;
|
|
33
|
+
}
|
|
34
|
+
export function subscriptionId(raw) {
|
|
35
|
+
assertNonEmpty(raw, "SubscriptionId");
|
|
36
|
+
return raw;
|
|
37
|
+
}
|
|
38
|
+
export function reportId(raw) {
|
|
39
|
+
assertNonEmpty(raw, "ReportId");
|
|
40
|
+
return raw;
|
|
41
|
+
}
|
|
42
|
+
export function roleId(raw) {
|
|
43
|
+
assertNonEmpty(raw, "RoleId");
|
|
44
|
+
return raw;
|
|
45
|
+
}
|
|
46
|
+
export function pluginId(raw) {
|
|
47
|
+
assertNonEmpty(raw, "PluginId");
|
|
48
|
+
return raw;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=branded.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branded.js","sourceRoot":"","sources":["../src/branded.ts"],"names":[],"mappings":"AAgBA,kEAAkE;AAClE,SAAS,cAAc,CAAC,GAAW,EAAE,KAAa;IAChD,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC9B,OAAO,GAAa,CAAC;AACvB,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,cAAc,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAChC,OAAO,GAAe,CAAC;AACzB,CAAC;AACD,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,cAAc,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACjC,OAAO,GAAgB,CAAC;AAC1B,CAAC;AACD,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,cAAc,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACjC,OAAO,GAAgB,CAAC;AAC1B,CAAC;AACD,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,cAAc,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAClC,OAAO,GAAiB,CAAC;AAC3B,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,cAAc,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IACrC,OAAO,GAAoB,CAAC;AAC9B,CAAC;AACD,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,cAAc,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IACnC,OAAO,GAAkB,CAAC;AAC5B,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,cAAc,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IACtC,OAAO,GAAqB,CAAC;AAC/B,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,cAAc,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAChC,OAAO,GAAe,CAAC;AACzB,CAAC;AACD,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC9B,OAAO,GAAa,CAAC;AACvB,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,cAAc,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAChC,OAAO,GAAe,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare enum CloseCode {
|
|
2
|
+
/** Frame was a string, expected binary MessagePack */
|
|
3
|
+
NOT_BINARY = 4001,
|
|
4
|
+
/** Failed to decode MessagePack frame */
|
|
5
|
+
INVALID_FRAME = 4002,
|
|
6
|
+
/** Client sent IDENTIFY twice */
|
|
7
|
+
ALREADY_IDENTIFIED = 4003,
|
|
8
|
+
/** IDENTIFY payload missing token */
|
|
9
|
+
MISSING_TOKEN = 4004,
|
|
10
|
+
/** Session token invalid or expired */
|
|
11
|
+
INVALID_SESSION = 4005,
|
|
12
|
+
/** Client sent opcode before IDENTIFY */
|
|
13
|
+
NOT_IDENTIFIED = 4006,
|
|
14
|
+
/** Client did not receive HEARTBEAT_ACK within timeout */
|
|
15
|
+
HEARTBEAT_TIMEOUT = 4007,
|
|
16
|
+
/** Server-side session/context changed — client should reconnect to refresh */
|
|
17
|
+
SESSION_UPDATED = 4010,
|
|
18
|
+
/** Account was permanently deleted — client should not reconnect */
|
|
19
|
+
ACCOUNT_DELETED = 4011
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=close-codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"close-codes.d.ts","sourceRoot":"","sources":["../src/close-codes.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,sDAAsD;IACtD,UAAU,OAAO;IACjB,yCAAyC;IACzC,aAAa,OAAO;IACpB,iCAAiC;IACjC,kBAAkB,OAAO;IACzB,qCAAqC;IACrC,aAAa,OAAO;IACpB,uCAAuC;IACvC,eAAe,OAAO;IACtB,yCAAyC;IACzC,cAAc,OAAO;IACrB,0DAA0D;IAC1D,iBAAiB,OAAO;IACxB,+EAA+E;IAC/E,eAAe,OAAO;IACtB,oEAAoE;IACpE,eAAe,OAAO;CACvB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export var CloseCode;
|
|
2
|
+
(function (CloseCode) {
|
|
3
|
+
/** Frame was a string, expected binary MessagePack */
|
|
4
|
+
CloseCode[CloseCode["NOT_BINARY"] = 4001] = "NOT_BINARY";
|
|
5
|
+
/** Failed to decode MessagePack frame */
|
|
6
|
+
CloseCode[CloseCode["INVALID_FRAME"] = 4002] = "INVALID_FRAME";
|
|
7
|
+
/** Client sent IDENTIFY twice */
|
|
8
|
+
CloseCode[CloseCode["ALREADY_IDENTIFIED"] = 4003] = "ALREADY_IDENTIFIED";
|
|
9
|
+
/** IDENTIFY payload missing token */
|
|
10
|
+
CloseCode[CloseCode["MISSING_TOKEN"] = 4004] = "MISSING_TOKEN";
|
|
11
|
+
/** Session token invalid or expired */
|
|
12
|
+
CloseCode[CloseCode["INVALID_SESSION"] = 4005] = "INVALID_SESSION";
|
|
13
|
+
/** Client sent opcode before IDENTIFY */
|
|
14
|
+
CloseCode[CloseCode["NOT_IDENTIFIED"] = 4006] = "NOT_IDENTIFIED";
|
|
15
|
+
/** Client did not receive HEARTBEAT_ACK within timeout */
|
|
16
|
+
CloseCode[CloseCode["HEARTBEAT_TIMEOUT"] = 4007] = "HEARTBEAT_TIMEOUT";
|
|
17
|
+
/** Server-side session/context changed — client should reconnect to refresh */
|
|
18
|
+
CloseCode[CloseCode["SESSION_UPDATED"] = 4010] = "SESSION_UPDATED";
|
|
19
|
+
/** Account was permanently deleted — client should not reconnect */
|
|
20
|
+
CloseCode[CloseCode["ACCOUNT_DELETED"] = 4011] = "ACCOUNT_DELETED";
|
|
21
|
+
})(CloseCode || (CloseCode = {}));
|
|
22
|
+
//# sourceMappingURL=close-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"close-codes.js","sourceRoot":"","sources":["../src/close-codes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,SAmBX;AAnBD,WAAY,SAAS;IACnB,sDAAsD;IACtD,wDAAiB,CAAA;IACjB,yCAAyC;IACzC,8DAAoB,CAAA;IACpB,iCAAiC;IACjC,wEAAyB,CAAA;IACzB,qCAAqC;IACrC,8DAAoB,CAAA;IACpB,uCAAuC;IACvC,kEAAsB,CAAA;IACtB,yCAAyC;IACzC,gEAAqB,CAAA;IACrB,0DAA0D;IAC1D,sEAAwB,CAAA;IACxB,+EAA+E;IAC/E,kEAAsB,CAAA;IACtB,oEAAoE;IACpE,kEAAsB,CAAA;AACxB,CAAC,EAnBW,SAAS,KAAT,SAAS,QAmBpB"}
|
package/dist/codec.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type DecoderOptions } from "@msgpack/msgpack";
|
|
2
|
+
import type { Opcode } from "./opcodes.js";
|
|
3
|
+
export interface GatewayFrame {
|
|
4
|
+
op: Opcode;
|
|
5
|
+
d: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare function encode(frame: GatewayFrame): Uint8Array;
|
|
8
|
+
/** Tighter limits for client-side decoding (browser memory is more constrained). */
|
|
9
|
+
export declare const CLIENT_DECODE_OPTIONS: DecoderOptions;
|
|
10
|
+
export declare function decode(data: ArrayLike<number> | BufferSource): GatewayFrame;
|
|
11
|
+
export declare function decodeClient(data: ArrayLike<number> | BufferSource): GatewayFrame;
|
|
12
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAU3C,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,OAAO,CAAC;CACZ;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CAEtD;AAED,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,EAAE,cAKnC,CAAC;AAEF,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,YAAY,GAAG,YAAY,CAY3E;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,YAAY,GAAG,YAAY,CAYjF"}
|
package/dist/codec.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { encode as msgpackEncode, decode as msgpackDecode, } from "@msgpack/msgpack";
|
|
2
|
+
/** Prevent OOM DoS — reject payloads with oversized strings/arrays/maps. */
|
|
3
|
+
const DECODE_OPTIONS = {
|
|
4
|
+
maxStrLength: 65_536,
|
|
5
|
+
maxBinLength: 65_536,
|
|
6
|
+
maxArrayLength: 10_000, // READY sends all channels across all servers; 100×50=5000, 2× headroom
|
|
7
|
+
maxMapLength: 500, // largest map is READY d object with nested server/channel/friend objects
|
|
8
|
+
};
|
|
9
|
+
export function encode(frame) {
|
|
10
|
+
return msgpackEncode(frame);
|
|
11
|
+
}
|
|
12
|
+
/** Tighter limits for client-side decoding (browser memory is more constrained). */
|
|
13
|
+
export const CLIENT_DECODE_OPTIONS = {
|
|
14
|
+
maxStrLength: 16_384,
|
|
15
|
+
maxBinLength: 16_384,
|
|
16
|
+
maxArrayLength: 2_000,
|
|
17
|
+
maxMapLength: 200,
|
|
18
|
+
};
|
|
19
|
+
export function decode(data) {
|
|
20
|
+
const result = msgpackDecode(data, DECODE_OPTIONS);
|
|
21
|
+
if (typeof result !== "object" ||
|
|
22
|
+
result === null ||
|
|
23
|
+
!("op" in result) ||
|
|
24
|
+
typeof result.op !== "number" ||
|
|
25
|
+
!("d" in result)) {
|
|
26
|
+
throw new Error("Invalid GatewayFrame: missing op or d");
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
export function decodeClient(data) {
|
|
31
|
+
const result = msgpackDecode(data, CLIENT_DECODE_OPTIONS);
|
|
32
|
+
if (typeof result !== "object" ||
|
|
33
|
+
result === null ||
|
|
34
|
+
!("op" in result) ||
|
|
35
|
+
typeof result.op !== "number" ||
|
|
36
|
+
!("d" in result)) {
|
|
37
|
+
throw new Error("Invalid GatewayFrame: missing op or d");
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,IAAI,aAAa,EACvB,MAAM,IAAI,aAAa,GAExB,MAAM,kBAAkB,CAAC;AAG1B,4EAA4E;AAC5E,MAAM,cAAc,GAAmB;IACrC,YAAY,EAAE,MAAM;IACpB,YAAY,EAAE,MAAM;IACpB,cAAc,EAAE,MAAM,EAAE,wEAAwE;IAChG,YAAY,EAAE,GAAG,EAAE,0EAA0E;CAC9F,CAAC;AAOF,MAAM,UAAU,MAAM,CAAC,KAAmB;IACxC,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,MAAM,qBAAqB,GAAmB;IACnD,YAAY,EAAE,MAAM;IACpB,YAAY,EAAE,MAAM;IACpB,cAAc,EAAE,KAAK;IACrB,YAAY,EAAE,GAAG;CAClB,CAAC;AAEF,MAAM,UAAU,MAAM,CAAC,IAAsC;IAC3D,MAAM,MAAM,GAAG,aAAa,CAAC,IAAkB,EAAE,cAAc,CAAC,CAAC;IACjE,IACE,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,KAAK,IAAI;QACf,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC;QACjB,OAAQ,MAAkC,CAAC,EAAE,KAAK,QAAQ;QAC1D,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,EAChB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAAsB,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAsC;IACjE,MAAM,MAAM,GAAG,aAAa,CAAC,IAAkB,EAAE,qBAAqB,CAAC,CAAC;IACxE,IACE,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,KAAK,IAAI;QACf,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC;QACjB,OAAQ,MAAkC,CAAC,EAAE,KAAK,QAAQ;QAC1D,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,EAChB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAAsB,CAAC;AAChC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Opcode } from "./opcodes.js";
|
|
2
|
+
export { CloseCode } from "./close-codes.js";
|
|
3
|
+
export { encode, decode, decodeClient, CLIENT_DECODE_OPTIONS } from "./codec.js";
|
|
4
|
+
export type { GatewayFrame } from "./codec.js";
|
|
5
|
+
export * from "./branded.js";
|
|
6
|
+
export type { WebRtcSignalPayload, FileShareRequest, FileShareBroadcast, FileAvailabilityPayload, FileSessionCreatePayload, FileSessionInvitePayload, FileSessionJoinPayload, FileSessionJoinAcceptPayload, FileSessionJoinedPayload, FileSessionProgressPayload, FileSessionCompletePayload, FileSessionClosePayload, FileSessionLeavePayload, } from "./signaling.js";
|
|
7
|
+
export * from "./schemas.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,cAAc,cAAc,CAAC;AAC7B,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,4BAA4B,EAC5B,wBAAwB,EACxB,0BAA0B,EAC1B,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AACxB,cAAc,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Opcode } from "./opcodes.js";
|
|
2
|
+
export { CloseCode } from "./close-codes.js";
|
|
3
|
+
export { encode, decode, decodeClient, CLIENT_DECODE_OPTIONS } from "./codec.js";
|
|
4
|
+
export * from "./branded.js";
|
|
5
|
+
export * from "./schemas.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEjF,cAAc,cAAc,CAAC;AAgB7B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export declare enum Opcode {
|
|
2
|
+
/** Server -> Client: heartbeat interval */
|
|
3
|
+
HELLO = 0,
|
|
4
|
+
/** Client -> Server: heartbeat acknowledgement */
|
|
5
|
+
HEARTBEAT = 1,
|
|
6
|
+
/** Client -> Server: session token */
|
|
7
|
+
IDENTIFY = 2,
|
|
8
|
+
/** Server -> Client: user, servers, channels */
|
|
9
|
+
READY = 3,
|
|
10
|
+
/** Server -> Client: heartbeat acknowledged */
|
|
11
|
+
HEARTBEAT_ACK = 4,
|
|
12
|
+
/** Both: new message */
|
|
13
|
+
MESSAGE_CREATE = 10,
|
|
14
|
+
/** Both: edited message */
|
|
15
|
+
MESSAGE_UPDATE = 11,
|
|
16
|
+
/** Both: deleted message */
|
|
17
|
+
MESSAGE_DELETE = 12,
|
|
18
|
+
/** Both: user started typing */
|
|
19
|
+
TYPING_START = 13,
|
|
20
|
+
/** Both: presence change */
|
|
21
|
+
PRESENCE_UPDATE = 20,
|
|
22
|
+
/** Client -> Server: WebRTC SDP offer for P2P connection */
|
|
23
|
+
WEBRTC_OFFER = 30,
|
|
24
|
+
/** Client -> Server: WebRTC SDP answer in response to offer */
|
|
25
|
+
WEBRTC_ANSWER = 31,
|
|
26
|
+
/** Client -> Server: WebRTC ICE candidate for NAT traversal */
|
|
27
|
+
WEBRTC_ICE_CANDIDATE = 32,
|
|
28
|
+
/** Client -> Server: file shared via P2P (stores receipt, broadcasts to channel) */
|
|
29
|
+
FILE_SHARE = 33,
|
|
30
|
+
/** Client -> Server: seeder availability changed for a file */
|
|
31
|
+
FILE_AVAILABILITY_UPDATE = 34,
|
|
32
|
+
/** Server -> Client: channel created */
|
|
33
|
+
CHANNEL_CREATE = 40,
|
|
34
|
+
/** Server -> Client: channel updated */
|
|
35
|
+
CHANNEL_UPDATE = 41,
|
|
36
|
+
/** Server -> Client: channel deleted */
|
|
37
|
+
CHANNEL_DELETE = 42,
|
|
38
|
+
/** Server -> Client: member added */
|
|
39
|
+
MEMBER_ADD = 50,
|
|
40
|
+
/** Server -> Client: member removed */
|
|
41
|
+
MEMBER_REMOVE = 51,
|
|
42
|
+
/** Server -> Client: server created */
|
|
43
|
+
SERVER_CREATE = 60,
|
|
44
|
+
/** Server -> Client: server deleted */
|
|
45
|
+
SERVER_DELETE = 61,
|
|
46
|
+
/** Server -> Client: server updated (name, icon, owner) */
|
|
47
|
+
SERVER_UPDATE = 62,
|
|
48
|
+
/** Server -> Client: friend request received */
|
|
49
|
+
FRIEND_REQUEST = 70,
|
|
50
|
+
/** Server -> Client: friend request accepted */
|
|
51
|
+
FRIEND_ACCEPT = 71,
|
|
52
|
+
/** Server -> Client: friend removed */
|
|
53
|
+
FRIEND_REMOVE = 72,
|
|
54
|
+
/** Server -> Client: DM channel created */
|
|
55
|
+
DM_CHANNEL_CREATE = 80,
|
|
56
|
+
/** Server -> Client: subscription tier was gifted */
|
|
57
|
+
SUBSCRIPTION_GIFT = 85,
|
|
58
|
+
/** Server -> Client: account deletion countdown started */
|
|
59
|
+
ACCOUNT_DELETION_PENDING = 90,
|
|
60
|
+
/** Server -> Client: account deletion was cancelled */
|
|
61
|
+
ACCOUNT_DELETION_CANCELLED = 91,
|
|
62
|
+
/** Server -> Client: error notification (e.g., tier restriction) */
|
|
63
|
+
ERROR = 99,
|
|
64
|
+
/** Sender -> Server: create a share session */
|
|
65
|
+
FILE_SESSION_CREATE = 100,
|
|
66
|
+
/** Server -> Recipients: you've been invited to a share session */
|
|
67
|
+
FILE_SESSION_INVITE = 101,
|
|
68
|
+
/** Recipient -> Server: joining the share session */
|
|
69
|
+
FILE_SESSION_JOIN = 102,
|
|
70
|
+
/** Server -> Sender: a user joined the session */
|
|
71
|
+
FILE_SESSION_JOINED = 103,
|
|
72
|
+
/** Recipient -> Server -> Sender: download progress update */
|
|
73
|
+
FILE_SESSION_PROGRESS = 104,
|
|
74
|
+
/** Recipient -> Server -> Sender: download complete */
|
|
75
|
+
FILE_SESSION_COMPLETE = 105,
|
|
76
|
+
/** Sender -> Server -> All: session ended */
|
|
77
|
+
FILE_SESSION_CLOSE = 106,
|
|
78
|
+
/** Recipient -> Server -> Sender: user left the session */
|
|
79
|
+
FILE_SESSION_LEAVE = 107
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=opcodes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opcodes.d.ts","sourceRoot":"","sources":["../src/opcodes.ts"],"names":[],"mappings":"AAAA,oBAAY,MAAM;IAChB,2CAA2C;IAC3C,KAAK,IAAI;IACT,kDAAkD;IAClD,SAAS,IAAI;IACb,sCAAsC;IACtC,QAAQ,IAAI;IACZ,gDAAgD;IAChD,KAAK,IAAI;IACT,+CAA+C;IAC/C,aAAa,IAAI;IAEjB,wBAAwB;IACxB,cAAc,KAAK;IACnB,2BAA2B;IAC3B,cAAc,KAAK;IACnB,4BAA4B;IAC5B,cAAc,KAAK;IACnB,gCAAgC;IAChC,YAAY,KAAK;IAEjB,4BAA4B;IAC5B,eAAe,KAAK;IAEpB,4DAA4D;IAC5D,YAAY,KAAK;IACjB,+DAA+D;IAC/D,aAAa,KAAK;IAClB,+DAA+D;IAC/D,oBAAoB,KAAK;IACzB,oFAAoF;IACpF,UAAU,KAAK;IACf,+DAA+D;IAC/D,wBAAwB,KAAK;IAE7B,wCAAwC;IACxC,cAAc,KAAK;IACnB,wCAAwC;IACxC,cAAc,KAAK;IACnB,wCAAwC;IACxC,cAAc,KAAK;IAEnB,qCAAqC;IACrC,UAAU,KAAK;IACf,uCAAuC;IACvC,aAAa,KAAK;IAElB,uCAAuC;IACvC,aAAa,KAAK;IAClB,uCAAuC;IACvC,aAAa,KAAK;IAClB,2DAA2D;IAC3D,aAAa,KAAK;IAElB,gDAAgD;IAChD,cAAc,KAAK;IACnB,gDAAgD;IAChD,aAAa,KAAK;IAClB,uCAAuC;IACvC,aAAa,KAAK;IAElB,2CAA2C;IAC3C,iBAAiB,KAAK;IAEtB,qDAAqD;IACrD,iBAAiB,KAAK;IAEtB,2DAA2D;IAC3D,wBAAwB,KAAK;IAC7B,uDAAuD;IACvD,0BAA0B,KAAK;IAE/B,oEAAoE;IACpE,KAAK,KAAK;IAIV,+CAA+C;IAC/C,mBAAmB,MAAM;IACzB,mEAAmE;IACnE,mBAAmB,MAAM;IACzB,qDAAqD;IACrD,iBAAiB,MAAM;IACvB,kDAAkD;IAClD,mBAAmB,MAAM;IACzB,8DAA8D;IAC9D,qBAAqB,MAAM;IAC3B,uDAAuD;IACvD,qBAAqB,MAAM;IAC3B,6CAA6C;IAC7C,kBAAkB,MAAM;IACxB,2DAA2D;IAC3D,kBAAkB,MAAM;CACzB"}
|
package/dist/opcodes.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export var Opcode;
|
|
2
|
+
(function (Opcode) {
|
|
3
|
+
/** Server -> Client: heartbeat interval */
|
|
4
|
+
Opcode[Opcode["HELLO"] = 0] = "HELLO";
|
|
5
|
+
/** Client -> Server: heartbeat acknowledgement */
|
|
6
|
+
Opcode[Opcode["HEARTBEAT"] = 1] = "HEARTBEAT";
|
|
7
|
+
/** Client -> Server: session token */
|
|
8
|
+
Opcode[Opcode["IDENTIFY"] = 2] = "IDENTIFY";
|
|
9
|
+
/** Server -> Client: user, servers, channels */
|
|
10
|
+
Opcode[Opcode["READY"] = 3] = "READY";
|
|
11
|
+
/** Server -> Client: heartbeat acknowledged */
|
|
12
|
+
Opcode[Opcode["HEARTBEAT_ACK"] = 4] = "HEARTBEAT_ACK";
|
|
13
|
+
/** Both: new message */
|
|
14
|
+
Opcode[Opcode["MESSAGE_CREATE"] = 10] = "MESSAGE_CREATE";
|
|
15
|
+
/** Both: edited message */
|
|
16
|
+
Opcode[Opcode["MESSAGE_UPDATE"] = 11] = "MESSAGE_UPDATE";
|
|
17
|
+
/** Both: deleted message */
|
|
18
|
+
Opcode[Opcode["MESSAGE_DELETE"] = 12] = "MESSAGE_DELETE";
|
|
19
|
+
/** Both: user started typing */
|
|
20
|
+
Opcode[Opcode["TYPING_START"] = 13] = "TYPING_START";
|
|
21
|
+
/** Both: presence change */
|
|
22
|
+
Opcode[Opcode["PRESENCE_UPDATE"] = 20] = "PRESENCE_UPDATE";
|
|
23
|
+
/** Client -> Server: WebRTC SDP offer for P2P connection */
|
|
24
|
+
Opcode[Opcode["WEBRTC_OFFER"] = 30] = "WEBRTC_OFFER";
|
|
25
|
+
/** Client -> Server: WebRTC SDP answer in response to offer */
|
|
26
|
+
Opcode[Opcode["WEBRTC_ANSWER"] = 31] = "WEBRTC_ANSWER";
|
|
27
|
+
/** Client -> Server: WebRTC ICE candidate for NAT traversal */
|
|
28
|
+
Opcode[Opcode["WEBRTC_ICE_CANDIDATE"] = 32] = "WEBRTC_ICE_CANDIDATE";
|
|
29
|
+
/** Client -> Server: file shared via P2P (stores receipt, broadcasts to channel) */
|
|
30
|
+
Opcode[Opcode["FILE_SHARE"] = 33] = "FILE_SHARE";
|
|
31
|
+
/** Client -> Server: seeder availability changed for a file */
|
|
32
|
+
Opcode[Opcode["FILE_AVAILABILITY_UPDATE"] = 34] = "FILE_AVAILABILITY_UPDATE";
|
|
33
|
+
/** Server -> Client: channel created */
|
|
34
|
+
Opcode[Opcode["CHANNEL_CREATE"] = 40] = "CHANNEL_CREATE";
|
|
35
|
+
/** Server -> Client: channel updated */
|
|
36
|
+
Opcode[Opcode["CHANNEL_UPDATE"] = 41] = "CHANNEL_UPDATE";
|
|
37
|
+
/** Server -> Client: channel deleted */
|
|
38
|
+
Opcode[Opcode["CHANNEL_DELETE"] = 42] = "CHANNEL_DELETE";
|
|
39
|
+
/** Server -> Client: member added */
|
|
40
|
+
Opcode[Opcode["MEMBER_ADD"] = 50] = "MEMBER_ADD";
|
|
41
|
+
/** Server -> Client: member removed */
|
|
42
|
+
Opcode[Opcode["MEMBER_REMOVE"] = 51] = "MEMBER_REMOVE";
|
|
43
|
+
/** Server -> Client: server created */
|
|
44
|
+
Opcode[Opcode["SERVER_CREATE"] = 60] = "SERVER_CREATE";
|
|
45
|
+
/** Server -> Client: server deleted */
|
|
46
|
+
Opcode[Opcode["SERVER_DELETE"] = 61] = "SERVER_DELETE";
|
|
47
|
+
/** Server -> Client: server updated (name, icon, owner) */
|
|
48
|
+
Opcode[Opcode["SERVER_UPDATE"] = 62] = "SERVER_UPDATE";
|
|
49
|
+
/** Server -> Client: friend request received */
|
|
50
|
+
Opcode[Opcode["FRIEND_REQUEST"] = 70] = "FRIEND_REQUEST";
|
|
51
|
+
/** Server -> Client: friend request accepted */
|
|
52
|
+
Opcode[Opcode["FRIEND_ACCEPT"] = 71] = "FRIEND_ACCEPT";
|
|
53
|
+
/** Server -> Client: friend removed */
|
|
54
|
+
Opcode[Opcode["FRIEND_REMOVE"] = 72] = "FRIEND_REMOVE";
|
|
55
|
+
/** Server -> Client: DM channel created */
|
|
56
|
+
Opcode[Opcode["DM_CHANNEL_CREATE"] = 80] = "DM_CHANNEL_CREATE";
|
|
57
|
+
/** Server -> Client: subscription tier was gifted */
|
|
58
|
+
Opcode[Opcode["SUBSCRIPTION_GIFT"] = 85] = "SUBSCRIPTION_GIFT";
|
|
59
|
+
/** Server -> Client: account deletion countdown started */
|
|
60
|
+
Opcode[Opcode["ACCOUNT_DELETION_PENDING"] = 90] = "ACCOUNT_DELETION_PENDING";
|
|
61
|
+
/** Server -> Client: account deletion was cancelled */
|
|
62
|
+
Opcode[Opcode["ACCOUNT_DELETION_CANCELLED"] = 91] = "ACCOUNT_DELETION_CANCELLED";
|
|
63
|
+
/** Server -> Client: error notification (e.g., tier restriction) */
|
|
64
|
+
Opcode[Opcode["ERROR"] = 99] = "ERROR";
|
|
65
|
+
// ── File Share Sessions (DM P2P) ──────────────────────────────────────────
|
|
66
|
+
/** Sender -> Server: create a share session */
|
|
67
|
+
Opcode[Opcode["FILE_SESSION_CREATE"] = 100] = "FILE_SESSION_CREATE";
|
|
68
|
+
/** Server -> Recipients: you've been invited to a share session */
|
|
69
|
+
Opcode[Opcode["FILE_SESSION_INVITE"] = 101] = "FILE_SESSION_INVITE";
|
|
70
|
+
/** Recipient -> Server: joining the share session */
|
|
71
|
+
Opcode[Opcode["FILE_SESSION_JOIN"] = 102] = "FILE_SESSION_JOIN";
|
|
72
|
+
/** Server -> Sender: a user joined the session */
|
|
73
|
+
Opcode[Opcode["FILE_SESSION_JOINED"] = 103] = "FILE_SESSION_JOINED";
|
|
74
|
+
/** Recipient -> Server -> Sender: download progress update */
|
|
75
|
+
Opcode[Opcode["FILE_SESSION_PROGRESS"] = 104] = "FILE_SESSION_PROGRESS";
|
|
76
|
+
/** Recipient -> Server -> Sender: download complete */
|
|
77
|
+
Opcode[Opcode["FILE_SESSION_COMPLETE"] = 105] = "FILE_SESSION_COMPLETE";
|
|
78
|
+
/** Sender -> Server -> All: session ended */
|
|
79
|
+
Opcode[Opcode["FILE_SESSION_CLOSE"] = 106] = "FILE_SESSION_CLOSE";
|
|
80
|
+
/** Recipient -> Server -> Sender: user left the session */
|
|
81
|
+
Opcode[Opcode["FILE_SESSION_LEAVE"] = 107] = "FILE_SESSION_LEAVE";
|
|
82
|
+
})(Opcode || (Opcode = {}));
|
|
83
|
+
//# sourceMappingURL=opcodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opcodes.js","sourceRoot":"","sources":["../src/opcodes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,MA6FX;AA7FD,WAAY,MAAM;IAChB,2CAA2C;IAC3C,qCAAS,CAAA;IACT,kDAAkD;IAClD,6CAAa,CAAA;IACb,sCAAsC;IACtC,2CAAY,CAAA;IACZ,gDAAgD;IAChD,qCAAS,CAAA;IACT,+CAA+C;IAC/C,qDAAiB,CAAA;IAEjB,wBAAwB;IACxB,wDAAmB,CAAA;IACnB,2BAA2B;IAC3B,wDAAmB,CAAA;IACnB,4BAA4B;IAC5B,wDAAmB,CAAA;IACnB,gCAAgC;IAChC,oDAAiB,CAAA;IAEjB,4BAA4B;IAC5B,0DAAoB,CAAA;IAEpB,4DAA4D;IAC5D,oDAAiB,CAAA;IACjB,+DAA+D;IAC/D,sDAAkB,CAAA;IAClB,+DAA+D;IAC/D,oEAAyB,CAAA;IACzB,oFAAoF;IACpF,gDAAe,CAAA;IACf,+DAA+D;IAC/D,4EAA6B,CAAA;IAE7B,wCAAwC;IACxC,wDAAmB,CAAA;IACnB,wCAAwC;IACxC,wDAAmB,CAAA;IACnB,wCAAwC;IACxC,wDAAmB,CAAA;IAEnB,qCAAqC;IACrC,gDAAe,CAAA;IACf,uCAAuC;IACvC,sDAAkB,CAAA;IAElB,uCAAuC;IACvC,sDAAkB,CAAA;IAClB,uCAAuC;IACvC,sDAAkB,CAAA;IAClB,2DAA2D;IAC3D,sDAAkB,CAAA;IAElB,gDAAgD;IAChD,wDAAmB,CAAA;IACnB,gDAAgD;IAChD,sDAAkB,CAAA;IAClB,uCAAuC;IACvC,sDAAkB,CAAA;IAElB,2CAA2C;IAC3C,8DAAsB,CAAA;IAEtB,qDAAqD;IACrD,8DAAsB,CAAA;IAEtB,2DAA2D;IAC3D,4EAA6B,CAAA;IAC7B,uDAAuD;IACvD,gFAA+B,CAAA;IAE/B,oEAAoE;IACpE,sCAAU,CAAA;IAEV,6EAA6E;IAE7E,+CAA+C;IAC/C,mEAAyB,CAAA;IACzB,mEAAmE;IACnE,mEAAyB,CAAA;IACzB,qDAAqD;IACrD,+DAAuB,CAAA;IACvB,kDAAkD;IAClD,mEAAyB,CAAA;IACzB,8DAA8D;IAC9D,uEAA2B,CAAA;IAC3B,uDAAuD;IACvD,uEAA2B,CAAA;IAC3B,6CAA6C;IAC7C,iEAAwB,CAAA;IACxB,2DAA2D;IAC3D,iEAAwB,CAAA;AAC1B,CAAC,EA7FW,MAAM,KAAN,MAAM,QA6FjB"}
|