sonic-ws 1.3.1 → 1.3.2

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.
@@ -2,91 +2,5 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- "use strict";
6
5
 
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.PacketHolder = void 0;
9
-
10
- class PacketHolder {
11
-
12
- key;
13
-
14
- keys;
15
-
16
- tags;
17
-
18
- packetMap;
19
-
20
- packets;
21
-
22
- constructor(packets) {
23
-
24
-
25
- this.key = 1;
26
- this.keys = {};
27
- this.tags = {};
28
- this.packetMap = {};
29
- if (!packets)
30
- return;
31
- this.holdPackets(packets);
32
- }
33
-
34
- createKey(tag) {
35
- this.keys[tag] = this.key;
36
- this.tags[this.key] = tag;
37
- this.key++;
38
- }
39
-
40
- holdPackets(packets) {
41
- this.packets = packets;
42
- for (const packet of packets)
43
- this.createKey(packet.tag), this.packetMap[packet.tag] = packet;
44
- }
45
-
46
- getKey(tag) {
47
- if (!(tag in this.keys))
48
- throw new Error(`Not a valid tag: ${tag}`);
49
- return this.keys[tag];
50
- }
51
-
52
- getTag(key) {
53
- if (!(key in this.tags))
54
- return undefined;
55
- return this.tags[key];
56
- }
57
-
58
- getPacket(tag) {
59
- if (!(tag in this.packetMap))
60
- throw new Error("Unknown packet tag: " + tag);
61
- return this.packetMap[tag];
62
- }
63
-
64
- hasKey(key) {
65
- return key in this.tags;
66
- }
67
-
68
- hasTag(tag) {
69
- return tag in this.keys;
70
- }
71
-
72
- getKeys() {
73
- return this.keys;
74
- }
75
-
76
- getTagMap() {
77
- return this.tags;
78
- }
79
-
80
- getTags() {
81
- return Object.values(this.tags);
82
- }
83
-
84
- getPackets() {
85
- return this.packets;
86
- }
87
-
88
- serialize() {
89
- return this.packets.map(p => p.serialize()).flat();
90
- }
91
- }
92
- exports.PacketHolder = PacketHolder;
6
+ 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 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 in this.packetMap))throw new Error("Unknown packet tag: "+t);return this.packetMap[t]}hasKey(t){return t in this.tags}hasTag(t){return t in this.keys}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()}};
@@ -2,228 +2,5 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- "use strict";
6
5
 
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.processPacket = processPacket;
9
- exports.listenPacket = listenPacket;
10
- exports.CreatePacket = CreatePacket;
11
- exports.CreateObjPacket = CreateObjPacket;
12
- exports.CreateEnumPacket = CreateEnumPacket;
13
- exports.CreateKeyEffective = CreateKeyEffective;
14
- exports.FlattenData = FlattenData;
15
- exports.UnFlattenData = UnFlattenData;
16
- const Packets_1 = require("../../packets/Packets");
17
- const PacketType_1 = require("../../packets/PacketType");
18
- const EnumType_1 = require("../enums/EnumType");
19
- const CompressionUtil_1 = require("./CompressionUtil");
20
- const HashUtil_1 = require("./HashUtil");
21
-
22
- async function processPacket(packets, tag, values, sendQueue, id, force = false) {
23
- const code = packets.getKey(tag);
24
- const packet = packets.getPacket(tag);
25
- return handleQueue(sendQueue, packets, id, tag, values, force, async () => {
26
- if (packet.rereference) {
27
- if (id === -1)
28
- throw new Error("Cannot send a re-referenced packet from the server-wide sender!");
29
- const serialized = (0, HashUtil_1.hashValue)(values);
30
- if (packet.lastSent[id] === serialized) {
31
- return [code, CompressionUtil_1.EMPTY_UINT8, packet];
32
- }
33
- packet.lastSent[id] = serialized;
34
- }
35
- if (packet.autoFlatten) {
36
- values = FlattenData(values[0]);
37
- }
38
- else {
39
- if (values.length > packet.maxSize)
40
- throw new Error(`Packet "${tag}" only allows ${packet.maxSize} values!`);
41
- if (values.length < packet.minSize)
42
- throw new Error(`Packet "${tag}" requires at least ${packet.minSize} values!`);
43
- }
44
- if (!packet.object) {
45
- if (packet.type !== PacketType_1.PacketType.JSON) {
46
- const found = values.find(v => typeof v === 'object' && v != null);
47
- if (found)
48
- console.warn(`Passing an array will result in undefined behavior (${JSON.stringify(found)}). Spread the array with ...arr`);
49
- }
50
- }
51
- else {
52
- values = values.map(x => !Array.isArray(x) ? [x] : x);
53
- if (!packet.autoFlatten) {
54
- const dataMins = packet.dataMin;
55
- const dataMaxes = packet.dataMax;
56
- for (let i = 0; i < dataMins.length; i++) {
57
- if (values[i].length < dataMins[i])
58
- throw new Error(`Section ${i + 1} of packet "${tag}" requires at least ${dataMins[i]} values!`);
59
- if (values[i].length > dataMaxes[i])
60
- throw new Error(`Section ${i + 1} of packet "${tag}" only allows ${dataMaxes[i]} values!`);
61
- }
62
- }
63
- }
64
- const sendData = values.length > 0 ? await packet.processSend(values) : CompressionUtil_1.EMPTY_UINT8;
65
- return [code, sendData, packet];
66
- });
67
- }
68
-
69
- async function handleQueue(sendQueue, packets, id, tag, values, force, fn) {
70
- if (sendQueue[0] && !force) {
71
- return new Promise((resolve) => sendQueue[1].push([resolve, tag, values]));
72
- }
73
- sendQueue[0] = true;
74
- const result = await fn();
75
- if (sendQueue[1].length > 0) {
76
- const [resolve, nextTag, nextValues] = sendQueue[1].shift();
77
- queueMicrotask(async () => {
78
- resolve(await processPacket(packets, nextTag, nextValues, sendQueue, id, true));
79
- });
80
- }
81
- else {
82
- sendQueue[0] = false;
83
- }
84
- return result;
85
- }
86
-
87
- async function listenPacket(listened, listeners, errorCB) {
88
- if (typeof listened === 'string')
89
- return errorCB(listened);
90
- const [processed, flatten] = listened;
91
- try {
92
- if (flatten && Array.isArray(processed)) {
93
- for (const l of listeners) {
94
- await l(...processed);
95
- }
96
- }
97
- else {
98
- for (const l of listeners) {
99
- await l(processed);
100
- }
101
- }
102
- }
103
- catch (err) {
104
- console.error(err);
105
- errorCB(err);
106
- }
107
- }
108
-
109
- function isInvalidType(type) {
110
- return (!(typeof type == 'number' && type in PacketType_1.PacketType) && !(type instanceof EnumType_1.EnumPackage)) || type == PacketType_1.PacketType.KEY_EFFECTIVE;
111
- }
112
- const MAX_DATA_MAX = 2048383;
113
-
114
- function clampDataMax(dataMax) {
115
- if (dataMax < 0) {
116
- console.warn(`Having a data maximum below 0 does not do anything!`);
117
- return 0;
118
- }
119
-
120
- if (dataMax > MAX_DATA_MAX) {
121
- console.warn(`Only ${MAX_DATA_MAX} values can be sent on a type! Uhh make an issue if you want to send more.`);
122
- return MAX_DATA_MAX;
123
- }
124
- return dataMax;
125
- }
126
-
127
- function clampDataMin(dataMin, dataMax) {
128
- if (dataMin < 0) {
129
- console.warn(`Having a data minimum below 0 does not do anything!`);
130
- return 0;
131
- }
132
-
133
- if (dataMin > dataMax) {
134
- console.warn(`Data minimum can not be higher than the data maximum!`);
135
- return dataMax;
136
- }
137
- return dataMin;
138
- }
139
-
140
- function CreatePacket(settings) {
141
- let { tag, type = PacketType_1.PacketType.NONE, dataMax = 1, dataMin = 1, noDataRange = false, dontSpread = false, validator = null, dataBatching = 0, maxBatchSize = 10, rateLimit = 0, enabled = true, async = false, gzipCompression = type == PacketType_1.PacketType.JSON, rereference = false } = settings;
142
- if (!tag)
143
- throw new Error("Tag not selected!");
144
- if (noDataRange) {
145
- dataMin = rereference ? 1 : 0;
146
- dataMax = MAX_DATA_MAX;
147
- }
148
- else if (dataMin == undefined)
149
- dataMin = type == PacketType_1.PacketType.NONE ? 0 : dataMax;
150
- if (rereference && dataMin == 0)
151
- throw new Error("Rereference cannot be true if the dataMin is 0");
152
- if (isInvalidType(type)) {
153
- throw new Error(`Invalid packet type: ${type}`);
154
- }
155
- const schema = Packets_1.PacketSchema.single(type, clampDataMax(dataMax), clampDataMin(dataMin, dataMax), dontSpread, dataBatching, maxBatchSize, rateLimit, async, gzipCompression, rereference);
156
- return new Packets_1.Packet(tag, schema, validator, enabled, false);
157
- }
158
-
159
- function CreateObjPacket(settings) {
160
- let { tag, types = [], dataMaxes, dataMins, noDataRange = false, dontSpread = false, autoFlatten = false, validator = null, dataBatching = 0, maxBatchSize = 10, rateLimit = 0, enabled = true, async = false, gzipCompression = types && types.includes(PacketType_1.PacketType.JSON) } = settings;
161
- if (!tag)
162
- throw new Error("Tag not selected!");
163
- if (!types || types.length == 0)
164
- throw new Error("Types is set to 0 length");
165
- for (const type of types) {
166
- if (!isInvalidType(type))
167
- continue;
168
- throw new Error(`Invalid packet type in "${tag}" packet: ${type}`);
169
- }
170
- if (noDataRange) {
171
- dataMaxes = Array.from({ length: types.length }).map(() => MAX_DATA_MAX);
172
- dataMins = Array.from({ length: types.length }).map(() => 0);
173
- }
174
- else {
175
- if (dataMaxes == undefined)
176
- dataMaxes = Array.from({ length: types.length }).map(() => 1);
177
- else if (!Array.isArray(dataMaxes))
178
- dataMaxes = Array.from({ length: types.length }).map(() => dataMaxes);
179
- if (dataMins == undefined)
180
- dataMins = Array.from({ length: types.length }).map((_, i) => dataMaxes[i]);
181
- else if (!Array.isArray(dataMins))
182
- dataMins = Array.from({ length: types.length }).map(() => dataMins);
183
- }
184
- const clampedDataMaxes = dataMaxes.map(clampDataMax);
185
- const clampedDataMins = dataMins.map((m, i) => types[i] == PacketType_1.PacketType.NONE ? 0 : clampDataMin(m, clampedDataMaxes[i]));
186
- const schema = Packets_1.PacketSchema.object(types, clampedDataMaxes, clampedDataMins, dontSpread, autoFlatten, dataBatching, maxBatchSize, rateLimit, async, gzipCompression);
187
- return new Packets_1.Packet(tag, schema, validator, enabled, false);
188
- }
189
-
190
- function CreateEnumPacket(settings) {
191
- const { tag, enumData, dataMax = 1, dataMin = 0, noDataRange = false, dontSpread = false, validator = null, dataBatching = 0, maxBatchSize = 10, rateLimit = 0, enabled = true, async = false } = settings;
192
- return CreatePacket({
193
- tag: tag,
194
- type: enumData,
195
- dataMax,
196
- dataMin,
197
- noDataRange,
198
- dontSpread,
199
- validator,
200
- dataBatching,
201
- maxBatchSize,
202
- rateLimit,
203
- enabled,
204
- async,
205
- });
206
- }
207
- function CreateKeyEffective(settings) {
208
- const { tag, count = 2, validator = null, async = false } = settings;
209
- if (!tag)
210
- throw new Error("Tag not selected!");
211
- if (count < 2)
212
- throw new Error("Must have at least 2 key consumptions on key effective packet!");
213
- throw new Error("Currently W.I.P.");
214
- }
215
-
216
- function FlattenData(arr) {
217
- if (arr == null)
218
- return [];
219
- const setup = arr[0];
220
- if (setup == null)
221
- return [];
222
- if (!Array.isArray(setup))
223
- throw new Error(`Cannot flatten array: ${arr}`);
224
- return setup.map((_, i) => arr.map(row => row[i])) ?? [];
225
- }
226
-
227
- function UnFlattenData(arr) {
228
- return arr[0]?.map((_, i) => arr.map(col => col[i])) ?? [];
229
- }
6
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.processPacket=o,exports.listenPacket=async function(e,t,a){if("string"==typeof e)return a(e);const[n,r]=e;try{if(r&&Array.isArray(n))for(const e of t)await e(...n);else for(const e of t)await e(n)}catch(e){console.error(e),a(e)}},exports.CreatePacket=u,exports.CreateObjPacket=function(a){let{tag:n,types:r=[],dataMaxes:o,dataMins:u,noDataRange:f=!1,dontSpread:p=!1,autoFlatten:h=!1,validator:y=null,dataBatching:m=0,maxBatchSize:d=10,rateLimit:w=0,enabled:g=!0,async:k=!1,gzipCompression:P=r&&r.includes(t.PacketType.JSON)}=a;if(!n)throw new Error("Tag not selected!");if(!r||0==r.length)throw new Error("Types is set to 0 length");for(const e of r)if(i(e))throw new Error(`Invalid packet type in "${n}" packet: ${e}`);f?(o=Array.from({length:r.length}).map(()=>s),u=Array.from({length:r.length}).map(()=>0)):(null==o?o=Array.from({length:r.length}).map(()=>1):Array.isArray(o)||(o=Array.from({length:r.length}).map(()=>o)),null==u?u=Array.from({length:r.length}).map((e,t)=>o[t]):Array.isArray(u)||(u=Array.from({length:r.length}).map(()=>u)));const E=o.map(c),S=u.map((e,a)=>r[a]==t.PacketType.NONE?0:l(e,E[a])),x=new e.PacketSchema(!0,r,k,S,E,w,p,h,!1,m,d,P);return new e.Packet(n,x,y,g,!1)},exports.CreateEnumPacket=function(e){const{tag:t,enumData:a,dataMax:n=1,dataMin:r=0,noDataRange:o=!1,dontSpread:i=!1,validator:s=null,dataBatching:c=0,maxBatchSize:l=10,rateLimit:f=0,enabled:p=!0,async:h=!1}=e;return u({tag:t,type:a,dataMax:n,dataMin:r,noDataRange:o,dontSpread:i,validator:s,dataBatching:c,maxBatchSize:l,rateLimit:f,enabled:p,async:h})},exports.CreateKeyEffective=function(e){const{tag:t,count:a=2,validator:n=null,async:r=!1}=e;if(!t)throw new Error("Tag not selected!");if(a<2)throw new Error("Must have at least 2 key consumptions on key effective packet!");throw new Error("Currently W.I.P.")},exports.FlattenData=f,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"),n=require("./CompressionUtil"),r=require("./HashUtil");async function o(e,a,i,s,c,l=!1){const u=e.getKey(a),p=e.getPacket(a);return async function(e,t,a,n,r,i,s){if(e[0]&&!i)return new Promise(t=>e[1].push([t,n,r]));e[0]=!0;const c=await s();if(e[1].length>0){const[n,r,i]=e[1].shift();queueMicrotask(async()=>{n(await o(t,r,i,e,a,!0))})}else e[0]=!1;return c}(s,e,c,a,i,l,async()=>{if(p.rereference){if(-1===c)throw new Error("Cannot send a re-referenced packet from the server-wide sender!");const e=(0,r.hashValue)(i);if(p.lastSent[c]===e)return[u,n.EMPTY_UINT8,p];p.lastSent[c]=e}if(p.autoFlatten)i=f(i[0]);else{if(i.length>p.maxSize)throw new Error(`Packet "${a}" only allows ${p.maxSize} values!`);if(i.length<p.minSize)throw new Error(`Packet "${a}" requires at least ${p.minSize} values!`)}if(p.object){if(i=i.map(e=>Array.isArray(e)?e:[e]),!p.autoFlatten){const e=p.dataMin,t=p.dataMax;for(let n=0;n<e.length;n++){if(i[n].length<e[n])throw new Error(`Section ${n+1} of packet "${a}" requires at least ${e[n]} values!`);if(i[n].length>t[n])throw new Error(`Section ${n+1} of packet "${a}" only allows ${t[n]} values!`)}}}else if(p.type!==t.PacketType.JSON){const e=i.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=i.length>0?await p.processSend(i):n.EMPTY_UINT8;return[u,e,p]})}function i(e){return!(("number"==typeof e&&e in t.PacketType||e instanceof a.EnumPackage)&&e!=t.PacketType.KEY_EFFECTIVE)}const s=2048383;function c(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 l(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 u(a){let{tag:n,type:r=t.PacketType.NONE,dataMax:o=1,dataMin:u=1,noDataRange:f=!1,dontSpread:p=!1,validator:h=null,dataBatching:y=0,maxBatchSize:m=10,rateLimit:d=0,enabled:w=!0,async:g=!1,gzipCompression:k=r==t.PacketType.JSON,rereference:P=!1}=a;if(!n)throw new Error("Tag not selected!");if(f?(u=P?1:0,o=s):null==u&&(u=r==t.PacketType.NONE?0:o),P&&0==u)throw new Error("Rereference cannot be true if the dataMin is 0");if(i(r))throw new Error(`Invalid packet type: ${r}`);const E=new e.PacketSchema(!1,r,g,l(u,o),c(o),d,p,!1,P,y,m,k);return new e.Packet(n,E,h,w,!1)}function f(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]))??[]}
@@ -2,55 +2,5 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- "use strict";
6
5
 
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.RateHandler = void 0;
9
- const Connection_1 = require("../../Connection");
10
-
11
- class RateHandler {
12
- rates = {};
13
- limits = {};
14
- setInterval;
15
- socket;
16
- constructor(host) {
17
-
18
- this.setInterval = host.setInterval;
19
- this.socket = host.socket;
20
- }
21
- start() {
22
-
23
- if (Object.keys(this.rates).length == 0)
24
- return;
25
- this.setInterval(() => {
26
- for (const tag in this.rates) {
27
- this.rates[tag] = 0;
28
- }
29
- }, 1000);
30
- }
31
- registerRate(tag, limit) {
32
-
33
- if (limit == 0)
34
- return;
35
- this.rates[tag] = 0;
36
- this.limits[tag] = limit;
37
- }
38
- registerAll(packetHolder, prefix) {
39
- const packets = packetHolder.getPackets();
40
- for (const packet of packets)
41
- this.registerRate(prefix + packetHolder.getKey(packet.tag), packet.rateLimit);
42
- }
43
- trigger(tag) {
44
- if (tag in this.rates && ++this.rates[tag] > this.limits[tag]) {
45
- this.socket.close(Connection_1.CloseCodes.RATELIMIT);
46
- return true;
47
- }
48
- return false;
49
- }
50
- subtract(tag) {
51
- if (!(tag in this.rates))
52
- return;
53
- this.rates[tag]--;
54
- }
55
- }
56
- exports.RateHandler = RateHandler;
6
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.RateHandler=void 0;const t=require("../../Connection");exports.RateHandler=class{rates={};limits={};setInterval;socket;constructor(t){this.setInterval=t.setInterval,this.socket=t.socket}start(){0!=Object.keys(this.rates).length&&this.setInterval(()=>{for(const t in this.rates)this.rates[t]=0},1e3)}registerRate(t,e){0!=e&&(this.rates[t]=0,this.limits[t]=e)}registerAll(t,e){const s=t.getPackets();for(const r of s)this.registerRate(e+t.getKey(r.tag),r.rateLimit)}trigger(e){return e in this.rates&&++this.rates[e]>this.limits[e]&&(this.socket.close(t.CloseCodes.RATELIMIT),!0)}subtract(t){t in this.rates&&this.rates[t]--}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonic-ws",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
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",
@@ -8,7 +8,7 @@
8
8
  "webpack": "webpack --mode production",
9
9
  "build_web": "rimraf ./html && tsc --moduleResolution nodenext --module nodenext --outDir ./html src/ws/client/browser/ClientBrowser.ts && npm run webpack",
10
10
  "build_node": "rimraf ./dist && tsc -d",
11
- "build": "npm run build_node && npm run build_web && node minify",
11
+ "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",
12
12
  "test_web": "npm run build && node test-site/server.mjs",
13
13
  "test_node": "npm run build_node && node test.mjs",
14
14
  "publish": "npm run build && cp ./bundled/SonicWS_bundle.js ./release/SonicWS_bundle.js"
@@ -24,6 +24,7 @@
24
24
  "author": "lily",
25
25
  "license": "Apache-2.0",
26
26
  "dependencies": {
27
+ "open": "^11.0.0",
27
28
  "ws": "^8.18.2"
28
29
  },
29
30
  "devDependencies": {
@@ -1,11 +0,0 @@
1
- /**
2
- * Copyright 2026 Lily (liwybloc)
3
- * Licensed under the Apache License, Version 2.0.
4
- */
5
- import { SonicWS } from "../client/browser/ClientBrowser";
6
- export declare class DebugClient {
7
- host: SonicWS;
8
- constructor(host: SonicWS);
9
- private _evalInScope;
10
- private _loadDebugScript;
11
- }