Compare commits

...

3 commits

Author SHA1 Message Date
Lily Tsuru 7a2c81886c clean up deps 2024-04-05 04:57:26 -04:00
Lily Tsuru 4212050ae5 port entire project to using parcel + strict TypeScript
Mostly out of cleanliness, and actually bundling the libraries properly.

Yes, this includes the backend, because.. why not? It seems to work, at least.

The VNC client for instance also is now fully strict TypeScript.
2024-04-05 04:30:56 -04:00
Lily Tsuru 7b9c71d534 misc server cleanup 2024-04-04 20:51:51 -04:00
29 changed files with 705 additions and 395 deletions

View file

@ -1,4 +1,4 @@
Copyright 2023 Lily Tsuru/modeco80 <lily.modeco80@protonmail.ch> Copyright 2023-2024 Lily Tsuru/modeco80 <lily.modeco80@protonmail.ch>
Please see qemu/src/rfb/LICENSE for additional terms. Please see qemu/src/rfb/LICENSE for additional terms.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy

View file

@ -3,15 +3,25 @@
"version": "1.0.0", "version": "1.0.0",
"private": "true", "private": "true",
"description": "socket 2.0 backend", "description": "socket 2.0 backend",
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "tsc" "build": "parcel build src/index.ts --target node"
}, },
"author": "modeco80", "author": "modeco80",
"license": "MIT", "license": "MIT",
"targets": {
"node":{
"context": "node",
"outputFormat": "esmodule"
}
},
"dependencies": { "dependencies": {
"@fastify/websocket": "^10.0.1", "@fastify/websocket": "^10.0.1",
"@julusian/jpeg-turbo": "^2.1.0",
"@socketcomputer/qemu": "*", "@socketcomputer/qemu": "*",
"@socketcomputer/shared": "*", "@socketcomputer/shared": "*",
"fastify": "^4.26.2", "fastify": "^4.26.2",
@ -19,6 +29,7 @@
"canvas": "^2.11.2" "canvas": "^2.11.2"
}, },
"devDependencies": { "devDependencies": {
"parcel": "^2.12.0",
"@types/ws": "^8.5.10" "@types/ws": "^8.5.10"
} }
} }

View file

@ -64,7 +64,7 @@ export function Slot_PCDef(
pushOption('-device usb-tablet'); pushOption('-device usb-tablet');
return { return {
id: "socketvm1", id: "socketvm2-test",
command: qCommand command: qCommand
}; };
} }

View file

@ -1,4 +1,4 @@
import { QemuVmDefinition, QemuDisplay, QemuVM, VMState, setSnapshot, GenMacAddress } from '@socketcomputer/qemu'; import { QemuVmDefinition, QemuDisplay, QemuVM, VMState, setSnapshot } from '@socketcomputer/qemu';
import { Slot_PCDef } from './SlotQemuDefs.js'; import { Slot_PCDef } from './SlotQemuDefs.js';
import { ExtendableTimer } from './ExtendableTimer.js'; import { ExtendableTimer } from './ExtendableTimer.js';
import { EventEmitter } from 'node:events'; import { EventEmitter } from 'node:events';
@ -20,7 +20,7 @@ const kCanvasJpegQuality = 0.25;
class VMUser { class VMUser {
public connection: WebSocket; public connection: WebSocket;
public address: string; public address: string;
public username: string; public username: string = "";
private vm: SocketVM; private vm: SocketVM;
@ -49,10 +49,10 @@ class VMUser {
async SendBuffer(buffer: ArrayBuffer): Promise<void> { async SendBuffer(buffer: ArrayBuffer): Promise<void> {
return new Promise((res, rej) => { return new Promise((res, rej) => {
if (this.connection.readyState !== WebSocket.CLOSED) { if (this.connection.readyState !== WebSocket.CLOSED) {
this.connection.send(buffer, (err) => { this.connection.send(buffer);
res(); res();
});
} }
rej(new Error('connection haves closed'));
}); });
} }
@ -73,14 +73,17 @@ type userAndTime = {
class TurnQueue extends EventEmitter { class TurnQueue extends EventEmitter {
private queue: Queue<VMUser> = new Queue<VMUser>(); private queue: Queue<VMUser> = new Queue<VMUser>();
private turnTime = kTurnTimeSeconds; private turnTime = kTurnTimeSeconds;
private interval: NodeJS.Timeout = null; private interval: NodeJS.Timeout|null = null;
constructor() { constructor() {
super(); super();
} }
public CurrentUser(): VMUser { public CurrentUser(): VMUser|null {
return this.queue.peek(); if(this.queue.peek() == undefined)
return null;
// We already check if it'll be undefined
return this.queue.peek()!;
} }
public TryEnqueue(user: VMUser) { public TryEnqueue(user: VMUser) {
@ -132,7 +135,7 @@ class TurnQueue extends EventEmitter {
} }
private nextTurn() { private nextTurn() {
clearInterval(this.interval); clearInterval(this.interval!);
if (this.queue.size === 0) { if (this.queue.size === 0) {
} else { } else {
this.turnTime = kTurnTimeSeconds; this.turnTime = kTurnTimeSeconds;
@ -145,26 +148,24 @@ class TurnQueue extends EventEmitter {
class SocketVM extends EventEmitter { class SocketVM extends EventEmitter {
private vm: QemuVM; private vm: QemuVM;
private display: QemuDisplay; private display: QemuDisplay|null = null;
private timer: ExtendableTimer = null; private timer: ExtendableTimer = new ExtendableTimer(15);
private users: Array<VMUser> = []; private users: Array<VMUser> = [];
private queue: TurnQueue = new TurnQueue(); private queue: TurnQueue = new TurnQueue();
constructor(vm: QemuVM) { constructor(vm: QemuVM) {
super(); super();
this.vm = vm; this.vm = vm;
this.timer = new ExtendableTimer(15);
this.timer.on('expired', async () => { this.timer.on('expired', async () => {
// bye bye! // bye bye!
console.log(`[SocketVM] VM expired, resetting..`); console.log(`[SocketVM] VM timer expired, resetting..`);
await this.vm.Stop(); await this.vm.Stop();
}); });
this.timer.on('expiry-near', async () => { this.timer.on('expiry-near', async () => {
console.log(`[SocketVM] about to expire!`); console.log(`[SocketVM] VM timer expires in 1 minute.`);
}); });
this.queue.on('turnQueue', (arr: Array<userAndTime>) => { this.queue.on('turnQueue', (arr: Array<userAndTime>) => {
@ -296,14 +297,12 @@ class SocketVM extends EventEmitter {
break; break;
case Shared.MessageType.Key: case Shared.MessageType.Key:
console.log("GOT key event", (message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed)
if(user != this.queue.CurrentUser()) if(user != this.queue.CurrentUser())
return; return;
if(this.display == null) if(this.display == null)
return; return;
console.log("valid key event", (message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed);
this.display.KeyboardEvent((message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed); this.display.KeyboardEvent((message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed);
break; break;
@ -329,7 +328,7 @@ class SocketVM extends EventEmitter {
let self = this; let self = this;
// Hook up the display // Hook up the display
this.display.on('resize', async (width, height) => { this.display?.on('resize', async (width: number, height: number) => {
if(self.display == null) if(self.display == null)
return; return;
@ -353,7 +352,7 @@ class SocketVM extends EventEmitter {
}); });
}); });
this.display.on('rect', async (x, y, rect: ImageData) => { this.display?.on('rect', async (x: number, y: number, rect: ImageData) => {
let canvas = new Canvas(rect.width, rect.height); let canvas = new Canvas(rect.width, rect.height);
canvas.getContext('2d').putImageData(rect, 0, 0); canvas.getContext('2d').putImageData(rect, 0, 0);
@ -376,7 +375,7 @@ class SocketVM extends EventEmitter {
await user.SendMessage((encoder: Shared.MessageEncoder) => { await user.SendMessage((encoder: Shared.MessageEncoder) => {
encoder.Init(8); encoder.Init(8);
encoder.SetDisplaySizeMessage(this.display.Size().width, this.display.Size().height); encoder.SetDisplaySizeMessage(this.display!.Size().width, this.display!.Size().height);
return encoder.Finish(); return encoder.Finish();
}); });
@ -392,8 +391,21 @@ class SocketVM extends EventEmitter {
} }
} }
// CONFIG types (not used yet)
export type SocketComputerConfig_VM = {
ramsize: string,
hda: string,
netdev: string
};
export type SocketComputerConfig = {
listen: string,
port: number
vm: SocketComputerConfig_VM
};
export class SocketComputerServer { export class SocketComputerServer {
private vm: SocketVM = null; private vm: SocketVM|null = null;
private fastify: FastifyInstance = fastify({ private fastify: FastifyInstance = fastify({
exposeHeadRoutes: false exposeHeadRoutes: false
}); });
@ -433,12 +445,13 @@ export class SocketComputerServer {
CTRoutes(app: FastifyInstance) { CTRoutes(app: FastifyInstance) {
let self = this; let self = this;
// @ts-ignore (fastify types are broken...)
app.get('/', { websocket: true }, (connection: fastifyWebsocket.WebSocket, req: FastifyRequest) => { app.get('/', { websocket: true }, (connection: fastifyWebsocket.WebSocket, req: FastifyRequest) => {
let address = req.ip; let address = req.ip;
if(req.headers["cf-connecting-ip"] !== undefined) { if(req.headers["cf-connecting-ip"] !== undefined) {
address = req.headers["cf-connecting-ip"] as string; address = req.headers["cf-connecting-ip"] as string;
} }
new VMUser(connection, self.vm, address); new VMUser(connection, self.vm!, address);
}); });
} }
} }

View file

@ -8,15 +8,21 @@
"webapp" "webapp"
], ],
"scripts": { "scripts": {
"build:frontend": "npm -w shared run build && npm -w webapp run build", "build": "yarn build:service && yarn build:frontend",
"build:service": "npm -w shared run build && npm -w qemu run build && npm -w backend run build" "build:service": "npm -w shared run build && npm -w qemu run build && npm -w backend run build",
"build:frontend": "npm -w shared run build && npm -w webapp run build"
}, },
"dependencies": { "dependencies": {
"canvas": "^2.11.2" "canvas": "^2.11.2"
}, },
"devDependencies": { "devDependencies": {
"parcel": "^2.12.0",
"@parcel/packager-ts": "2.12.0",
"@parcel/transformer-sass": "^2.12.0",
"@parcel/transformer-typescript-types": "2.12.0",
"@types/node": "^20.12.2", "@types/node": "^20.12.2",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"stream-http": "^3.1.0",
"typescript": "^5.4.3" "typescript": "^5.4.3"
} }
} }

View file

@ -3,17 +3,30 @@
"version": "1.0.0", "version": "1.0.0",
"private": "true", "private": "true",
"description": "QEMU runtime for socketcomputer backend", "description": "QEMU runtime for socketcomputer backend",
"main": "dist/src/index.js", "exports": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "tsc" "build": "parcel build src/index.ts --target node --target types"
}, },
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"targets": {
"types": {},
"node": {
"context": "node",
"isLibrary": true,
"outputFormat": "esmodule"
}
},
"dependencies": { "dependencies": {
"canvas": "^2.11.2", "canvas": "^2.11.2",
"execa": "^8.0.1", "execa": "^8.0.1",
"split": "^1.0.1" "split": "^1.0.1"
},
"devDependencies": {
"parcel": "^2.12.0",
"@types/node": "^20.12.2",
"@types/split": "^1.0.5"
} }
} }

View file

@ -138,11 +138,11 @@ export class QemuDisplay extends EventEmitter {
}; };
} }
MouseEvent(x, y, buttons) { MouseEvent(x: number, y: number, buttons: number) {
this.displayVnc.sendPointerEvent(x, y, buttons); this.displayVnc.sendPointerEvent(x, y, buttons);
} }
KeyboardEvent(keysym, pressed) { KeyboardEvent(keysym: number, pressed: boolean) {
this.displayVnc.sendKeyEvent(keysym, pressed); this.displayVnc.sendKeyEvent(keysym, pressed);
} }
} }

View file

@ -25,7 +25,7 @@ const kMaxFailCount = 5;
let gVMShouldSnapshot = false; let gVMShouldSnapshot = false;
async function Sleep(ms) { async function Sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms)); return new Promise((resolve) => setTimeout(resolve, ms));
} }
@ -145,7 +145,7 @@ export class QemuVM extends EventEmitter {
if (this.state !== stateShouldBe) throw new Error(message); if (this.state !== stateShouldBe) throw new Error(message);
} }
private SetState(state) { private SetState(state: VMState) {
this.state = state; this.state = state;
this.emit('statechange', this.state); this.emit('statechange', this.state);
} }
@ -158,7 +158,7 @@ export class QemuVM extends EventEmitter {
return `${kVmTmpPathBase}/socket2-${this.definition.id}-vnc`; return `${kVmTmpPathBase}/socket2-${this.definition.id}-vnc`;
} }
private async StartQemu(split) { private async StartQemu(split: Array<string>) {
let self = this; let self = this;
this.SetState(VMState.Starting); this.SetState(VMState.Starting);
@ -227,11 +227,11 @@ export class QemuVM extends EventEmitter {
switch (ev.event) { switch (ev.event) {
// Handle the STOP event sent when using -no-shutdown // Handle the STOP event sent when using -no-shutdown
case 'STOP': case 'STOP':
await self.qmpInstance.Execute('system_reset'); await self.qmpInstance?.Execute('system_reset');
break; break;
case 'RESET': case 'RESET':
self.VMLog('got a reset event!'); self.VMLog('got a reset event!');
await self.qmpInstance.Execute('cont'); await self.qmpInstance?.Execute('cont');
break; break;
} }
}); });
@ -250,7 +250,7 @@ export class QemuVM extends EventEmitter {
try { try {
await Sleep(500); await Sleep(500);
this.qmpInstance.ConnectUNIX(this.GetQmpPath()); this.qmpInstance?.ConnectUNIX(this.GetQmpPath());
} catch (err) { } catch (err) {
// just try again // just try again
await Sleep(500); await Sleep(500);
@ -261,7 +261,7 @@ export class QemuVM extends EventEmitter {
private async DisconnectDisplay() { private async DisconnectDisplay() {
try { try {
this.display.Disconnect(); this.display?.Disconnect();
this.display = null; // disassociate with that display object. this.display = null; // disassociate with that display object.
await unlink(this.GetVncPath()); await unlink(this.GetVncPath());

View file

@ -123,7 +123,7 @@ export default class QmpClient extends Socket {
}); });
} }
Connect(host, port) { Connect(host: string, port: number) {
super.connect(port, host); super.connect(port, host);
this.ConnectImpl(); this.ConnectImpl();
} }

View file

@ -1,6 +1,6 @@
Copyright 2021 Filipe Calaça Barbosa Copyright 2021 Filipe Calaça Barbosa
Copyright 2022 dither Copyright 2022 dither
Copyright 2023 Lily Tsuru/modeco80 <lily.modeco80@protonmail.ch> Copyright 2023-2024 Lily Tsuru/modeco80 <lily.modeco80@protonmail.ch>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -2,9 +2,10 @@
The source here was originally taken from a fork of [vnc-rfb-client](https://github.com/ayunami2000/vnc-rfb-client) made for the LucidVM project, available [here](https://github.com/lucidvm/rfb). The source here was originally taken from a fork of [vnc-rfb-client](https://github.com/ayunami2000/vnc-rfb-client) made for the LucidVM project, available [here](https://github.com/lucidvm/rfb).
It has been grossly modified for the usecases for the `@socketcomputer/qemu` package: It has been grossly modified for the usecases for the socket2 backend, but is more than likely usable to other clients.
- converted to TypeScript - converted to (strict) TypeScript; my initial port beforehand was not strict and it Sucked
- Also, actually use interfaces, and reduce the amount of code duplicated significantly in the rect decoders.
- all modules rewritten to use ESM - all modules rewritten to use ESM
- some noisy debug prints removed - some noisy debug prints removed
- (some, very tiny) code cleanup - (some, very tiny) code cleanup

View file

@ -1,3 +1,5 @@
import { IRectDecoder } from './decoders/decoder.js';
import { HextileDecoder } from './decoders/hextile.js'; import { HextileDecoder } from './decoders/hextile.js';
import { RawDecoder } from './decoders/raw.js'; import { RawDecoder } from './decoders/raw.js';
import { ZrleDecoder } from './decoders/zrle.js'; import { ZrleDecoder } from './decoders/zrle.js';
@ -13,57 +15,79 @@ import * as crypto from 'node:crypto';
import { SocketBuffer } from './socketbuffer.js'; import { SocketBuffer } from './socketbuffer.js';
import { VncRectangle, Color3, PixelFormat, Cursor } from './types.js';
export class VncClient extends EventEmitter { export class VncClient extends EventEmitter {
// These are in no particular order. // These are in no particular order.
public debug: Boolean; public debug: boolean = false;
private _connected: Boolean; private _connected: boolean = false;
private _authenticated: Boolean; private _authenticated: boolean = false;
private _version: string; private _version: string = "";
private _password: string; private _password: string = "";
private _audioChannels: number; private _audioChannels: number = 2;
private _audioFrequency: number; private _audioFrequency: number = 22050;
private _rects: number; private _rects: number = 0;
private _decoders: any; // no real good way to type this yet. will do it later private _decoders: Array<IRectDecoder> = [];
private _fps: number; private _fps: number;
private _timerInterval: number; private _timerInterval: number;
private _timerPointer; private _timerPointer : NodeJS.Timeout|null = null;
public fb: Buffer; public fb: Buffer = Buffer.from([]);
private _handshaked: Boolean; private _handshaked: boolean = false;
private _waitingServerInit: Boolean; private _waitingServerInit: boolean = false;
private _expectingChallenge: Boolean; private _expectingChallenge: boolean = false;
private _challengeResponseSent: Boolean; private _challengeResponseSent: boolean = false;
private _set8BitColor: Boolean; private _set8BitColor: boolean = false;
private _frameBufferReady = false; private _frameBufferReady = false;
private _firstFrameReceived = false; private _firstFrameReceived = false;
private _processingFrame = false; private _processingFrame = false;
private _relativePointer: Boolean; private _relativePointer: boolean = false;
public bigEndianFlag: Boolean; public bigEndianFlag: boolean = false;
public clientWidth: number; public clientWidth: number = 0;
public clientHeight: number; public clientHeight: number = 0;
public clientName: string; public clientName: string = "";
public pixelFormat: any; public pixelFormat: PixelFormat = {
bitsPerPixel: 0,
depth: 0,
bigEndianFlag: 0,
trueColorFlag: 0,
redMax: 0,
greenMax: 0,
blueMax: 0,
redShift: 0,
greenShift: 0,
blueShift: 0
};
private _colorMap: any[]; private _colorMap: Color3[] = [];
private _audioData: Buffer; private _audioData: Buffer = Buffer.from([]);
private _cursor: any; private _cursor: Cursor = {
width: 0,
height: 0,
x: 0,
y: 0,
cursorPixels: null,
bitmask: null,
posX: 0,
posY: 0
};
public encodings: number[]; public encodings: number[];
private _connection: net.Socket; private _connection: net.Socket|null = null;
private _socketBuffer: SocketBuffer; private _socketBuffer: SocketBuffer;
static get consts() { static get consts() {
@ -101,7 +125,7 @@ export class VncClient extends EventEmitter {
* @returns {number} * @returns {number}
*/ */
get localPort() { get localPort() {
return this._connection ? this._connection.localPort : 0; return this._connection ? this._connection?.localPort : 0;
} }
constructor(options: any = { debug: false, fps: 0, encodings: [] }) { constructor(options: any = { debug: false, fps: 0, encodings: [] }) {
@ -125,7 +149,7 @@ export class VncClient extends EventEmitter {
this._audioFrequency = options.audioFrequency || 22050; this._audioFrequency = options.audioFrequency || 22050;
this._rects = 0; this._rects = 0;
this._decoders = {};
this._decoders[consts.encodings.raw] = new RawDecoder(); this._decoders[consts.encodings.raw] = new RawDecoder();
// TODO: Implement tight encoding // TODO: Implement tight encoding
// this._decoders[encodings.tight] = new tightDecoder(); // this._decoders[encodings.tight] = new tightDecoder();
@ -155,7 +179,7 @@ export class VncClient extends EventEmitter {
* Adjuste the configured FPS * Adjuste the configured FPS
* @param fps {number} - Number of update requests send by second * @param fps {number} - Number of update requests send by second
*/ */
changeFps(fps) { changeFps(fps: number) {
if (!Number.isNaN(fps)) { if (!Number.isNaN(fps)) {
this._fps = Number(fps); this._fps = Number(fps);
this._timerInterval = this._fps > 0 ? 1000 / this._fps : 0; this._timerInterval = this._fps > 0 ? 1000 / this._fps : 0;
@ -178,7 +202,7 @@ export class VncClient extends EventEmitter {
* @param options * @param options
*/ */
connect( connect(
options /* = { options: any /* = {
host: '', host: '',
password: '', password: '',
path: '', path: '',
@ -199,31 +223,31 @@ export class VncClient extends EventEmitter {
this._connection = net.connect(options.port || 5900, options.host); this._connection = net.connect(options.port || 5900, options.host);
// disable nagle's algorithm for TCP // disable nagle's algorithm for TCP
this._connection.setNoDelay(); this._connection?.setNoDelay();
} else { } else {
// unix socket. bodged in but oh well // unix socket. bodged in but oh well
this._connection = net.connect(options.path); this._connection = net.connect(options.path);
} }
this._connection.on('connect', () => { this._connection?.on('connect', () => {
this._connected = true; this._connected = true;
this.emit('connected'); this.emit('connected');
}); });
this._connection.on('close', () => { this._connection?.on('close', () => {
this.resetState(); this.resetState();
this.emit('closed'); this.emit('closed');
}); });
this._connection.on('timeout', () => { this._connection?.on('timeout', () => {
this.emit('connectTimeout'); this.emit('connectTimeout');
}); });
this._connection.on('error', (err) => { this._connection?.on('error', (err) => {
this.emit('connectError', err); this.emit('connectError', err);
}); });
this._connection.on('data', async (data) => { this._connection?.on('data', async (data) => {
this._socketBuffer.pushData(data); this._socketBuffer.pushData(data);
if (!this._handshaked) { if (!this._handshaked) {
@ -243,7 +267,7 @@ export class VncClient extends EventEmitter {
*/ */
disconnect() { disconnect() {
if (this._connection) { if (this._connection) {
this._connection.end(); this._connection?.end();
this.resetState(); this.resetState();
this.emit('disconnected'); this.emit('disconnected');
} }
@ -269,7 +293,7 @@ export class VncClient extends EventEmitter {
message.writeUInt16BE(width, 6); // Width message.writeUInt16BE(width, 6); // Width
message.writeUInt16BE(height, 8); // Height message.writeUInt16BE(height, 8); // Height
this._connection.write(message); this._connection?.write(message);
this._frameBufferReady = true; this._frameBufferReady = true;
} }
@ -283,15 +307,15 @@ export class VncClient extends EventEmitter {
// Handshake, negotiating protocol version // Handshake, negotiating protocol version
if (this._socketBuffer.toString() === consts.versionString.V3_003) { if (this._socketBuffer.toString() === consts.versionString.V3_003) {
this._log('Sending 3.3', true); this._log('Sending 3.3', true);
this._connection.write(consts.versionString.V3_003); this._connection?.write(consts.versionString.V3_003);
this._version = '3.3'; this._version = '3.3';
} else if (this._socketBuffer.toString() === consts.versionString.V3_007) { } else if (this._socketBuffer.toString() === consts.versionString.V3_007) {
this._log('Sending 3.7', true); this._log('Sending 3.7', true);
this._connection.write(consts.versionString.V3_007); this._connection?.write(consts.versionString.V3_007);
this._version = '3.7'; this._version = '3.7';
} else if (this._socketBuffer.toString() === consts.versionString.V3_008) { } else if (this._socketBuffer.toString() === consts.versionString.V3_008) {
this._log('Sending 3.8', true); this._log('Sending 3.8', true);
this._connection.write(consts.versionString.V3_008); this._connection?.write(consts.versionString.V3_008);
this._version = '3.8'; this._version = '3.8';
} else { } else {
// Negotiating auth mechanism // Negotiating auth mechanism
@ -299,10 +323,10 @@ export class VncClient extends EventEmitter {
if (this._socketBuffer.includes(0x02) && this._password) { if (this._socketBuffer.includes(0x02) && this._password) {
this._log('Password provided and server support VNC auth. Choosing VNC auth.', true); this._log('Password provided and server support VNC auth. Choosing VNC auth.', true);
this._expectingChallenge = true; this._expectingChallenge = true;
this._connection.write(Buffer.from([0x02])); this._connection?.write(Buffer.from([0x02]));
} else if (this._socketBuffer.includes(1)) { } else if (this._socketBuffer.includes(1)) {
this._log('Password not provided or server does not support VNC auth. Trying none.', true); this._log('Password not provided or server does not support VNC auth. Trying none.', true);
this._connection.write(Buffer.from([0x01])); this._connection?.write(Buffer.from([0x01]));
if (this._version === '3.7') { if (this._version === '3.7') {
this._waitingServerInit = true; this._waitingServerInit = true;
} else { } else {
@ -352,7 +376,7 @@ export class VncClient extends EventEmitter {
response.fill(des1.update(this._socketBuffer.buffer.slice(0, 8)), 0, 8); response.fill(des1.update(this._socketBuffer.buffer.slice(0, 8)), 0, 8);
response.fill(des2.update(this._socketBuffer.buffer.slice(8, 16)), 8, 16); response.fill(des2.update(this._socketBuffer.buffer.slice(8, 16)), 8, 16);
this._connection.write(response); this._connection?.write(response);
this._challengeResponseSent = true; this._challengeResponseSent = true;
} }
@ -363,7 +387,7 @@ export class VncClient extends EventEmitter {
* Reverse bits order of a byte * Reverse bits order of a byte
* @param buf - Buffer to be flipped * @param buf - Buffer to be flipped
*/ */
reverseBits(buf) { reverseBits(buf: Buffer) {
for (let x = 0; x < buf.length; x++) { for (let x = 0; x < buf.length; x++) {
let newByte = 0; let newByte = 0;
newByte += buf[x] & 128 ? 1 : 0; newByte += buf[x] & 128 ? 1 : 0;
@ -390,6 +414,7 @@ export class VncClient extends EventEmitter {
this.clientWidth = this._socketBuffer.readUInt16BE(); this.clientWidth = this._socketBuffer.readUInt16BE();
this.clientHeight = this._socketBuffer.readUInt16BE(); this.clientHeight = this._socketBuffer.readUInt16BE();
this.pixelFormat.bitsPerPixel = this._socketBuffer.readUInt8(); this.pixelFormat.bitsPerPixel = this._socketBuffer.readUInt8();
this.pixelFormat.depth = this._socketBuffer.readUInt8(); this.pixelFormat.depth = this._socketBuffer.readUInt8();
this.pixelFormat.bigEndianFlag = this._socketBuffer.readUInt8(); this.pixelFormat.bigEndianFlag = this._socketBuffer.readUInt8();
@ -457,7 +482,7 @@ export class VncClient extends EventEmitter {
message.writeUInt8(0, 19); // PixelFormat - Padding message.writeUInt8(0, 19); // PixelFormat - Padding
// Envia um setPixelFormat trocando para mapa de cores // Envia um setPixelFormat trocando para mapa de cores
this._connection.write(message); this._connection?.write(message);
this.pixelFormat.bitsPerPixel = 8; this.pixelFormat.bitsPerPixel = 8;
this.pixelFormat.depth = 8; this.pixelFormat.depth = 8;
@ -487,7 +512,7 @@ export class VncClient extends EventEmitter {
message.writeInt32BE(consts.encodings.raw, offset + 4); message.writeInt32BE(consts.encodings.raw, offset + 4);
} }
this._connection.write(message); this._connection?.write(message);
} }
/** /**
@ -498,7 +523,7 @@ export class VncClient extends EventEmitter {
//this._log(`Sending clientInit`); //this._log(`Sending clientInit`);
this._waitingServerInit = true; this._waitingServerInit = true;
// Shared bit set // Shared bit set
this._connection.write('1'); this._connection?.write('1');
} }
/** /**
@ -558,6 +583,10 @@ export class VncClient extends EventEmitter {
data: Buffer.alloc(4) data: Buffer.alloc(4)
}; };
const { width, height, bitmask, cursorPixels } = this._cursor; const { width, height, bitmask, cursorPixels } = this._cursor;
if(bitmask == null || cursorPixels == null)
throw new Error('No cursor data to get!');
const data = Buffer.alloc(height * width * 4); const data = Buffer.alloc(height * width * 4);
for (var y = 0; y < height; y++) { for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) { for (var x = 0; x < width; x++) {
@ -568,6 +597,7 @@ export class VncClient extends EventEmitter {
case 8: case 8:
console.log(8); console.log(8);
const index = cursorPixels.readUInt8(offset); const index = cursorPixels.readUInt8(offset);
// @ts-ignore (This line is extremely suspect anyways. I bet this is horribly broken!!)
const color = this._colorMap[index] | 0xff; const color = this._colorMap[index] | 0xff;
data.writeIntBE(color, offset, 4); data.writeIntBE(color, offset, 4);
break; break;
@ -606,12 +636,14 @@ export class VncClient extends EventEmitter {
while (this._rects) { while (this._rects) {
await this._socketBuffer.waitBytes(12); await this._socketBuffer.waitBytes(12);
const rect: any = {}; const rect: VncRectangle = {
rect.x = this._socketBuffer.readUInt16BE(); x: this._socketBuffer.readUInt16BE(),
rect.y = this._socketBuffer.readUInt16BE(); y: this._socketBuffer.readUInt16BE(),
rect.width = this._socketBuffer.readUInt16BE(); width: this._socketBuffer.readUInt16BE(),
rect.height = this._socketBuffer.readUInt16BE(); height: this._socketBuffer.readUInt16BE(),
rect.encoding = this._socketBuffer.readInt32BE(); encoding: this._socketBuffer.readInt32BE(),
data: null // for now
};
if (rect.encoding === consts.encodings.pseudoQemuAudio) { if (rect.encoding === consts.encodings.pseudoQemuAudio) {
this.sendAudio(true); this.sendAudio(true);
@ -700,7 +732,7 @@ export class VncClient extends EventEmitter {
this._colorMap[firstColor] = { this._colorMap[firstColor] = {
r: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255), r: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255),
g: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255), g: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255),
b: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255) b: Math.floor((this._socketBuffer.readUInt16BE() / 65535) * 255),
}; };
firstColor++; firstColor++;
} }
@ -733,7 +765,7 @@ export class VncClient extends EventEmitter {
*/ */
resetState() { resetState() {
if (this._connection) { if (this._connection) {
this._connection.end(); this._connection?.end();
} }
if (this._timerPointer) { if (this._timerPointer) {
@ -782,7 +814,7 @@ export class VncClient extends EventEmitter {
this._rects = 0; this._rects = 0;
this._colorMap = []; this._colorMap = [];
this.fb = null; this.fb = Buffer.from([]);
this._socketBuffer?.flush(false); this._socketBuffer?.flush(false);
@ -792,7 +824,9 @@ export class VncClient extends EventEmitter {
x: 0, x: 0,
y: 0, y: 0,
cursorPixels: null, cursorPixels: null,
bitmask: null bitmask: null,
posX: 0,
posY: 0
}; };
} }
@ -803,7 +837,7 @@ export class VncClient extends EventEmitter {
* @param key - Key code (keysym) defined by X Window System, check https://wiki.linuxquestions.org/wiki/List_of_keysyms * @param key - Key code (keysym) defined by X Window System, check https://wiki.linuxquestions.org/wiki/List_of_keysyms
* @param down - True if the key is pressed, false if it is not * @param down - True if the key is pressed, false if it is not
*/ */
sendKeyEvent(key, down = false) { sendKeyEvent(key: number, down: boolean = false) {
const message = Buffer.alloc(8); const message = Buffer.alloc(8);
message.writeUInt8(4); // Message type message.writeUInt8(4); // Message type
message.writeUInt8(down ? 1 : 0, 1); // Down flag message.writeUInt8(down ? 1 : 0, 1); // Down flag
@ -812,7 +846,7 @@ export class VncClient extends EventEmitter {
message.writeUInt32BE(key, 4); // Key code message.writeUInt32BE(key, 4); // Key code
this._connection.write(message); this._connection?.write(message);
} }
/** /**
@ -821,7 +855,7 @@ export class VncClient extends EventEmitter {
* @param yPosition - Y Position * @param yPosition - Y Position
* @param mask - Raw RFB button mask * @param mask - Raw RFB button mask
*/ */
sendPointerEvent(xPosition, yPosition, buttonMask) { sendPointerEvent(xPosition: number, yPosition: number, buttonMask: number) {
const message = Buffer.alloc(6); const message = Buffer.alloc(6);
message.writeUInt8(consts.clientMsgTypes.pointerEvent); // Message type message.writeUInt8(consts.clientMsgTypes.pointerEvent); // Message type
message.writeUInt8(buttonMask, 1); // Button Mask message.writeUInt8(buttonMask, 1); // Button Mask
@ -832,14 +866,14 @@ export class VncClient extends EventEmitter {
this._cursor.posX = xPosition; this._cursor.posX = xPosition;
this._cursor.posY = yPosition; this._cursor.posY = yPosition;
this._connection.write(message); this._connection?.write(message);
} }
/** /**
* Send client cut message to server * Send client cut message to server
* @param text - latin1 encoded * @param text - latin1 encoded
*/ */
clientCutText(text) { clientCutText(text: string) {
const textBuffer = Buffer.from(text, 'latin1'); const textBuffer = Buffer.from(text, 'latin1');
const message = Buffer.alloc(8 + textBuffer.length); const message = Buffer.alloc(8 + textBuffer.length);
message.writeUInt8(6); // Message type message.writeUInt8(6); // Message type
@ -849,18 +883,18 @@ export class VncClient extends EventEmitter {
message.writeUInt32BE(textBuffer.length, 4); // Padding message.writeUInt32BE(textBuffer.length, 4); // Padding
textBuffer.copy(message, 8); textBuffer.copy(message, 8);
this._connection.write(message); this._connection?.write(message);
} }
sendAudio(enable) { sendAudio(enable: boolean) {
const message = Buffer.alloc(4); const message = Buffer.alloc(4);
message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type
message.writeUInt8(1, 1); // Submessage Type message.writeUInt8(1, 1); // Submessage Type
message.writeUInt16BE(enable ? 0 : 1, 2); // Operation message.writeUInt16BE(enable ? 0 : 1, 2); // Operation
this._connection.write(message); this._connection?.write(message);
} }
sendAudioConfig(channels, frequency) { sendAudioConfig(channels: number, frequency: number) {
const message = Buffer.alloc(10); const message = Buffer.alloc(10);
message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type
message.writeUInt8(1, 1); // Submessage Type message.writeUInt8(1, 1); // Submessage Type
@ -868,7 +902,7 @@ export class VncClient extends EventEmitter {
message.writeUInt8(0 /*U8*/, 4); // Sample Format message.writeUInt8(0 /*U8*/, 4); // Sample Format
message.writeUInt8(channels, 5); // Number of Channels message.writeUInt8(channels, 5); // Number of Channels
message.writeUInt32BE(frequency, 6); // Frequency message.writeUInt32BE(frequency, 6); // Frequency
this._connection.write(message); this._connection?.write(message);
} }
/** /**
@ -877,7 +911,7 @@ export class VncClient extends EventEmitter {
* @param debug * @param debug
* @private * @private
*/ */
_log(text, debug = false) { _log(text: string, debug = false) {
if (!debug || (debug && this.debug)) { if (!debug || (debug && this.debug)) {
console.log(text); console.log(text);
} }

View file

@ -1,9 +1,11 @@
export class CopyRectDecoder { import { SocketBuffer } from "../socketbuffer";
getPixelBytePos(x, y, width, height) { import { IRectDecoder } from "./decoder";
return (y * width + x) * 4; import { getPixelBytePos } from "./util";
}
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> { import { VncRectangle, Color3 } from "../types";
export class CopyRectDecoder implements IRectDecoder {
async decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
await socket.waitBytes(4); await socket.waitBytes(4);
rect.data = socket.readNBytesOffset(4); rect.data = socket.readNBytesOffset(4);
@ -13,8 +15,8 @@ export class CopyRectDecoder {
for (let h = 0; h < rect.height; h++) { for (let h = 0; h < rect.height; h++) {
for (let w = 0; w < rect.width; w++) { for (let w = 0; w < rect.width; w++) {
const fbOrigBytePosOffset = this.getPixelBytePos(x + w, y + h, screenW, screenH); const fbOrigBytePosOffset = getPixelBytePos(x + w, y + h, screenW, screenH);
const fbBytePosOffset = this.getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH); const fbBytePosOffset = getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH);
fb.writeUInt8(fb.readUInt8(fbOrigBytePosOffset), fbBytePosOffset); fb.writeUInt8(fb.readUInt8(fbOrigBytePosOffset), fbBytePosOffset);
fb.writeUInt8(fb.readUInt8(fbOrigBytePosOffset + 1), fbBytePosOffset + 1); fb.writeUInt8(fb.readUInt8(fbOrigBytePosOffset + 1), fbBytePosOffset + 1);

View file

@ -0,0 +1,7 @@
import { SocketBuffer } from "../socketbuffer";
import { Color3, VncRectangle } from "../types";
export interface IRectDecoder {
decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void>;
}

View file

@ -1,27 +1,25 @@
export class HextileDecoder { import { SocketBuffer } from "../socketbuffer";
getPixelBytePos(x, y, width, height) { import { IRectDecoder } from "./decoder";
return (y * width + x) * 4; import { applyColor, getPixelBytePos } from "./util";
}
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> { import { VncRectangle, Color3 } from "../types";
export class HextileDecoder implements IRectDecoder {
async decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
const initialOffset = socket.offset; const initialOffset = socket.offset;
let dataSize = 0; let dataSize = 0;
let tiles; let lastSubEncoding = 0;
let totalTiles;
let tilesX;
let tilesY;
let lastSubEncoding;
const backgroundColor = { r: 0, g: 0, b: 0, a: 255 }; const backgroundColor = { r: 0, g: 0, b: 0, a: 255 };
const foregroundColor = { r: 0, g: 0, b: 0, a: 255 }; const foregroundColor = { r: 0, g: 0, b: 0, a: 255 };
tilesX = Math.ceil(rect.width / 16); let tilesX = Math.ceil(rect.width / 16);
tilesY = Math.ceil(rect.height / 16); let tilesY = Math.ceil(rect.height / 16);
tiles = tilesX * tilesY; let tiles = tilesX * tilesY;
totalTiles = tiles; let totalTiles = tiles;
while (tiles) { while (tiles) {
await socket.waitBytes(1); await socket.waitBytes(1);
@ -42,7 +40,7 @@ export class HextileDecoder {
// We need to ignore zeroed tile after a raw tile // We need to ignore zeroed tile after a raw tile
} else { } else {
// If zeroed tile and last tile was not raw, use the last backgroundColor // If zeroed tile and last tile was not raw, use the last backgroundColor
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb); applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
} }
} else if (subEncoding & 0x01) { } else if (subEncoding & 0x01) {
// If Raw, ignore all other bits // If Raw, ignore all other bits
@ -50,7 +48,7 @@ export class HextileDecoder {
dataSize += th * tw * (bitsPerPixel / 8); dataSize += th * tw * (bitsPerPixel / 8);
for (let h = 0; h < th; h++) { for (let h = 0; h < th; h++) {
for (let w = 0; w < tw; w++) { for (let w = 0; w < tw; w++) {
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH); const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
if (bitsPerPixel === 8) { if (bitsPerPixel === 8) {
const index = socket.readUInt8(); const index = socket.readUInt8();
const color = colorMap[index]; const color = colorMap[index];
@ -148,7 +146,7 @@ export class HextileDecoder {
} }
// Initialize tile with the background color // Initialize tile with the background color
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb); applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
// AnySubrects bit // AnySubrects bit
if (subEncoding & 0x08) { if (subEncoding & 0x08) {
@ -206,13 +204,13 @@ export class HextileDecoder {
const sw = (wh >> 4) + 1; const sw = (wh >> 4) + 1;
const sh = (wh & 0x0f) + 1; const sh = (wh & 0x0f) + 1;
this.applyColor(sw, sh, tx + sx, ty + sy, screenW, screenH, color, fb); applyColor(sw, sh, tx + sx, ty + sy, screenW, screenH, color, fb);
} }
} else { } else {
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb); applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
} }
} else { } else {
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb); applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
} }
lastSubEncoding = subEncoding; lastSubEncoding = subEncoding;
@ -226,16 +224,5 @@ export class HextileDecoder {
}); });
} }
// Apply color to a rect on buffer
applyColor(tw, th, tx, ty, screenW, screenH, color, fb) {
for (let h = 0; h < th; h++) {
for (let w = 0; w < tw; w++) {
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
fb.writeUInt8(color.r || 255, fbBytePosOffset + 2);
fb.writeUInt8(color.g || 255, fbBytePosOffset + 1);
fb.writeUInt8(color.b || 255, fbBytePosOffset);
fb.writeUInt8(255, fbBytePosOffset + 3);
}
}
}
} }

View file

@ -1,16 +1,19 @@
export class RawDecoder { import { SocketBuffer } from "../socketbuffer";
getPixelBytePos(x, y, width, height) { import { IRectDecoder } from "./decoder";
return (y * width + x) * 4; import { getPixelBytePos } from "./util";
}
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> { import { VncRectangle, Color3 } from "../types";
export class RawDecoder implements IRectDecoder {
async decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
await socket.waitBytes(rect.width * rect.height * (bitsPerPixel / 8)); await socket.waitBytes(rect.width * rect.height * (bitsPerPixel / 8));
rect.data = socket.readNBytesOffset(rect.width * rect.height * (bitsPerPixel / 8)); rect.data = socket.readNBytesOffset(rect.width * rect.height * (bitsPerPixel / 8));
for (let h = 0; h < rect.height; h++) { for (let h = 0; h < rect.height; h++) {
for (let w = 0; w < rect.width; w++) { for (let w = 0; w < rect.width; w++) {
const fbBytePosOffset = this.getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH); const fbBytePosOffset = getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH);
if (bitsPerPixel === 8) { if (bitsPerPixel === 8) {
const bytePosOffset = h * rect.width + w; const bytePosOffset = h * rect.width + w;
const index = rect.data.readUInt8(bytePosOffset); const index = rect.data.readUInt8(bytePosOffset);

View file

@ -0,0 +1,19 @@
import { Color3 } from "../types";
export function getPixelBytePos(x: number, y: number, width: number, height: number, stride: number = 4): number {
return (y * width + x) * stride;
}
// Apply color to a rect on buffer
export function applyColor(tw: number, th: number, tx: number, ty: number, screenW: number, screenH: number, color: Color3, fb: Buffer) {
for (let h = 0; h < th; h++) {
for (let w = 0; w < tw; w++) {
const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
fb.writeUInt8(color.r || 255, fbBytePosOffset + 2);
fb.writeUInt8(color.g || 255, fbBytePosOffset + 1);
fb.writeUInt8(color.b || 255, fbBytePosOffset);
fb.writeUInt8(255, fbBytePosOffset + 3);
}
}
}

View file

@ -1,7 +1,11 @@
import * as zlib from 'node:zlib'; import * as zlib from 'node:zlib';
import { SocketBuffer } from '../socketbuffer.js'; import { SocketBuffer } from "../socketbuffer";
import { IRectDecoder } from "./decoder";
import { applyColor, getPixelBytePos } from "./util";
export class ZrleDecoder { import { VncRectangle, Color3, Color4 } from "../types";
export class ZrleDecoder implements IRectDecoder {
private zlib: zlib.Inflate; private zlib: zlib.Inflate;
private unBuffer: SocketBuffer; private unBuffer: SocketBuffer;
@ -14,11 +18,7 @@ export class ZrleDecoder {
}); });
} }
getPixelBytePos(x, y, width, height) { async decode(rect: VncRectangle, fb: Buffer, bitsPerPixel: number, colorMap: Array<Color3>, screenW: number, screenH: number, socket: SocketBuffer, depth: number): Promise<void> {
return (y * width + x) * 4;
}
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
await socket.waitBytes(4); await socket.waitBytes(4);
@ -35,15 +35,10 @@ export class ZrleDecoder {
this.zlib.write(compressedData, async () => { this.zlib.write(compressedData, async () => {
this.zlib.flush(); this.zlib.flush();
let tiles; let tilesX = Math.ceil(rect.width / 64);
let totalTiles; let tilesY = Math.ceil(rect.height / 64);
let tilesX; let tiles = tilesX * tilesY;
let tilesY; let totalTiles = tiles;
tilesX = Math.ceil(rect.width / 64);
tilesY = Math.ceil(rect.height / 64);
tiles = tilesX * tilesY;
totalTiles = tiles;
while (tiles) { while (tiles) {
await this.unBuffer.waitBytes(1, 'tile begin.'); await this.unBuffer.waitBytes(1, 'tile begin.');
@ -67,7 +62,7 @@ export class ZrleDecoder {
// Raw // Raw
for (let h = 0; h < th; h++) { for (let h = 0; h < th; h++) {
for (let w = 0; w < tw; w++) { for (let w = 0; w < tw; w++) {
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH); const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
if (bitsPerPixel === 8) { if (bitsPerPixel === 8) {
await this.unBuffer.waitBytes(1, 'raw 8bits'); await this.unBuffer.waitBytes(1, 'raw 8bits');
const index = this.unBuffer.readUInt8(); const index = this.unBuffer.readUInt8();
@ -105,11 +100,11 @@ export class ZrleDecoder {
} }
} else if (subEncoding === 1) { } else if (subEncoding === 1) {
// Single Color // Single Color
let color = { r: 0, g: 0, b: 0, a: 255 }; let color: Color4 = { r: 0, g: 0, b: 0, a: 255 };
if (bitsPerPixel === 8) { if (bitsPerPixel === 8) {
await this.unBuffer.waitBytes(1, 'single color 8bits'); await this.unBuffer.waitBytes(1, 'single color 8bits');
const index = this.unBuffer.readUInt8(); const index = this.unBuffer.readUInt8();
color = colorMap[index]; color = (colorMap[index] as Color4);
} else if (bitsPerPixel === 24 || (bitsPerPixel === 32 && depth === 24)) { } else if (bitsPerPixel === 24 || (bitsPerPixel === 32 && depth === 24)) {
await this.unBuffer.waitBytes(3, 'single color 24bits'); await this.unBuffer.waitBytes(3, 'single color 24bits');
color.r = this.unBuffer.readUInt8(); color.r = this.unBuffer.readUInt8();
@ -122,7 +117,7 @@ export class ZrleDecoder {
color.b = this.unBuffer.readUInt8(); color.b = this.unBuffer.readUInt8();
color.a = this.unBuffer.readUInt8(); color.a = this.unBuffer.readUInt8();
} }
this.applyColor(tw, th, tx, ty, screenW, screenH, color, fb); applyColor(tw, th, tx, ty, screenW, screenH, color, fb);
} else if (subEncoding >= 2 && subEncoding <= 16) { } else if (subEncoding >= 2 && subEncoding <= 16) {
// Palette // Palette
const palette = []; const palette = [];
@ -152,7 +147,7 @@ export class ZrleDecoder {
// const i = (tw * th) / (8 / bitsPerIndex); // const i = (tw * th) / (8 / bitsPerIndex);
// const pixels = []; // const pixels = [];
let byte; let byte = 0;
let bitPos = 0; let bitPos = 0;
for (let h = 0; h < th; h++) { for (let h = 0; h < th; h++) {
@ -162,7 +157,7 @@ export class ZrleDecoder {
byte = this.unBuffer.readUInt8(); byte = this.unBuffer.readUInt8();
bitPos = 0; bitPos = 0;
} }
let color; let color : Color4 = { r: 0, g: 0, b: 0, a: 255 };
switch (bitsPerIndex) { switch (bitsPerIndex) {
case 1: case 1:
if (bitPos === 0) { if (bitPos === 0) {
@ -216,7 +211,7 @@ export class ZrleDecoder {
} }
break; break;
} }
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH); const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
fb.writeUInt8(color.b ?? 0, fbBytePosOffset); fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1); fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2); fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
@ -259,7 +254,7 @@ export class ZrleDecoder {
totalRun += runLength; totalRun += runLength;
runs++; runs++;
} }
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH); const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
fb.writeUInt8(color.b ?? 0, fbBytePosOffset); fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1); fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2); fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
@ -321,7 +316,7 @@ export class ZrleDecoder {
totalRun += runLength; totalRun += runLength;
runs++; runs++;
} }
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH); const fbBytePosOffset = getPixelBytePos(tx + w, ty + h, screenW, screenH);
fb.writeUInt8(color.b ?? 0, fbBytePosOffset); fb.writeUInt8(color.b ?? 0, fbBytePosOffset);
fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1); fb.writeUInt8(color.g ?? 0, fbBytePosOffset + 1);
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2); fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
@ -342,16 +337,4 @@ export class ZrleDecoder {
}); });
} }
// Apply color to a rect on buffer
applyColor(tw, th, tx, ty, screenW, screenH, color, fb) {
for (let h = 0; h < th; h++) {
for (let w = 0; w < tw; w++) {
const fbBytePosOffset = this.getPixelBytePos(tx + w, ty + h, screenW, screenH);
fb.writeUInt8(color.b || 255, fbBytePosOffset);
fb.writeUInt8(color.g || 255, fbBytePosOffset + 1);
fb.writeUInt8(color.r || 255, fbBytePosOffset + 2);
fb.writeUInt8(255, fbBytePosOffset + 3);
}
}
}
} }

View file

@ -1,9 +1,11 @@
/// this is a pretty poor name. /// this is a pretty poor name.
export class SocketBuffer { export class SocketBuffer {
public buffer?: Buffer; public buffer: Buffer;
private offset: number; public offset: number; // :(
constructor() { constructor() {
this.buffer = Buffer.from([]);
this.offset = 0;
this.flush(); this.flush();
} }
@ -21,11 +23,11 @@ export class SocketBuffer {
return this.buffer.toString(); return this.buffer.toString();
} }
includes(check) { includes(check: Buffer|number|string) {
return this.buffer.includes(check); return this.buffer.includes(check);
} }
pushData(data) { pushData(data: Buffer) {
this.buffer = Buffer.concat([this.buffer, data]); this.buffer = Buffer.concat([this.buffer, data]);
} }
@ -77,17 +79,17 @@ export class SocketBuffer {
return data; return data;
} }
readNBytes(bytes, offset = this.offset) { readNBytes(bytes: number, offset = this.offset) {
return this.buffer.slice(offset, offset + bytes); return this.buffer.slice(offset, offset + bytes);
} }
readNBytesOffset(bytes) { readNBytesOffset(bytes: number) {
const data = this.buffer.slice(this.offset, this.offset + bytes); const data = this.buffer.slice(this.offset, this.offset + bytes);
this.offset += bytes; this.offset += bytes;
return data; return data;
} }
setOffset(n) { setOffset(n: number) {
this.offset = n; this.offset = n;
} }
@ -96,7 +98,7 @@ export class SocketBuffer {
} }
// name is nullable because there are Many(yay....) times it just isn't passed // name is nullable because there are Many(yay....) times it just isn't passed
waitBytes(bytes, name: any | null = null): Promise<void> { async waitBytes(bytes: number, name: any | null = null): Promise<void> {
if (this.bytesLeft() >= bytes) { if (this.bytesLeft() >= bytes) {
return; return;
} }
@ -114,17 +116,17 @@ export class SocketBuffer {
}); });
} }
fill(data) { fill(data: Buffer) {
this.buffer.fill(data, this.offset, this.offset + data.length); this.buffer.fill(data, this.offset, this.offset + data.length);
this.offset += data.length; this.offset += data.length;
} }
fillMultiple(data, repeats) { fillMultiple(data: Buffer, repeats: number) {
this.buffer.fill(data, this.offset, this.offset + data.length * repeats); this.buffer.fill(data, this.offset, this.offset + data.length * repeats);
this.offset += data.length * repeats; this.offset += data.length * repeats;
} }
sleep(n): Promise<void> { sleep(n: number): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(resolve, n); setTimeout(resolve, n);
}); });

44
qemu/src/rfb/types.ts Normal file
View file

@ -0,0 +1,44 @@
export type Rect = {
x: number,
y: number,
width: number,
height: number,
}
export type VncRectangle = Rect & {
encoding: number,
data: Buffer | null // ?
};
export type PixelFormat = {
bitsPerPixel: number,
depth: number,
bigEndianFlag: number,
trueColorFlag: number,
redMax: number,
greenMax: number,
blueMax: number,
redShift: number,
blueShift: number,
greenShift: number
}
export type Cursor = Rect & {
cursorPixels: Buffer|null,
bitmask: Buffer|null,
posX: number,
posY: number
}
export type Color3 = {
r: number,
g: number,
b: number
}
export type Color4 = Color3 & {
a: number,
};

View file

@ -4,14 +4,29 @@
"private": "true", "private": "true",
"description": "crusttest shared bits", "description": "crusttest shared bits",
"type": "module", "type": "module",
"main": "dist/src/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [ "files": [
"dist" "dist"
], ],
"devDependencies": {}, "targets": {
"types": {},
"shared":{
"context": "browser",
"isLibrary": true,
"outputFormat": "esmodule"
}
},
"dependencies": {
},
"devDependencies": {
"parcel": "^2.12.0"
},
"scripts": { "scripts": {
"build": "tsc" "build": "parcel build src/index.ts --target shared --target types"
}, },
"author": "", "author": "",
"license": "ISC" "license": "ISC"

View file

@ -103,84 +103,90 @@ export type DeserializedMessage = AnyMessage;
export const kProtocolHeaderSize = 8; export const kProtocolHeaderSize = 8;
export class MessageEncoder { export class MessageEncoder {
private struct: Struct; private struct: Struct|null = null;
private buffer: ArrayBuffer; private buffer: ArrayBuffer|null = null;
Init(byteSize) { Init(byteSize: number) {
this.buffer = new ArrayBuffer(byteSize + kProtocolHeaderSize); this.buffer = new ArrayBuffer(byteSize + kProtocolHeaderSize);
this.struct = new Struct(this.buffer); this.struct = new Struct(this.buffer);
this.InitHeader(); this.InitHeader();
} }
SetKeyMessage(keysym, pressed) { SetKeyMessage(keysym: number, pressed: boolean) {
this.SetTypeCode(MessageType.Key); this.SetTypeCode(MessageType.Key);
this.struct.WriteU16(keysym); this.struct?.WriteU16(keysym);
this.struct.WriteU8(pressed == true ? 1 : 0); this.struct?.WriteU8(pressed == true ? 1 : 0);
} }
SetMouseMessage(x, y, buttons: MouseButtons) { SetMouseMessage(x: number, y: number, buttons: MouseButtons) {
this.SetTypeCode(MessageType.Mouse); this.SetTypeCode(MessageType.Mouse);
this.struct.WriteU16(x); this.struct?.WriteU16(x);
this.struct.WriteU16(y); this.struct?.WriteU16(y);
this.struct.WriteU8(buttons); this.struct?.WriteU8(buttons);
} }
SetTurnMessage() { SetTurnMessage() {
this.SetTypeCode(MessageType.Turn); this.SetTypeCode(MessageType.Turn);
} }
SetTurnSrvMessage(ms, usersQueue) { SetTurnSrvMessage(ms: number, usersQueue: Array<string>) {
this.SetTypeCode(MessageType.Turn); this.SetTypeCode(MessageType.Turn);
this.struct.WriteU32(ms); this.struct?.WriteU32(ms);
this.struct.WriteArray(usersQueue, this.struct.WriteString); this.struct?.WriteArray(usersQueue, this.struct?.WriteString);
} }
SetDisplayRectMessage(x, y, buffer: ArrayBuffer) { SetDisplayRectMessage(x: number, y: number, buffer: ArrayBuffer) {
this.SetTypeCode(MessageType.DisplayRect); this.SetTypeCode(MessageType.DisplayRect);
this.struct.WriteU16(x); this.struct?.WriteU16(x);
this.struct.WriteU16(y); this.struct?.WriteU16(y);
this.struct.WriteBuffer(buffer); this.struct?.WriteBuffer(buffer);
} }
SetDisplaySizeMessage(w, h) { SetDisplaySizeMessage(w: number, h: number) {
this.SetTypeCode(MessageType.DisplaySize); this.SetTypeCode(MessageType.DisplaySize);
this.struct.WriteU16(w); this.struct?.WriteU16(w);
this.struct.WriteU16(h); this.struct?.WriteU16(h);
} }
SetAddUserMessage(user: string) { SetAddUserMessage(user: string) {
this.SetTypeCode(MessageType.AddUser); this.SetTypeCode(MessageType.AddUser);
this.struct.WriteString(user); this.struct?.WriteString(user);
} }
SetRemUserMessage(user: string) { SetRemUserMessage(user: string) {
this.SetTypeCode(MessageType.RemUser); this.SetTypeCode(MessageType.RemUser);
this.struct.WriteString(user); this.struct?.WriteString(user);
} }
// Setup some stuff and then return the final message // Setup some stuff and then return the final message
Finish() { Finish() {
let endOffset = this.struct.Tell(); if(this.struct == null || this.buffer == null)
this.struct.Seek(4); // seek to size offset throw new Error('no');
this.struct.WriteU32(endOffset - kProtocolHeaderSize);
this.struct.Seek(endOffset); let endOffset :number = this.struct?.Tell();
return this.buffer.slice(0, endOffset); this.struct?.Seek(4); // seek to size offset
this.struct?.WriteU32(endOffset - kProtocolHeaderSize);
this.struct?.Seek(endOffset);
return this.buffer?.slice(0, endOffset);
} }
private InitHeader() { private InitHeader() {
this.struct.Seek(0); this.struct?.Seek(0);
this.struct.WriteU16(kProtocolMagic); this.struct?.WriteU16(kProtocolMagic);
this.struct.WriteU16(0); // No message type yet this.struct?.WriteU16(0); // No message type yet
this.struct.WriteU32(0); // No payload size yet this.struct?.WriteU32(0); // No payload size yet
} }
private SetTypeCode(type: MessageType) { private SetTypeCode(type: MessageType) {
let oldOff = this.struct.Tell(); if(this.struct == null)
this.struct.Seek(2); // seek to type offset throw new Error('no');
this.struct.WriteU16(type);
this.struct.Seek(oldOff); let oldOff = this.struct?.Tell();
this.struct?.Seek(2); // seek to type offset
this.struct?.WriteU16(type);
this.struct?.Seek(oldOff);
} }
} }
@ -189,14 +195,17 @@ export class MessageDecoder {
static async ReadMessage(buffer: ArrayBuffer, asClient: boolean): Promise<DeserializedMessage> { static async ReadMessage(buffer: ArrayBuffer, asClient: boolean): Promise<DeserializedMessage> {
return new Promise((res, rej) => { return new Promise((res, rej) => {
MessageDecoder.ReadMessageSync(buffer, asClient, (err: Error, message: DeserializedMessage) => { MessageDecoder.ReadMessageSync(buffer, asClient, (err: Error|null, message: DeserializedMessage|null) => {
if (err) rej(err); if (err) rej(err);
if(message != null) {
res(message); res(message);
}
}); });
}); });
} }
private static ReadMessageSync(buffer: ArrayBuffer, asClient: boolean, callback: (err: Error, message:DeserializedMessage) => void) { private static ReadMessageSync(buffer: ArrayBuffer, asClient: boolean, callback: (err: Error|null, message: DeserializedMessage|null) => void) {
let struct = new Struct(buffer); let struct = new Struct(buffer);
// Read and verify the header // Read and verify the header

View file

@ -36,7 +36,7 @@ export class Struct {
return s; return s;
} }
ReadStringLen(maxStringLength) { ReadStringLen(maxStringLength: number) {
let stringLength = this.ReadU32(); let stringLength = this.ReadU32();
let s = ''; let s = '';
@ -97,20 +97,21 @@ export class Struct {
// then copying // then copying
// Add an array with a fixed type // Add an array with a fixed type
WriteArray(arr, functor) { WriteArray(arr: any[], functor: any) {
this.WriteU32(arr.length); this.WriteU32(arr.length);
for (let elem of arr) functor.call(this, elem); for (let elem of arr) functor.call(this, elem);
} }
// Add a pascal UTF-16 string. // Add a pascal UTF-16 string.
WriteString(str) { WriteString(str: string) {
this.WriteU32(str.length); this.WriteU32(str.length);
for (let i in str) this.WriteU16(str.charCodeAt(i)); for (var i = 0; i < str.length; ++i)
this.WriteU16(str.charCodeAt(i));
} }
// writes a string with a max length. // writes a string with a max length.
// will trim strings that are too long // will trim strings that are too long
WriteStringLen(str, len) { WriteStringLen(str: string, len: number) {
let length = len; let length = len;
// pick the string length, but ONLY // pick the string length, but ONLY
@ -125,38 +126,39 @@ export class Struct {
this.WriteU16(str.charCodeAt(i)); this.WriteU16(str.charCodeAt(i));
} }
WriteU8(i) { WriteU8(i: number) {
this.dv.setUint8(this.byteOffset, i); this.dv.setUint8(this.byteOffset, i);
this.byteOffset++; this.byteOffset++;
} }
WriteS8(i) { WriteS8(i: number) {
this.dv.setInt8(this.byteOffset, i); this.dv.setInt8(this.byteOffset, i);
this.byteOffset++; this.byteOffset++;
} }
WriteU16(i) { WriteU16(i: number) {
this.dv.setUint16(this.byteOffset, i, false); this.dv.setUint16(this.byteOffset, i, false);
this.byteOffset += 2; this.byteOffset += 2;
} }
WriteS16(i) { WriteS16(i: number) {
this.dv.setInt16(this.byteOffset, i, false); this.dv.setInt16(this.byteOffset, i, false);
this.byteOffset += 2; this.byteOffset += 2;
} }
WriteU32(i) { WriteU32(i: number) {
this.dv.setUint32(this.byteOffset, i, false); this.dv.setUint32(this.byteOffset, i, false);
this.byteOffset += 4; this.byteOffset += 4;
} }
WriteS32(i) { WriteS32(i: number) {
this.dv.setInt32(this.byteOffset, i, false); this.dv.setInt32(this.byteOffset, i, false);
this.byteOffset += 4; this.byteOffset += 4;
} }
WriteBuffer(buffer: ArrayBuffer) { WriteBuffer(buffer: ArrayBuffer) {
let u8ar = new Uint8Array(buffer);
this.WriteU32(buffer.byteLength); this.WriteU32(buffer.byteLength);
for (let i = 0; i < buffer.byteLength; ++i) this.WriteU8(buffer[i]); for (let i = 0; i < buffer.byteLength; ++i) this.WriteU8(u8ar[i]);
} }
} }

View file

@ -1,13 +0,0 @@
// This is the base tsconfig
{
"compilerOptions": {
"target": "ES2021",
"module": "ES2020",
"moduleResolution": "Node",
"declaration": true,
"sourceMap": true,
// more compiler options?
"strict": false, // maybe enable later..?
}
}

View file

@ -1,27 +1,10 @@
// This is the base tsconfig the entire Socket2 project uses
{ {
"files": [],
"compilerOptions": { "compilerOptions": {
"declaration": true, "target": "ES2022",
"declarationMap": true, "module": "ES2022",
"noEmitOnError": true, "moduleResolution": "Node",
"skipLibCheck": true, "allowSyntheticDefaultImports": true,
"baseUrl": "./", "strict": true,
}
"paths": {
"@socketcomputer/shared*": [ "shared/src/*" ],
"@socketcomputer/backend*": [ "backend/src/*" ],
"@socketcomputer/qemu*": [ "qemu/src/*" ]
},
},
"exclude": [
"node_modules",
"dist"
],
"references": [
{ "path": "./backend" },
{ "path": "./qemu" },
{ "path": "./shared" },
]
} }

View file

@ -10,11 +10,8 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@parcel/transformer-sass": "^2.12.0", "parcel": "^2.12.0"
"parcel": "^2.12.0",
"typescript": "^5.4.3"
}, },
"dependencies": { "dependencies": {
"nanoevents": "^9.0.0"
} }
} }

View file

@ -3,12 +3,10 @@ import * as Shared from '@socketcomputer/shared';
import {GetKeysym} from "./keyboard"; import {GetKeysym} from "./keyboard";
import {Mouse} from "./mouse"; import {Mouse} from "./mouse";
type UserRecord = { type UserRecord = {
username: string username: string
}; };
let turnInt: number = -1;
async function sleep(ms: number) : Promise<void> { async function sleep(ms: number) : Promise<void> {
return new Promise((res) => { return new Promise((res) => {
@ -16,7 +14,10 @@ async function sleep(ms: number) : Promise<void> {
}); });
} }
function waitingTimer(text, ms, dot: boolean = true) {
let turnInt: number = -1;
function waitingTimer(text: string, ms: number, dot: boolean = true) {
let dots = ''; let dots = '';
let timer = document.querySelector('.turn-timer') as HTMLDivElement; let timer = document.querySelector('.turn-timer') as HTMLDivElement;
@ -24,6 +25,7 @@ function waitingTimer(text, ms, dot: boolean = true) {
clearInterval(turnInt); clearInterval(turnInt);
} }
// @ts-ignore (for some reason it's assuming these are Node)
turnInt = setInterval(() => { turnInt = setInterval(() => {
ms -= 1000; ms -= 1000;
let seconds = Math.floor(ms / 1000); let seconds = Math.floor(ms / 1000);
@ -47,7 +49,7 @@ function waitingTimer(text, ms, dot: boolean = true) {
// client for // client for
class SocketClient { class SocketClient {
private websocket: WebSocket = null; private websocket: WebSocket|null = null;
private url = ""; private url = "";
private selfNamed = false; private selfNamed = false;
@ -57,8 +59,8 @@ class SocketClient {
private hasTurn = false; private hasTurn = false;
private mouse = new Mouse(); private mouse = new Mouse();
private canvas:HTMLCanvasElement = null; private canvas:HTMLCanvasElement|null = null;
private canvasCtx : CanvasRenderingContext2D = null; private canvasCtx : CanvasRenderingContext2D|null = null;
constructor(url: string, canvas: HTMLCanvasElement) { constructor(url: string, canvas: HTMLCanvasElement) {
@ -219,9 +221,9 @@ class SocketClient {
} }
private async onWsClose() { private async onWsClose() {
this.websocket.removeEventListener("open", this.onWsOpen); this.websocket?.removeEventListener("open", this.onWsOpen);
this.websocket.removeEventListener("message", this.onWsMessage); this.websocket?.removeEventListener("message", this.onWsMessage);
this.websocket.removeEventListener("close", this.onWsClose); this.websocket?.removeEventListener("close", this.onWsClose);
this.websocket = null; this.websocket = null;
// reset state // reset state
@ -245,7 +247,7 @@ class SocketClient {
async SendBuffer(buffer: ArrayBuffer): Promise<void> { async SendBuffer(buffer: ArrayBuffer): Promise<void> {
return new Promise((res, rej) => { return new Promise((res, rej) => {
this.websocket.send(buffer); this.websocket?.send(buffer);
res(); res();
}); });
} }
@ -275,8 +277,10 @@ class SocketClient {
} }
private resizeDisplay(message: Shared.DisplaySizeMessage) { private resizeDisplay(message: Shared.DisplaySizeMessage) {
this.canvas.width = message.width; if(this.canvas == null)
this.canvas.height = message.height; return;
this.canvas!.width = message.width;
this.canvas!.height = message.height;
} }
private updateUserCount() { private updateUserCount() {
@ -327,7 +331,7 @@ class SocketClient {
let blob = new Blob([message.data]); let blob = new Blob([message.data]);
createImageBitmap(blob) createImageBitmap(blob)
.then((image) => { .then((image) => {
this.canvasCtx.drawImage(image, message.x, message.y); this.canvasCtx?.drawImage(image, message.x, message.y);
}).catch((err) => { }).catch((err) => {
console.error(`Error decoding rect for some reason...`, err); console.error(`Error decoding rect for some reason...`, err);
}); });

View file

@ -1,19 +1,6 @@
{ {
"extends": "../tsconfig-base.json", "extends": "../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"composite": true, "lib": ["DOM"],
"esModuleInterop": true, }
"experimentalDecorators": true,
"lib": ["DOM", "ESNext"],
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES6",
"outDir": "./dist",
"baseUrl": "."
},
"references": [
{ "path": "../shared" }
]
} }

323
yarn.lock
View file

@ -83,11 +83,36 @@
dependencies: dependencies:
"@lezer/common" "^1.0.0" "@lezer/common" "^1.0.0"
"@lmdb/lmdb-darwin-arm64@2.8.5":
version "2.8.5"
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.8.5.tgz#895d8cb16a9d709ce5fedd8b60022903b875e08e"
integrity sha512-KPDeVScZgA1oq0CiPBcOa3kHIqU+pTOwRFDIhxvmf8CTNvqdZQYp5cCKW0bUk69VygB2PuTiINFWbY78aR2pQw==
"@lmdb/lmdb-darwin-x64@2.8.5":
version "2.8.5"
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.8.5.tgz#ca243534c8b37d5516c557e4624256d18dd63184"
integrity sha512-w/sLhN4T7MW1nB3R/U8WK5BgQLz904wh+/SmA2jD8NnF7BLLoUgflCNxOeSPOWp8geP6nP/+VjWzZVip7rZ1ug==
"@lmdb/lmdb-linux-arm64@2.8.5":
version "2.8.5"
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.8.5.tgz#b44a8023057e21512eefb9f6120096843b531c1e"
integrity sha512-vtbZRHH5UDlL01TT5jB576Zox3+hdyogvpcbvVJlmU5PdL3c5V7cj1EODdh1CHPksRl+cws/58ugEHi8bcj4Ww==
"@lmdb/lmdb-linux-arm@2.8.5":
version "2.8.5"
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.8.5.tgz#17bd54740779c3e4324e78e8f747c21416a84b3d"
integrity sha512-c0TGMbm2M55pwTDIfkDLB6BpIsgxV4PjYck2HiOX+cy/JWiBXz32lYbarPqejKs9Flm7YVAKSILUducU9g2RVg==
"@lmdb/lmdb-linux-x64@2.8.5": "@lmdb/lmdb-linux-x64@2.8.5":
version "2.8.5" version "2.8.5"
resolved "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.8.5.tgz" resolved "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.8.5.tgz"
integrity sha512-Xkc8IUx9aEhP0zvgeKy7IQ3ReX2N8N1L0WPcQwnZweWmOuKfwpS3GRIYqLtK5za/w3E60zhFfNdS+3pBZPytqQ== integrity sha512-Xkc8IUx9aEhP0zvgeKy7IQ3ReX2N8N1L0WPcQwnZweWmOuKfwpS3GRIYqLtK5za/w3E60zhFfNdS+3pBZPytqQ==
"@lmdb/lmdb-win32-x64@2.8.5":
version "2.8.5"
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.8.5.tgz#8233e8762440b0f4632c47a09b1b6f23de8b934c"
integrity sha512-4wvrf5BgnR8RpogHhtpCPJMKBmvyZPhhUtEwMJbXh0ni2BucpfF07jlmyM11zRqQ2XIq6PbC2j7W7UCCcm1rRQ==
"@mapbox/node-pre-gyp@^1.0.0": "@mapbox/node-pre-gyp@^1.0.0":
version "1.0.11" version "1.0.11"
resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz" resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz"
@ -112,11 +137,36 @@
"@lezer/lr" "^1.0.0" "@lezer/lr" "^1.0.0"
json5 "^2.2.1" json5 "^2.2.1"
"@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz#44d752c1a2dc113f15f781b7cc4f53a307e3fa38"
integrity sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==
"@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz#f954f34355712212a8e06c465bc06c40852c6bb3"
integrity sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==
"@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz#45c63037f045c2b15c44f80f0393fa24f9655367"
integrity sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==
"@msgpackr-extract/msgpackr-extract-linux-arm@3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz#35707efeafe6d22b3f373caf9e8775e8920d1399"
integrity sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==
"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.2": "@msgpackr-extract/msgpackr-extract-linux-x64@3.0.2":
version "3.0.2" version "3.0.2"
resolved "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz" resolved "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz"
integrity sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA== integrity sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==
"@msgpackr-extract/msgpackr-extract-win32-x64@3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz#0f164b726869f71da3c594171df5ebc1c4b0a407"
integrity sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==
"@parcel/bundler-default@2.12.0": "@parcel/bundler-default@2.12.0":
version "2.12.0" version "2.12.0"
resolved "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.12.0.tgz" resolved "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.12.0.tgz"
@ -190,7 +240,7 @@
"@parcel/transformer-react-refresh-wrap" "2.12.0" "@parcel/transformer-react-refresh-wrap" "2.12.0"
"@parcel/transformer-svg" "2.12.0" "@parcel/transformer-svg" "2.12.0"
"@parcel/core@^2.12.0", "@parcel/core@2.12.0": "@parcel/core@2.12.0":
version "2.12.0" version "2.12.0"
resolved "https://registry.npmjs.org/@parcel/core/-/core-2.12.0.tgz" resolved "https://registry.npmjs.org/@parcel/core/-/core-2.12.0.tgz"
integrity sha512-s+6pwEj+GfKf7vqGUzN9iSEPueUssCCQrCBUlcAfKrJe0a22hTUCjewpB0I7lNrCIULt8dkndD+sMdOrXsRl6Q== integrity sha512-s+6pwEj+GfKf7vqGUzN9iSEPueUssCCQrCBUlcAfKrJe0a22hTUCjewpB0I7lNrCIULt8dkndD+sMdOrXsRl6Q==
@ -415,6 +465,13 @@
"@parcel/utils" "2.12.0" "@parcel/utils" "2.12.0"
posthtml "^0.16.4" posthtml "^0.16.4"
"@parcel/packager-ts@2.12.0":
version "2.12.0"
resolved "https://registry.yarnpkg.com/@parcel/packager-ts/-/packager-ts-2.12.0.tgz#7422c07ff3a327fdb592f6d707d31bc146590a17"
integrity sha512-8wR0BNN2NBD+IIU0tjioK+lRD4p2Qi/fKxDH5ixEW912tRV+Vd4kE8k++U6YQIpSlK4FRnjFod5zYYhNSLuiXg==
dependencies:
"@parcel/plugin" "2.12.0"
"@parcel/packager-wasm@2.12.0": "@parcel/packager-wasm@2.12.0":
version "2.12.0" version "2.12.0"
resolved "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.12.0.tgz" resolved "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.12.0.tgz"
@ -667,6 +724,25 @@
posthtml-render "^3.0.0" posthtml-render "^3.0.0"
semver "^7.5.2" semver "^7.5.2"
"@parcel/transformer-typescript-types@2.12.0":
version "2.12.0"
resolved "https://registry.yarnpkg.com/@parcel/transformer-typescript-types/-/transformer-typescript-types-2.12.0.tgz#63e3fc4d1c5d61e1d3a2d56ff58454cf58b514ca"
integrity sha512-uxF4UBMYvbjiV3zHTWMrZX8cFD92VUvD3ArcGi5WEtuVROUm9Sc47o0mOzxKfMFlJu2KOfZVHYlzK9f/UKA2kQ==
dependencies:
"@parcel/diagnostic" "2.12.0"
"@parcel/plugin" "2.12.0"
"@parcel/source-map" "^2.1.1"
"@parcel/ts-utils" "2.12.0"
"@parcel/utils" "2.12.0"
nullthrows "^1.1.1"
"@parcel/ts-utils@2.12.0":
version "2.12.0"
resolved "https://registry.yarnpkg.com/@parcel/ts-utils/-/ts-utils-2.12.0.tgz#47878a6f3baff77d2fa6f9878fe235c9c5d75da8"
integrity sha512-zou+W6dcqnXXUOfN5zGM+ePIWbYOhGp8bVB2jICoNkoKmNAHd4l4zeHl5yQXnbZfynVw88cZVqxtXS8tYebelg==
dependencies:
nullthrows "^1.1.1"
"@parcel/types@2.12.0": "@parcel/types@2.12.0":
version "2.12.0" version "2.12.0"
resolved "https://registry.npmjs.org/@parcel/types/-/types-2.12.0.tgz" resolved "https://registry.npmjs.org/@parcel/types/-/types-2.12.0.tgz"
@ -694,6 +770,41 @@
chalk "^4.1.0" chalk "^4.1.0"
nullthrows "^1.1.1" nullthrows "^1.1.1"
"@parcel/watcher-android-arm64@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz#c2c19a3c442313ff007d2d7a9c2c1dd3e1c9ca84"
integrity sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==
"@parcel/watcher-darwin-arm64@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz#c817c7a3b4f3a79c1535bfe54a1c2818d9ffdc34"
integrity sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==
"@parcel/watcher-darwin-x64@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz#1a3f69d9323eae4f1c61a5f480a59c478d2cb020"
integrity sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==
"@parcel/watcher-freebsd-x64@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz#0d67fef1609f90ba6a8a662bc76a55fc93706fc8"
integrity sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==
"@parcel/watcher-linux-arm-glibc@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz#ce5b340da5829b8e546bd00f752ae5292e1c702d"
integrity sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==
"@parcel/watcher-linux-arm64-glibc@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz#6d7c00dde6d40608f9554e73998db11b2b1ff7c7"
integrity sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==
"@parcel/watcher-linux-arm64-musl@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz#bd39bc71015f08a4a31a47cd89c236b9d6a7f635"
integrity sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==
"@parcel/watcher-linux-x64-glibc@2.4.1": "@parcel/watcher-linux-x64-glibc@2.4.1":
version "2.4.1" version "2.4.1"
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz" resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz"
@ -704,6 +815,21 @@
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz" resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz"
integrity sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ== integrity sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==
"@parcel/watcher-win32-arm64@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz#eb4deef37e80f0b5e2f215dd6d7a6d40a85f8adc"
integrity sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==
"@parcel/watcher-win32-ia32@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz#94fbd4b497be39fd5c8c71ba05436927842c9df7"
integrity sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==
"@parcel/watcher-win32-x64@2.4.1":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz#4bf920912f67cae5f2d264f58df81abfea68dadf"
integrity sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==
"@parcel/watcher@^2.0.7": "@parcel/watcher@^2.0.7":
version "2.4.1" version "2.4.1"
resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz" resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz"
@ -739,35 +865,30 @@
"@parcel/utils" "2.12.0" "@parcel/utils" "2.12.0"
nullthrows "^1.1.1" nullthrows "^1.1.1"
"@socketcomputer/backend@file:/home/lily/source/socket-revamp/backend": "@swc/core-darwin-arm64@1.4.11":
version "1.0.0" version "1.4.11"
resolved "file:backend" resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.11.tgz#91ef40816e10495a4038a98dc6c8dfcc85d9c59b"
dependencies: integrity sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==
"@fastify/websocket" "^10.0.1"
"@julusian/jpeg-turbo" "^2.1.0"
"@socketcomputer/qemu" "*"
"@socketcomputer/shared" "*"
canvas "^2.11.2"
fastify "^4.26.2"
mnemonist "^0.39.8"
"@socketcomputer/qemu@*", "@socketcomputer/qemu@file:/home/lily/source/socket-revamp/qemu": "@swc/core-darwin-x64@1.4.11":
version "1.0.0" version "1.4.11"
resolved "file:qemu" resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.11.tgz#6f71e3cd4687ef5df226ba0b8a20adc52fa7dc9e"
dependencies: integrity sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==
canvas "^2.11.2"
execa "^8.0.1"
split "^1.0.1"
"@socketcomputer/shared@*", "@socketcomputer/shared@file:/home/lily/source/socket-revamp/shared": "@swc/core-linux-arm-gnueabihf@1.4.11":
version "1.0.0" version "1.4.11"
resolved "file:shared" resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.11.tgz#08521822b5510cb506bc49e728f416636ff0306f"
integrity sha512-XJLB71uw0rog4DjYAPxFGAuGCBQpgJDlPZZK6MTmZOvI/1t0+DelJ24IjHIxk500YYM26Yv47xPabqFPD7I2zQ==
"@socketcomputer/webapp@file:/home/lily/source/socket-revamp/webapp": "@swc/core-linux-arm64-gnu@1.4.11":
version "1.0.0" version "1.4.11"
resolved "file:webapp" resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.11.tgz#9485bc591aa573b282d08b168b80a60badb8df9b"
dependencies: integrity sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==
nanoevents "^9.0.0"
"@swc/core-linux-arm64-musl@1.4.11":
version "1.4.11"
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.11.tgz#85eecad7aaab7e94b1ff15ab9d95e80a1e95f356"
integrity sha512-eV+KduiRYUFjPsvbZuJ9aknQH9Tj0U2/G9oIZSzLx/18WsYi+upzHbgxmIIHJ2VJgfd7nN40RI/hMtxNsUzR/g==
"@swc/core-linux-x64-gnu@1.4.11": "@swc/core-linux-x64-gnu@1.4.11":
version "1.4.11" version "1.4.11"
@ -779,6 +900,21 @@
resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz" resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz"
integrity sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA== integrity sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==
"@swc/core-win32-arm64-msvc@1.4.11":
version "1.4.11"
resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.11.tgz#d836b79d8730bf83e6b38a5b888e83944d6fb233"
integrity sha512-35khwkyly7lF5NDSyvIrukBMzxPorgc5iTSDfVO/LvnmN5+fm4lTlrDr4tUfTdOhv3Emy7CsKlsNAeFRJ+Pm+w==
"@swc/core-win32-ia32-msvc@1.4.11":
version "1.4.11"
resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.11.tgz#bc60bbdc65134aaa5b214e2aaf209acfce401d17"
integrity sha512-Wx8/6f0ufgQF2pbVPsJ2dAmFLwIOW+xBE5fxnb7VnEbGkTgP1qMDWiiAtD9rtvDSuODG3i1AEmAak/2HAc6i6A==
"@swc/core-win32-x64-msvc@1.4.11":
version "1.4.11"
resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.11.tgz#92fd6d4e2d70bbd4fda438f02310d998db8c7b7c"
integrity sha512-0xRFW6K9UZQH2NVC/0pVB0GJXS45lY24f+6XaPBF1YnMHd8A8GoHl7ugyM5yNUTe2AKhSgk5fJV00EJt/XBtdQ==
"@swc/core@^1.3.36": "@swc/core@^1.3.36":
version "1.4.11" version "1.4.11"
resolved "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz" resolved "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz"
@ -829,6 +965,21 @@
dependencies: dependencies:
undici-types "~5.26.4" undici-types "~5.26.4"
"@types/split@^1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@types/split/-/split-1.0.5.tgz#4bd47164b81d6381db37978d5344b374b6825f6c"
integrity sha512-gMiDr4vA6YofTpAkPQtP+5pvStIf3CMYphf32YAG/3RwogNL8ii1CQKDc+sxN62KuxPoRaJXcf2zDCDkEBH4FA==
dependencies:
"@types/node" "*"
"@types/through" "*"
"@types/through@*":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.33.tgz#14ebf599320e1c7851e7d598149af183c6b9ea56"
integrity sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==
dependencies:
"@types/node" "*"
"@types/ws@^8.5.10": "@types/ws@^8.5.10":
version "8.5.10" version "8.5.10"
resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz" resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz"
@ -1011,7 +1162,7 @@ braces@^3.0.2, braces@~3.0.2:
dependencies: dependencies:
fill-range "^7.0.1" fill-range "^7.0.1"
browserslist@^4.6.6, "browserslist@>= 4.21.0": browserslist@^4.6.6:
version "4.23.0" version "4.23.0"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz"
integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
@ -1029,6 +1180,11 @@ buffer@^6.0.3:
base64-js "^1.3.1" base64-js "^1.3.1"
ieee754 "^1.2.1" ieee754 "^1.2.1"
builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==
callsites@^3.0.0: callsites@^3.0.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
@ -1137,16 +1293,16 @@ color-convert@^2.0.1:
dependencies: dependencies:
color-name "~1.1.4" color-name "~1.1.4"
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-name@1.1.3: color-name@1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-support@^1.1.2, color-support@^1.1.3: color-support@^1.1.2, color-support@^1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz"
@ -1229,7 +1385,7 @@ csso@^4.2.0:
dependencies: dependencies:
css-tree "^1.1.2" css-tree "^1.1.2"
debug@^4, debug@^4.0.0, debug@4: debug@4, debug@^4, debug@^4.0.0:
version "4.3.4" version "4.3.4"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@ -1263,12 +1419,7 @@ detect-libc@^1.0.3:
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz" resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz"
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
detect-libc@^2.0.0: detect-libc@^2.0.0, detect-libc@^2.0.1:
version "2.0.3"
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz"
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
detect-libc@^2.0.1:
version "2.0.3" version "2.0.3"
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz" resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz"
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
@ -1527,6 +1678,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
gauge@^3.0.0: gauge@^3.0.0:
version "3.0.2" version "3.0.2"
resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz" resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz"
@ -1675,7 +1831,7 @@ inflight@^1.0.4:
once "^1.3.0" once "^1.3.0"
wrappy "1" wrappy "1"
inherits@^2.0.3, inherits@2: inherits@2, inherits@^2.0.3, inherits@^2.0.4:
version "2.0.4" version "2.0.4"
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@ -1791,6 +1947,36 @@ light-my-request@^5.11.0:
process-warning "^3.0.0" process-warning "^3.0.0"
set-cookie-parser "^2.4.1" set-cookie-parser "^2.4.1"
lightningcss-darwin-arm64@1.24.1:
version "1.24.1"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.24.1.tgz#551735defa1e092ecf91244ca081f65f10ebd5f0"
integrity sha512-1jQ12jBy+AE/73uGQWGSafK5GoWgmSiIQOGhSEXiFJSZxzV+OXIx+a9h2EYHxdJfX864M+2TAxWPWb0Vv+8y4w==
lightningcss-darwin-x64@1.24.1:
version "1.24.1"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.24.1.tgz#5acb1338ac0aae38e405efd854ed97ba11509eea"
integrity sha512-R4R1d7VVdq2mG4igMU+Di8GPf0b64ZLnYVkubYnGG0Qxq1KaXQtAzcLI43EkpnoWvB/kUg8JKCWH4S13NfiLcQ==
lightningcss-freebsd-x64@1.24.1:
version "1.24.1"
resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.24.1.tgz#ff692c41ed0bbf37ab5a239db4c2fc04c11195e6"
integrity sha512-z6NberUUw5ALES6Ixn2shmjRRrM1cmEn1ZQPiM5IrZ6xHHL5a1lPin9pRv+w6eWfcrEo+qGG6R9XfJrpuY3e4g==
lightningcss-linux-arm-gnueabihf@1.24.1:
version "1.24.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.24.1.tgz#ba41556f4422a6a889553ad897898a314386153e"
integrity sha512-NLQLnBQW/0sSg74qLNI8F8QKQXkNg4/ukSTa+XhtkO7v3BnK19TS1MfCbDHt+TTdSgNEBv0tubRuapcKho2EWw==
lightningcss-linux-arm64-gnu@1.24.1:
version "1.24.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.24.1.tgz#6b569b6078634233bc470c4179dd67e535f22d73"
integrity sha512-AQxWU8c9E9JAjAi4Qw9CvX2tDIPjgzCTrZCSXKELfs4mCwzxRkHh2RCxX8sFK19RyJoJAjA/Kw8+LMNRHS5qEg==
lightningcss-linux-arm64-musl@1.24.1:
version "1.24.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.24.1.tgz#644abd32c09c87228bfb5dda21e8d3f75da6f731"
integrity sha512-JCgH/SrNrhqsguUA0uJUM1PvN5+dVuzPIlXcoWDHSv2OU/BWlj2dUYr3XNzEw748SmNZPfl2NjQrAdzaPOn1lA==
lightningcss-linux-x64-gnu@1.24.1: lightningcss-linux-x64-gnu@1.24.1:
version "1.24.1" version "1.24.1"
resolved "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.24.1.tgz" resolved "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.24.1.tgz"
@ -1801,6 +1987,11 @@ lightningcss-linux-x64-musl@1.24.1:
resolved "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.24.1.tgz" resolved "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.24.1.tgz"
integrity sha512-HLfzVik3RToot6pQ2Rgc3JhfZkGi01hFetHt40HrUMoeKitLoqUUT5owM6yTZPTytTUW9ukLBJ1pc3XNMSvlLw== integrity sha512-HLfzVik3RToot6pQ2Rgc3JhfZkGi01hFetHt40HrUMoeKitLoqUUT5owM6yTZPTytTUW9ukLBJ1pc3XNMSvlLw==
lightningcss-win32-x64-msvc@1.24.1:
version "1.24.1"
resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.24.1.tgz#bd6b562d902e0f92904ac3754c722d9e63e00480"
integrity sha512-joEupPjYJ7PjZtDsS5lzALtlAudAbgIBMGJPNeFe5HfdmJXFd13ECmEM+5rXNxYVMRHua2w8132R6ab5Z6K9Ow==
lightningcss@^1.22.1: lightningcss@^1.22.1:
version "1.24.1" version "1.24.1"
resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.24.1.tgz" resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.24.1.tgz"
@ -1982,11 +2173,6 @@ nan@^2.17.0:
resolved "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz" resolved "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz"
integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==
nanoevents@^9.0.0:
version "9.0.0"
resolved "https://registry.npmjs.org/nanoevents/-/nanoevents-9.0.0.tgz"
integrity sha512-X8pU7IOpgKXVLPxYUI55ymXc8XuBE+uypfEyEFBtHkD1EX9KavYTVc+vXZHFyHKzA1TaZoVDqklLdQBBrxIuAw==
node-addon-api@^5.0.0: node-addon-api@^5.0.0:
version "5.1.0" version "5.1.0"
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz" resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz"
@ -2492,6 +2678,11 @@ source-map@^0.6.1:
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
split2@^4.0.0:
version "4.2.0"
resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
split@^1.0.1: split@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.npmjs.org/split/-/split-1.0.1.tgz" resolved "https://registry.npmjs.org/split/-/split-1.0.1.tgz"
@ -2499,12 +2690,7 @@ split@^1.0.1:
dependencies: dependencies:
through "2" through "2"
split2@^4.0.0: srcset@4:
version "4.2.0"
resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
srcset@4, srcset@4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz" resolved "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz"
integrity sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw== integrity sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==
@ -2514,18 +2700,21 @@ stable@^0.1.8:
resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz" resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz"
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
stream-http@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5"
integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==
dependencies:
builtin-status-codes "^3.0.0"
inherits "^2.0.4"
readable-stream "^3.6.0"
xtend "^4.0.2"
stream-shift@^1.0.2: stream-shift@^1.0.2:
version "1.0.3" version "1.0.3"
resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz" resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz"
integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==
string_decoder@^1.1.1, string_decoder@^1.3.0:
version "1.3.0"
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
@ -2535,6 +2724,13 @@ string_decoder@^1.1.1, string_decoder@^1.3.0:
is-fullwidth-code-point "^3.0.0" is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1" strip-ansi "^6.0.1"
string_decoder@^1.1.1, string_decoder@^1.3.0:
version "1.3.0"
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1: strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
@ -2566,7 +2762,7 @@ supports-color@^7.1.0:
dependencies: dependencies:
has-flag "^4.0.0" has-flag "^4.0.0"
svgo@^2.4.0, svgo@^3.0.2: svgo@^2.4.0:
version "2.8.0" version "2.8.0"
resolved "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz" resolved "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz"
integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==
@ -2640,7 +2836,7 @@ type-fest@^0.20.2:
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
typescript@^5.4.3, typescript@>=4.9.5: typescript@^5.4.3:
version "5.4.3" version "5.4.3"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz" resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz"
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
@ -2736,6 +2932,11 @@ ws@^8.0.0:
resolved "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz" resolved "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz"
integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==
xtend@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
y18n@^5.0.5: y18n@^5.0.5:
version "5.0.8" version "5.0.8"
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"