sonic-ws 2.0.2 → 2.2.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 -6
- package/bundled/bundle.js +1 -1
- package/bundled/bundle.wasm +0 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +8 -1
- package/dist/native/wasm/node/sonic_ws_core_bg.wasm +0 -0
- package/dist/native/wrapper.d.ts +3 -3
- package/dist/native/wrapper.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/ws/Connection.d.ts +4 -0
- package/dist/ws/Connection.js +1 -1
- package/dist/ws/client/core/ClientCore.d.ts +53 -1
- package/dist/ws/client/core/ClientCore.js +1 -1
- package/dist/ws/client/node/ClientNode.d.ts +7 -2
- package/dist/ws/client/node/ClientNode.js +1 -1
- package/dist/ws/packets/PacketType.d.ts +0 -2
- package/dist/ws/packets/PacketType.js +1 -1
- package/dist/ws/packets/Packets.d.ts +44 -1
- package/dist/ws/packets/Packets.js +1 -1
- package/dist/ws/server/Adapter.d.ts +21 -0
- package/dist/ws/server/Adapter.js +7 -0
- package/dist/ws/server/SonicWSConnection.d.ts +18 -1
- package/dist/ws/server/SonicWSConnection.js +1 -1
- package/dist/ws/server/SonicWSServer.d.ts +45 -2
- package/dist/ws/server/SonicWSServer.js +1 -1
- package/dist/ws/util/packets/BatchHelper.js +1 -1
- package/dist/ws/util/packets/ConstructorRegistry.d.ts +10 -0
- package/dist/ws/util/packets/ConstructorRegistry.js +7 -0
- package/dist/ws/util/packets/ControlProtocol.d.ts +47 -0
- package/dist/ws/util/packets/ControlProtocol.js +7 -0
- package/dist/ws/util/packets/PacketHolder.js +1 -1
- package/dist/ws/util/packets/PacketManifest.d.ts +17 -0
- package/dist/ws/util/packets/PacketManifest.js +7 -0
- package/dist/ws/util/packets/PacketUtils.d.ts +46 -5
- package/dist/ws/util/packets/PacketUtils.js +1 -1
- package/package.json +4 -4
- package/dist/native/wasm/pkg/README.md +0 -6
- package/dist/native/wasm/pkg/package.json +0 -19
- package/dist/native/wasm/pkg/sonic_ws_core.d.ts +0 -51
- package/dist/native/wasm/pkg/sonic_ws_core.js +0 -7
- package/dist/native/wasm/pkg/sonic_ws_core_bg.js +0 -7
- package/dist/native/wasm/pkg/sonic_ws_core_bg.wasm +0 -0
- package/dist/native/wasm/pkg/sonic_ws_core_bg.wasm.d.ts +0 -36
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 Lily (liwybloc)
|
|
3
|
+
* License-Identifier: LicenseRef-Lily-Personal-NonCommercial-2026
|
|
4
|
+
* See LICENSE for personal, non-commercial license terms.
|
|
5
|
+
*/
|
|
6
|
+
export declare const CONTROL_KEY = 0;
|
|
7
|
+
export declare enum ControlType {
|
|
8
|
+
REQUEST = 1,
|
|
9
|
+
RESPONSE = 2,
|
|
10
|
+
REPLAY = 3,
|
|
11
|
+
RESUME = 4,
|
|
12
|
+
RESUMED = 5
|
|
13
|
+
}
|
|
14
|
+
export type ControlRequest = {
|
|
15
|
+
type: ControlType.REQUEST;
|
|
16
|
+
id: number;
|
|
17
|
+
packetKey: number;
|
|
18
|
+
payload: Uint8Array;
|
|
19
|
+
};
|
|
20
|
+
export type ControlResponse = {
|
|
21
|
+
type: ControlType.RESPONSE;
|
|
22
|
+
id: number;
|
|
23
|
+
ok: boolean;
|
|
24
|
+
value: any;
|
|
25
|
+
};
|
|
26
|
+
export type ControlReplay = {
|
|
27
|
+
type: ControlType.REPLAY;
|
|
28
|
+
sequence: number;
|
|
29
|
+
payload: Uint8Array;
|
|
30
|
+
};
|
|
31
|
+
export type ControlResume = {
|
|
32
|
+
type: ControlType.RESUME;
|
|
33
|
+
sessionId: string;
|
|
34
|
+
lastSequence: number;
|
|
35
|
+
};
|
|
36
|
+
export type ControlResumed = {
|
|
37
|
+
type: ControlType.RESUMED;
|
|
38
|
+
recovered: boolean;
|
|
39
|
+
replayed: number;
|
|
40
|
+
};
|
|
41
|
+
export type ControlMessage = ControlRequest | ControlResponse | ControlReplay | ControlResume | ControlResumed;
|
|
42
|
+
export declare function encodeControlRequest(id: number, packetKey: number, payload: Uint8Array): Uint8Array;
|
|
43
|
+
export declare function encodeControlResponse(id: number, ok: boolean, value: any): Uint8Array;
|
|
44
|
+
export declare const encodeReplay: (sequence: number, payload: Uint8Array) => Uint8Array<ArrayBuffer>;
|
|
45
|
+
export declare function encodeResume(sessionId: string, lastSequence: number): Uint8Array;
|
|
46
|
+
export declare const encodeResumed: (recovered: boolean, replayed: number) => Uint8Array<ArrayBuffer>;
|
|
47
|
+
export declare function decodeControl(data: Uint8Array): ControlMessage;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 Lily (liwybloc)
|
|
3
|
+
* License-Identifier: LicenseRef-Lily-Personal-NonCommercial-2026
|
|
4
|
+
* See LICENSE for personal, non-commercial license terms.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.encodeResumed=exports.encodeReplay=exports.ControlType=exports.CONTROL_KEY=void 0,exports.encodeControlRequest=function(r,o,n){return Uint8Array.from([exports.CONTROL_KEY,t.REQUEST,...(0,e.convertVarInt)(r),o,...n])},exports.encodeControlResponse=function(o,n,s){return Uint8Array.from([exports.CONTROL_KEY,t.RESPONSE,...(0,e.convertVarInt)(o),Number(n),...(0,r.compressJSON)(s)])},exports.encodeResume=function(r,o){const n=(new TextEncoder).encode(r);return Uint8Array.from([exports.CONTROL_KEY,t.RESUME,...(0,e.convertVarInt)(n.length),...n,...(0,e.convertVarInt)(o)])},exports.decodeControl=function(o){if(o[0]!==exports.CONTROL_KEY||o.length<3)throw new Error("Invalid SonicWS control frame");const n=o[1];switch(n){case t.REPLAY:{const[r,t]=(0,e.readVarInt)(o,2);return{type:n,sequence:t,payload:o.slice(r)}}case t.RESUME:{const[r,t]=(0,e.readVarInt)(o,2),s=r+t;if(s>o.length)throw new Error("Recovery frame has an invalid session id");const[c,a]=(0,e.readVarInt)(o,s);return{type:n,sessionId:(new TextDecoder).decode(o.slice(r,s)),lastSequence:a}}case t.RESUMED:{if(o.length<4)throw new Error("Invalid recovery result frame");const[r,t]=(0,e.readVarInt)(o,3);return{type:n,recovered:0!==o[2],replayed:t}}case t.REQUEST:{const[r,t]=(0,e.readVarInt)(o,2);if(r>=o.length)throw new Error("RPC request is missing its packet key");return{type:n,id:t,packetKey:o[r],payload:o.slice(r+1)}}case t.RESPONSE:{const[t,s]=(0,e.readVarInt)(o,2);if(t>=o.length)throw new Error("RPC response is missing its status");return{type:n,id:s,ok:0!==o[t],value:(0,r.decompressJSON)(o.slice(t+1))}}default:throw new Error(`Unknown SonicWS control frame type: ${n}`)}};const e=require("./CompressionUtil"),r=require("./JSONUtil");var t;exports.CONTROL_KEY=0,function(e){e[e.REQUEST=1]="REQUEST",e[e.RESPONSE=2]="RESPONSE",e[e.REPLAY=3]="REPLAY",e[e.RESUME=4]="RESUME",e[e.RESUMED=5]="RESUMED"}(t||(exports.ControlType=t={}));exports.encodeReplay=(r,o)=>Uint8Array.from([exports.CONTROL_KEY,t.REPLAY,...(0,e.convertVarInt)(r),...o]);exports.encodeResumed=(r,o)=>Uint8Array.from([exports.CONTROL_KEY,t.RESUMED,Number(r),...(0,e.convertVarInt)(o)]);
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* See LICENSE for personal, non-commercial license terms.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.PacketHolder=void 0;exports.PacketHolder=class{key;keys;tags;packetMap;packets;constructor(t){this.key=1,this.keys={},this.tags={},this.packetMap={},t&&this.holdPackets(t)}createKey(t){this.keys[t]=this.key,this.tags[this.key]=t,this.key++}holdPackets(t){this.packets=t;for(const e of t)this.createKey(e.tag),this.packetMap[e.tag]=e}getKey(t){if(!(t
|
|
7
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.PacketHolder=void 0;exports.PacketHolder=class{key;keys;tags;packetMap;packets;variants={};parents=new Set;constructor(t){this.key=1,this.keys={},this.tags={},this.packetMap={},t&&this.holdPackets(t)}createKey(t){this.keys[t]=this.key,this.tags[this.key]=t,this.key++}holdPackets(t){this.packets=t;for(const e of t)this.createKey(e.tag),this.packetMap[e.tag]=e,e.parent&&e.variant&&(this.variants[`${e.parent}.${e.variant}`]=e.tag,this.parents.add(e.parent)),e.isParent&&this.parents.add(e.tag)}getKey(t){if(!((t=this.resolveTag(t))in this.keys))throw new Error(`Not a valid tag: ${t}`);return this.keys[t]}getTag(t){if(t in this.tags)return this.tags[t]}getPacket(t){if(!((t=this.resolveTag(t))in this.packetMap))throw new Error("Unknown packet tag: "+t);return this.packetMap[t]}hasKey(t){return t in this.tags}hasTag(t){return this.resolveTag(t)in this.keys||this.parents.has(t)}resolveTag(t){return this.variants[t]??t}getVariantTag(t,e){const s=this.variants[`${t}.${e}`];if(!s)throw new Error(`Unknown packet variant: ${t}.${e}`);return s}getKeys(){return this.keys}getTagMap(){return this.tags}getTags(){return Object.values(this.tags)}getPackets(){return this.packets}serialize(){return this.packets.map(t=>t.serialize()).flat()}};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 Lily (liwybloc)
|
|
3
|
+
* License-Identifier: LicenseRef-Lily-Personal-NonCommercial-2026
|
|
4
|
+
* See LICENSE for personal, non-commercial license terms.
|
|
5
|
+
*/
|
|
6
|
+
import { Packet } from "../../packets/Packets";
|
|
7
|
+
export type PacketManifest = {
|
|
8
|
+
clientPackets: readonly Packet<any>[];
|
|
9
|
+
serverPackets: readonly Packet<any>[];
|
|
10
|
+
};
|
|
11
|
+
/** Serializes both directional packet tables into a portable, versioned manifest. */
|
|
12
|
+
export declare function CreatePacketManifest(manifest: PacketManifest): Uint8Array;
|
|
13
|
+
/** Loads a manifest produced by TypeScript or Python for the current protocol version. */
|
|
14
|
+
export declare function LoadPacketManifest(data: Uint8Array): {
|
|
15
|
+
clientPackets: Packet<any>[];
|
|
16
|
+
serverPackets: Packet<any>[];
|
|
17
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 Lily (liwybloc)
|
|
3
|
+
* License-Identifier: LicenseRef-Lily-Personal-NonCommercial-2026
|
|
4
|
+
* See LICENSE for personal, non-commercial license terms.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.CreatePacketManifest=function(t){const i=t.clientPackets.flatMap(e=>e.serialize()),n=t.serverPackets.flatMap(e=>e.serialize());return Uint8Array.from([...a,e.VERSION,...(0,r.convertVarInt)(i.length),...i,...n])},exports.LoadPacketManifest=function(i){if(i.length<6||a.some((e,t)=>i[t]!==e))throw new Error("Invalid SonicWS packet manifest");if(i[4]!==e.VERSION)throw new Error(`Packet manifest protocol mismatch: ${i[4]} != ${e.VERSION}`);const[n,s]=(0,r.readVarInt)(i,5),c=n+s;if(c>i.length)throw new Error("Truncated SonicWS packet manifest");return{clientPackets:t.Packet.deserializeAll(i.slice(n,c),!1),serverPackets:t.Packet.deserializeAll(i.slice(c),!1)}};const e=require("../../../version"),t=require("../../packets/Packets"),r=require("./CompressionUtil"),a=[83,87,83,77];
|
|
@@ -41,6 +41,8 @@ export type SharedPacketSettings = {
|
|
|
41
41
|
async?: boolean;
|
|
42
42
|
/** If this is true, the packet will be Gzip compressed. Defaults to false on all types but JSON. */
|
|
43
43
|
gzipCompression?: boolean;
|
|
44
|
+
/** Retain this server-to-client packet briefly for connection-state recovery. */
|
|
45
|
+
replay?: boolean;
|
|
44
46
|
};
|
|
45
47
|
/** Settings for single-typed packets */
|
|
46
48
|
export type SinglePacketSettings = SharedPacketSettings & {
|
|
@@ -52,6 +54,21 @@ export type SinglePacketSettings = SharedPacketSettings & {
|
|
|
52
54
|
dataMin?: number;
|
|
53
55
|
/** If this is true, it will save the last received of this value, and if no data is sent, it'll re-use the previous value. This is not compatible with dataMin: 0. Defaults to false. */
|
|
54
56
|
rereference?: boolean;
|
|
57
|
+
/** Field names used to map positional values to and from an object. */
|
|
58
|
+
schema?: readonly string[];
|
|
59
|
+
/** Treat one array of records as fixed-width row-major data. Requires schema. */
|
|
60
|
+
autoFlatten?: boolean;
|
|
61
|
+
/** Packet-level numeric quantization. trackError defaults to true and enables per-connection error feedback. */
|
|
62
|
+
quantized?: {
|
|
63
|
+
scale: number;
|
|
64
|
+
trackError?: boolean;
|
|
65
|
+
};
|
|
66
|
+
/** Inclusive application-level numeric minimum. */
|
|
67
|
+
min?: number;
|
|
68
|
+
/** Inclusive application-level numeric maximum. */
|
|
69
|
+
max?: number;
|
|
70
|
+
/** Local class constructed from decoded schema fields. The class name is exchanged; peers must register their own matching class. */
|
|
71
|
+
constructor?: Function;
|
|
55
72
|
};
|
|
56
73
|
/** Settings for multi-typed packets */
|
|
57
74
|
export type MultiPacketSettings = SharedPacketSettings & {
|
|
@@ -63,6 +80,21 @@ export type MultiPacketSettings = SharedPacketSettings & {
|
|
|
63
80
|
dataMins?: number[] | number;
|
|
64
81
|
/** Will automatically run FlattenData() and UnFlattenData() on values; this will optimize [[x,y,z],[x,y,z]...] for wire transfer */
|
|
65
82
|
autoFlatten?: boolean;
|
|
83
|
+
/** Field names for records transposed into object-packet columns. */
|
|
84
|
+
schema?: readonly string[];
|
|
85
|
+
/** Column-major repeated-record mapping. autoFlatten remains a deprecated alias. */
|
|
86
|
+
autoTranspose?: boolean;
|
|
87
|
+
/** Local class constructed for every decoded schema record. */
|
|
88
|
+
constructor?: Function;
|
|
89
|
+
};
|
|
90
|
+
export type PacketGroupSettings = {
|
|
91
|
+
tag: string;
|
|
92
|
+
variants: Record<string, Omit<SinglePacketSettings, "tag">>;
|
|
93
|
+
};
|
|
94
|
+
type GroupMetadata = {
|
|
95
|
+
parent: string;
|
|
96
|
+
variant: string;
|
|
97
|
+
isParent: boolean;
|
|
66
98
|
};
|
|
67
99
|
/** Settings for single-typed enum packets */
|
|
68
100
|
export type EnumPacketSettings = SharedPacketSettings & {
|
|
@@ -73,10 +105,6 @@ export type EnumPacketSettings = SharedPacketSettings & {
|
|
|
73
105
|
/** The minimum amount of values that can be sent through this packet; defaults to the max */
|
|
74
106
|
dataMin?: number;
|
|
75
107
|
};
|
|
76
|
-
export type KeyEffectivePacketSettings = SharedPacketSettings & {
|
|
77
|
-
/** Amount of keys to consume in order to have differing values; defaults to 2. Must be 2+ */
|
|
78
|
-
count?: number;
|
|
79
|
-
};
|
|
80
108
|
/**
|
|
81
109
|
* Creates a structure for a simple single-typed packet.
|
|
82
110
|
* This packet can be sent and received with the specified tag, type, and data cap.
|
|
@@ -86,6 +114,7 @@ export type KeyEffectivePacketSettings = SharedPacketSettings & {
|
|
|
86
114
|
*/
|
|
87
115
|
export declare function CreatePacket<T extends ArguableType>(settings: SinglePacketSettings & {
|
|
88
116
|
type?: T;
|
|
117
|
+
_group?: GroupMetadata;
|
|
89
118
|
}): Packet<ConvertType<T>>;
|
|
90
119
|
/**
|
|
91
120
|
* Creates a structure for an object (multi-typed) packet.
|
|
@@ -99,6 +128,18 @@ export declare function CreateObjPacket<T extends readonly ArguableType[], V ext
|
|
|
99
128
|
}>(settings: MultiPacketSettings & {
|
|
100
129
|
readonly types: T;
|
|
101
130
|
}): Packet<V>;
|
|
131
|
+
/**
|
|
132
|
+
* Creates a parent packet and its named variants as ordinary packet definitions.
|
|
133
|
+
*
|
|
134
|
+
* A group named `movement` with `look`, `move`, and `both` variants returns four
|
|
135
|
+
* packets: `movement` (`PacketType.NONE`), `movement.look`, `movement.move`, and
|
|
136
|
+
* `movement.both`. Spread the returned array into `clientPackets` or
|
|
137
|
+
* `serverPackets`. Send a child with `sendVariant("movement", "move", value)`;
|
|
138
|
+
* listeners on `movement.move` receive the child payload, while listeners on
|
|
139
|
+
* `movement` also receive `{ variant: "move", payload }`. Sending `movement`
|
|
140
|
+
* directly represents the parent/empty variant (`variant: ""`).
|
|
141
|
+
*/
|
|
142
|
+
export declare function CreatePacketGroup(settings: PacketGroupSettings): Packet<any>[];
|
|
102
143
|
/**
|
|
103
144
|
* Creates and defines an enum packet. This can be used to create an enum-based packet
|
|
104
145
|
* with a specific tag and possible values.
|
|
@@ -106,7 +147,6 @@ export declare function CreateObjPacket<T extends readonly ArguableType[], V ext
|
|
|
106
147
|
* @returns The constructed packet structure data.
|
|
107
148
|
*/
|
|
108
149
|
export declare function CreateEnumPacket(settings: EnumPacketSettings): Packet<PacketType.ENUMS>;
|
|
109
|
-
export declare function CreateKeyEffective(settings: KeyEffectivePacketSettings): Packet<PacketType.KEY_EFFECTIVE>;
|
|
110
150
|
/**
|
|
111
151
|
* Flattens a 2-depth array for efficient wire transfer
|
|
112
152
|
* Turns [[x,y,z],[x,y,z]...] to [[x,x...],[y,y...],[z,z...]]
|
|
@@ -119,3 +159,4 @@ export declare function FlattenData(arr: any[][]): any[][];
|
|
|
119
159
|
* @param array A flattened array
|
|
120
160
|
*/
|
|
121
161
|
export declare function UnFlattenData(arr: any[][]): any[][];
|
|
162
|
+
export {};
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* See LICENSE for personal, non-commercial license terms.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
Object.defineProperty(exports,"__esModule",{value:!0}),exports.processPacket=
|
|
7
|
+
Object.defineProperty(exports,"__esModule",{value:!0}),exports.processPacket=i,exports.listenPacket=async function(e,t,a){if("string"==typeof e)return a(e);const[r,n]=e;try{if(n&&Array.isArray(r))for(const e of t)await e(...r);else for(const e of t)await e(r)}catch(e){console.error(e),a(e)}},exports.CreatePacket=p,exports.CreateObjPacket=function(a){const r=Object.prototype.hasOwnProperty.call(a,"constructor")?a.constructor:void 0;let{tag:n,types:i=[],dataMaxes:p,dataMins:m,noDataRange:w=!1,dontSpread:d=!1,autoFlatten:y=!1,autoTranspose:g,schema:k,validator:P=null,dataBatching:E=0,maxBatchSize:v=10,rateLimit:S=0,enabled:T=!0,async:$=!1,gzipCompression:b=i&&i.includes(t.PacketType.JSON)}=a;if(!n)throw new Error("Tag not selected!");if(!i||0==i.length)throw new Error("Types is set to 0 length");if(a.replay&&E)throw new Error(`Packet "${n}" cannot combine replay with batching`);if(f(k,n),r&&!k)throw new Error(`Packet "${n}" constructor requires schema`);r&&(0,o.RegisterPacketConstructor)(r);if(k&&k.length!==i.length)throw new Error(`Packet "${n}" schema length must match types length`);if(void 0!==g&&y&&g!==y)throw new Error(`Packet "${n}" has conflicting autoFlatten and autoTranspose options`);const x=g??y;for(const e of i)if(c(e))throw new Error(`Invalid packet type in "${n}" packet: ${e}`);w?(p=Array.from({length:i.length}).map(()=>s),m=Array.from({length:i.length}).map(()=>0)):(null==p?p=Array.from({length:i.length}).map(()=>1):Array.isArray(p)||(p=Array.from({length:i.length}).map(()=>p)),null==m?m=Array.from({length:i.length}).map((e,t)=>p[t]):Array.isArray(m)||(m=Array.from({length:i.length}).map(()=>m)));const A=p.map(l),M=m.map((e,a)=>i[a]==t.PacketType.NONE?0:u(e,A[a])),O=new e.PacketSchema(!0,i,$,M,A,h(S),d,x,!1,E,v,b,k,void 0,void 0,void 0,void 0,r?.name,a.replay??!1);return new e.Packet(n,O,P,T,!1)},exports.CreatePacketGroup=function(e){if(!e.tag||e.tag.includes("$"))throw new Error("Packet group tag is required and cannot contain '$'");const a=Object.entries(e.variants);if(!a.length)throw new Error(`Packet group "${e.tag}" requires at least one variant`);const r=p({tag:e.tag,type:t.PacketType.NONE,dataMin:0,dataMax:0,_group:{parent:e.tag,variant:"",isParent:!0}}),n=a.map(([t,a])=>{if(!t||t.includes("$"))throw new Error("Packet variant names cannot be empty or contain '$'");return p({...a,tag:`${e.tag}.${t}`,_group:{parent:e.tag,variant:t,isParent:!1}})});return[r,...n]},exports.CreateEnumPacket=function(e){const{tag:t,enumData:a,dataMax:r=1,dataMin:n=0,noDataRange:o=!1,dontSpread:i=!1,validator:c=null,dataBatching:s=0,maxBatchSize:l=10,rateLimit:u=0,enabled:h=!0,async:f=!1}=e;return p({tag:t,type:a,dataMax:r,dataMin:n,noDataRange:o,dontSpread:i,validator:c,dataBatching:s,maxBatchSize:l,rateLimit:u,enabled:h,async:f})},exports.FlattenData=w,exports.UnFlattenData=function(e){return e[0]?.map((t,a)=>e.map(e=>e[a]))??[]};const e=require("../../packets/Packets"),t=require("../../packets/PacketType"),a=require("../enums/EnumType"),r=require("./CompressionUtil"),n=require("./HashUtil"),o=require("./ConstructorRegistry");async function i(e,a,o,c,s,l=!1){const u=e.getKey(a),h=e.getPacket(a);return async function(e,t,a,r,n,o,c){if(e[0]&&!o)return new Promise(t=>e[1].push([t,r,n]));e[0]=!0;const s=await c();if(e[1].length>0){const[r,n,o]=e[1].shift();queueMicrotask(async()=>{r(await i(t,n,o,e,a,!0))})}else e[0]=!1;return s}(c,e,s,a,o,l,async()=>{if(h.rereference){if(-1===s)throw new Error("Cannot send a re-referenced packet from the server-wide sender!");const e=(0,n.hashValue)(o);if(h.lastSent[s]===e)return[u,r.EMPTY_UINT8,h];h.lastSent[s]=e}if(o=h.prepareSend(o,s),h.autoFlatten&&h.object&&!h.fields)o=w(o[0]);else{if(o.length>h.maxSize)throw new Error(`Packet "${a}" only allows ${h.maxSize} values!`);if(o.length<h.minSize)throw new Error(`Packet "${a}" requires at least ${h.minSize} values!`)}if(h.object){if(o=o.map(e=>Array.isArray(e)?e:[e]),!h.autoFlatten){const e=h.dataMin,t=h.dataMax;for(let r=0;r<e.length;r++){if(o[r].length<e[r])throw new Error(`Section ${r+1} of packet "${a}" requires at least ${e[r]} values!`);if(o[r].length>t[r])throw new Error(`Section ${r+1} of packet "${a}" only allows ${t[r]} values!`)}}}else if(h.type!==t.PacketType.JSON){const e=o.find(e=>"object"==typeof e&&null!=e);e&&console.warn(`Passing an array will result in undefined behavior (${JSON.stringify(e)}). Spread the array with ...arr`)}const e=o.length>0?await h.processSend(o):r.EMPTY_UINT8;return[u,e,h]})}function c(e){return!("number"==typeof e&&e in t.PacketType||e instanceof a.EnumPackage)}const s=2048383;function l(e){return e<0?(console.warn("Having a data maximum below 0 does not do anything!"),0):e>s?(console.warn(`Only ${s} values can be sent on a type! Uhh make an issue if you want to send more.`),s):e}function u(e,t){return e<0?(console.warn("Having a data minimum below 0 does not do anything!"),0):e>t?(console.warn("Data minimum can not be higher than the data maximum!"),t):e}function h(e){if(!Number.isFinite(e)||e<0)throw new Error("Rate limit must be a non-negative finite number");return(e=Math.floor(e))>r.MAX_USHORT?(console.warn(`A rate limit above ${r.MAX_USHORT} is considered infinite.`),0):e}function p(a){const r=!0===a.autoFlatten&&void 0===a.dataMax&&void 0===a.dataMin,n=Object.prototype.hasOwnProperty.call(a,"constructor")?a.constructor:void 0;let{tag:i,type:p=t.PacketType.NONE,dataMax:w=1,dataMin:d,noDataRange:y=!1,dontSpread:g=!1,validator:k=null,dataBatching:P=0,maxBatchSize:E=10,rateLimit:v=0,enabled:S=!0,async:T=!1,gzipCompression:$=p==t.PacketType.JSON,rereference:b=!1,schema:x,autoFlatten:A=!1,quantized:M,min:O,max:q}=a;if(!i)throw new Error("Tag not selected!");if(y||r?(d=b?1:0,w=s):null==d&&(d=p==t.PacketType.NONE?0:w),b&&0==d)throw new Error("Rereference cannot be true if the dataMin is 0");if(a.replay&&P)throw new Error(`Packet "${i}" cannot combine replay with batching`);if(c(p))throw new Error(`Invalid packet type: ${p}`);if(f(x,i),n&&!x)throw new Error(`Packet "${i}" constructor requires schema`);if(n&&(0,o.RegisterPacketConstructor)(n),A&&(!x||0===x.length))throw new Error(`Packet "${i}" autoFlatten requires schema`);if(x&&!A&&d===w&&x.length!==w)throw new Error(`Packet "${i}" schema length must match its fixed value count (${w})`);!function(e,t,a,r,n){if(void 0!==a&&void 0!==r&&a>r)throw new Error(`Packet "${n}" min cannot exceed max`);if((t||void 0!==a||void 0!==r)&&!m.has(e))throw new Error(`Packet "${n}" numeric options require a numeric packet type`);if(t&&(!Number.isFinite(t.scale)||t.scale<=0))throw new Error(`Packet "${n}" quantization scale must be positive and finite`)}(p,M,O,q,i);const N=new e.PacketSchema(!1,p,T,u(d,w),l(w),h(v),g,A,b,P,E,$,x,M,O,q,a._group,n?.name,a.replay??!1);return new e.Packet(i,N,k,S,!1)}function f(e,t){if(e){if(!e.length||e.some(e=>"string"!=typeof e||!e))throw new Error(`Packet "${t}" schema must contain non-empty field names`);if(new Set(e).size!==e.length)throw new Error(`Packet "${t}" schema fields must be unique`)}}const m=new Set([t.PacketType.BYTES,t.PacketType.UBYTES,t.PacketType.SHORTS,t.PacketType.USHORTS,t.PacketType.VARINT,t.PacketType.UVARINT,t.PacketType.DELTAS,t.PacketType.FLOATS,t.PacketType.DOUBLES]);function w(e){if(null==e)return[];const t=e[0];if(null==t)return[];if(!Array.isArray(t))throw new Error(`Cannot flatten array: ${e}`);return t.map((t,a)=>e.map(e=>e[a]))??[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonic-ws",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Ultra-lightweight, high-performance, and bandwidth efficient websocket library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"build_wasm_node": "wasm-pack build --release --target nodejs --out-dir ../ts/src/native/wasm/node --out-name sonic_ws_core ../core --features wasm --no-default-features",
|
|
19
19
|
"build_wasm": "npm run build_wasm_browser && npm run build_wasm_node",
|
|
20
20
|
"build_web": "npm run build_wasm_browser && tsc --moduleResolution nodenext --module nodenext --outDir ./dist src/ws/client/browser/ClientBrowser.ts && cpy \"src/native/wasm/pkg/*\" dist/native/wasm/pkg --flat && rimraf ./dist/native/wasm/pkg/.gitignore && npm run webpack && node package-files.mjs",
|
|
21
|
-
"build_node": "npm run
|
|
22
|
-
"build": "npm run build_node && npm run build_web && rimraf ./dist/ws/client/browser && rimraf ./dist/ws/debug/DebugClient.d.ts && rimraf ./dist/ws/debug/DebugClient.js && node minify.mjs && node package-files.mjs",
|
|
21
|
+
"build_node": "npm run build_wasm_node && rimraf ./dist && tsc -d && cpy \"src/native/wasm/node/*\" dist/native/wasm/node --flat && rimraf ./dist/native/wasm/node/.gitignore",
|
|
22
|
+
"build": "npm run build_node && npm run build_web && rimraf ./dist/native/wasm/pkg ./dist/ws/client/browser && rimraf ./dist/ws/debug/DebugClient.d.ts && rimraf ./dist/ws/debug/DebugClient.js && node minify.mjs && node package-files.mjs",
|
|
23
23
|
|
|
24
24
|
"test_web": "npm run build && node tests/test_web.mjs",
|
|
25
|
-
"test_node": "npm
|
|
25
|
+
"test_node": "npm run build_node && node tests/test_node.mjs",
|
|
26
26
|
"prepack": "npm run build",
|
|
27
27
|
|
|
28
28
|
"stage_package": "node package-files.mjs",
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "sonic-ws-core",
|
|
3
|
-
"type": "module",
|
|
4
|
-
"description": "Language-neutral SonicWS packet codec core",
|
|
5
|
-
"version": "0.1.0",
|
|
6
|
-
"license": "LicenseRef-Lily-Personal-NonCommercial-2026",
|
|
7
|
-
"files": [
|
|
8
|
-
"sonic_ws_core_bg.wasm",
|
|
9
|
-
"sonic_ws_core.js",
|
|
10
|
-
"sonic_ws_core_bg.js",
|
|
11
|
-
"sonic_ws_core.d.ts"
|
|
12
|
-
],
|
|
13
|
-
"main": "sonic_ws_core.js",
|
|
14
|
-
"types": "sonic_ws_core.d.ts",
|
|
15
|
-
"sideEffects": [
|
|
16
|
-
"./sonic_ws_core.js",
|
|
17
|
-
"./snippets/*"
|
|
18
|
-
]
|
|
19
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2026 Lily (liwybloc)
|
|
3
|
-
* License-Identifier: LicenseRef-Lily-Personal-NonCommercial-2026
|
|
4
|
-
* See LICENSE for personal, non-commercial license terms.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export function decodeBatch(data: Uint8Array, compressed: boolean, max: number, max_output_size?: number | null): Array<any>;
|
|
10
|
-
|
|
11
|
-
export function decodeBooleans(data: Uint8Array, count: number): Array<any>;
|
|
12
|
-
|
|
13
|
-
export function decodeFloats(value: number, data: Uint8Array): Array<any>;
|
|
14
|
-
|
|
15
|
-
export function decodeHex(data: Uint8Array): string;
|
|
16
|
-
|
|
17
|
-
export function decodeRaw(data: Uint8Array): Uint8Array;
|
|
18
|
-
|
|
19
|
-
export function decodeSigned(value: number, data: Uint8Array): Array<any>;
|
|
20
|
-
|
|
21
|
-
export function decodeStrings(value: number, data: Uint8Array): Array<any>;
|
|
22
|
-
|
|
23
|
-
export function decodeUnsigned(value: number, data: Uint8Array): Array<any>;
|
|
24
|
-
|
|
25
|
-
export function deflateRaw(data: Uint8Array): Uint8Array;
|
|
26
|
-
|
|
27
|
-
export function encodeBatch(values: Array<any>, compressed: boolean): Uint8Array;
|
|
28
|
-
|
|
29
|
-
export function encodeBooleans(values: Array<any>): Uint8Array;
|
|
30
|
-
|
|
31
|
-
export function encodeFloats(value: number, values: Array<any>): Uint8Array;
|
|
32
|
-
|
|
33
|
-
export function encodeHex(value: string): Uint8Array;
|
|
34
|
-
|
|
35
|
-
export function encodeSigned(value: number, values: Array<any>): Uint8Array;
|
|
36
|
-
|
|
37
|
-
export function encodeStrings(value: number, values: Array<any>): Uint8Array;
|
|
38
|
-
|
|
39
|
-
export function encodeUnsigned(value: number, values: Array<any>): Uint8Array;
|
|
40
|
-
|
|
41
|
-
export function frameObject(sectors: Array<any>): Uint8Array;
|
|
42
|
-
|
|
43
|
-
export function inflateRaw(data: Uint8Array, max_output_size?: number | null): Uint8Array;
|
|
44
|
-
|
|
45
|
-
export function unframeObject(data: Uint8Array, count: number): Array<any>;
|
|
46
|
-
|
|
47
|
-
export function validateEncoded(value: number, data: Uint8Array, min: number, max: number, compressed: boolean, batched: boolean, max_batch?: number | null): void;
|
|
48
|
-
|
|
49
|
-
export function validateEnum(data: Uint8Array, size: number, min: number, max: number): void;
|
|
50
|
-
|
|
51
|
-
export function validateObject(data: Uint8Array, kinds: Array<any>, mins: Array<any>, maxes: Array<any>, enum_sizes: Array<any>): void;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2026 Lily (liwybloc)
|
|
3
|
-
* License-Identifier: LicenseRef-Lily-Personal-NonCommercial-2026
|
|
4
|
-
* See LICENSE for personal, non-commercial license terms.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import*as e from"./sonic_ws_core_bg.wasm";import{__wbg_set_wasm as d}from"./sonic_ws_core_bg.js";d(e),e.__wbindgen_start();export{decodeBatch,decodeBooleans,decodeFloats,decodeHex,decodeRaw,decodeSigned,decodeStrings,decodeUnsigned,deflateRaw,encodeBatch,encodeBooleans,encodeFloats,encodeHex,encodeSigned,encodeStrings,encodeUnsigned,frameObject,inflateRaw,unframeObject,validateEncoded,validateEnum,validateObject}from"./sonic_ws_core_bg.js";
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2026 Lily (liwybloc)
|
|
3
|
-
* License-Identifier: LicenseRef-Lily-Personal-NonCommercial-2026
|
|
4
|
-
* See LICENSE for personal, non-commercial license terms.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export function decodeBatch(e,n,t,o){const r=l.decodeBatch(e,n,t,i(o)?Number.MAX_SAFE_INTEGER:o>>>0);if(r[2])throw f(r[1]);return f(r[0])}export function decodeBooleans(e,n){const t=l.decodeBooleans(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function decodeFloats(e,n){const t=l.decodeFloats(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function decodeHex(e){let n,t;try{const i=l.decodeHex(e);var r=i[0],c=i[1];if(i[3])throw r=0,c=0,f(i[2]);return n=r,t=c,o(r,c)}finally{l.__wbindgen_free(n,t,1)}}export function decodeRaw(e){const n=l.decodeRaw(e);if(n[2])throw f(n[1]);return f(n[0])}export function decodeSigned(e,n){const t=l.decodeSigned(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function decodeStrings(e,n){const t=l.decodeStrings(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function decodeUnsigned(e,n){const t=l.decodeUnsigned(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function deflateRaw(e){const n=l.deflateRaw(e);if(n[2])throw f(n[1]);return f(n[0])}export function encodeBatch(e,n){const t=l.encodeBatch(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function encodeBooleans(e){const n=l.encodeBooleans(e);if(n[2])throw f(n[1]);return f(n[0])}export function encodeFloats(e,n){const t=l.encodeFloats(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function encodeHex(e){const n=d(e,l.__wbindgen_malloc,l.__wbindgen_realloc),t=w,o=l.encodeHex(n,t);if(o[2])throw f(o[1]);return f(o[0])}export function encodeSigned(e,n){const t=l.encodeSigned(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function encodeStrings(e,n){const t=l.encodeStrings(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function encodeUnsigned(e,n){const t=l.encodeUnsigned(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function frameObject(e){const n=l.frameObject(e);if(n[2])throw f(n[1]);return f(n[0])}export function inflateRaw(e,n){const t=l.inflateRaw(e,i(n)?Number.MAX_SAFE_INTEGER:n>>>0);if(t[2])throw f(t[1]);return f(t[0])}export function unframeObject(e,n){const t=l.unframeObject(e,n);if(t[2])throw f(t[1]);return f(t[0])}export function validateEncoded(e,n,t,o,r,c,d){const u=l.validateEncoded(e,n,t,o,r,c,i(d)?Number.MAX_SAFE_INTEGER:d>>>0);if(u[1])throw f(u[0])}export function validateEnum(e,n,t,o){const r=l.validateEnum(e,n,t,o);if(r[1])throw f(r[0])}export function validateObject(e,n,t,o,r){const c=l.validateObject(e,n,t,o,r);if(c[1])throw f(c[0])}export function __wbg___wbindgen_boolean_get_fa956cfa2d1bd751(e){const n="boolean"==typeof e?e:void 0;return i(n)?16777215:n?1:0}export function __wbg___wbindgen_number_get_394265ed1e1b84ee(e,n){const o="number"==typeof n?n:void 0;t().setFloat64(e+8,i(o)?0:o,!0),t().setInt32(e+0,!i(o),!0)}export function __wbg___wbindgen_string_get_b0ca35b86a603356(e,n){const o="string"==typeof n?n:void 0;var r=i(o)?0:d(o,l.__wbindgen_malloc,l.__wbindgen_realloc),c=w;t().setInt32(e+4,c,!0),t().setInt32(e+0,r,!0)}export function __wbg___wbindgen_throw_344f42d3211c4765(e,n){throw new Error(o(e,n))}export function __wbg_get_unchecked_6e0ad6d2a41b06f6(e,n){return e[n>>>0]}export function __wbg_length_1f0964f4a5e2c6d8(e){return e.length}export function __wbg_length_370319915dc99107(e){return e.length}export function __wbg_new_32b398fb48b6d94a(){return new Array}export function __wbg_new_cd45aabdf6073e84(e){return new Uint8Array(e)}export function __wbg_new_from_slice_77cdfb7977362f3c(n,t){return new Uint8Array(e(n,t))}export function __wbg_prototypesetcall_4770620bbe4688a0(n,t,o){Uint8Array.prototype.set.call(e(n,t),o)}export function __wbg_push_d2ae3af0c1217ae6(e,n){return e.push(n)}export function __wbindgen_cast_0000000000000001(e){return e}export function __wbindgen_cast_0000000000000002(e,n){return o(e,n)}export function __wbindgen_init_externref_table(){const e=l.__wbindgen_externrefs,n=e.grow(4);e.set(0,void 0),e.set(n+0,void 0),e.set(n+1,null),e.set(n+2,!0),e.set(n+3,!1)}function e(e,n){return e>>>=0,c().subarray(e/1,e/1+n)}let n=null;function t(){return(null===n||!0===n.buffer.detached||void 0===n.buffer.detached&&n.buffer!==l.memory.buffer)&&(n=new DataView(l.memory.buffer)),n}function o(e,n){return function(e,n){a+=n,a>=_&&(u=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),u.decode(),a=n);return u.decode(c().subarray(e,e+n))}(e>>>0,n)}let r=null;function c(){return null!==r&&0!==r.byteLength||(r=new Uint8Array(l.memory.buffer)),r}function i(e){return null==e}function d(e,n,t){if(void 0===t){const t=s.encode(e),o=n(t.length,1)>>>0;return c().subarray(o,o+t.length).set(t),w=t.length,o}let o=e.length,r=n(o,1)>>>0;const i=c();let d=0;for(;d<o;d++){const n=e.charCodeAt(d);if(n>127)break;i[r+d]=n}if(d!==o){0!==d&&(e=e.slice(d)),r=t(r,o,o=d+3*e.length,1)>>>0;const n=c().subarray(r+d,r+o);d+=s.encodeInto(e,n).written,r=t(r,o,d,1)>>>0}return w=d,r}function f(e){const n=l.__wbindgen_externrefs.get(e);return l.__externref_table_dealloc(e),n}let u=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});u.decode();const _=2146435072;let a=0;const s=new TextEncoder;"encodeInto"in s||(s.encodeInto=function(e,n){const t=s.encode(e);return n.set(t),{read:e.length,written:t.length}});let l,w=0;export function __wbg_set_wasm(e){l=e}
|
|
Binary file
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2026 Lily (liwybloc)
|
|
3
|
-
* License-Identifier: LicenseRef-Lily-Personal-NonCommercial-2026
|
|
4
|
-
* See LICENSE for personal, non-commercial license terms.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export const memory: WebAssembly.Memory;
|
|
9
|
-
export const decodeBatch: (a: any, b: number, c: number, d: number) => [number, number, number];
|
|
10
|
-
export const decodeBooleans: (a: any, b: number) => [number, number, number];
|
|
11
|
-
export const decodeFloats: (a: number, b: any) => [number, number, number];
|
|
12
|
-
export const decodeHex: (a: any) => [number, number, number, number];
|
|
13
|
-
export const decodeRaw: (a: any) => [number, number, number];
|
|
14
|
-
export const decodeSigned: (a: number, b: any) => [number, number, number];
|
|
15
|
-
export const decodeStrings: (a: number, b: any) => [number, number, number];
|
|
16
|
-
export const decodeUnsigned: (a: number, b: any) => [number, number, number];
|
|
17
|
-
export const deflateRaw: (a: any) => [number, number, number];
|
|
18
|
-
export const encodeBatch: (a: any, b: number) => [number, number, number];
|
|
19
|
-
export const encodeBooleans: (a: any) => [number, number, number];
|
|
20
|
-
export const encodeFloats: (a: number, b: any) => [number, number, number];
|
|
21
|
-
export const encodeHex: (a: number, b: number) => [number, number, number];
|
|
22
|
-
export const encodeSigned: (a: number, b: any) => [number, number, number];
|
|
23
|
-
export const encodeStrings: (a: number, b: any) => [number, number, number];
|
|
24
|
-
export const encodeUnsigned: (a: number, b: any) => [number, number, number];
|
|
25
|
-
export const frameObject: (a: any) => [number, number, number];
|
|
26
|
-
export const inflateRaw: (a: any, b: number) => [number, number, number];
|
|
27
|
-
export const unframeObject: (a: any, b: number) => [number, number, number];
|
|
28
|
-
export const validateEncoded: (a: number, b: any, c: number, d: number, e: number, f: number, g: number) => [number, number];
|
|
29
|
-
export const validateEnum: (a: any, b: number, c: number, d: number) => [number, number];
|
|
30
|
-
export const validateObject: (a: any, b: any, c: any, d: any, e: any) => [number, number];
|
|
31
|
-
export const __wbindgen_malloc: (a: number, b: number) => number;
|
|
32
|
-
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
33
|
-
export const __wbindgen_externrefs: WebAssembly.Table;
|
|
34
|
-
export const __externref_table_dealloc: (a: number) => void;
|
|
35
|
-
export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
36
|
-
export const __wbindgen_start: () => void;
|