Compare commits
3 commits
115a78be01
...
7a2c81886c
Author | SHA1 | Date | |
---|---|---|---|
7a2c81886c | |||
4212050ae5 | |||
7b9c71d534 |
29 changed files with 705 additions and 395 deletions
2
LICENSE
2
LICENSE
|
@ -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.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
|
|
@ -3,15 +3,25 @@
|
|||
"version": "1.0.0",
|
||||
"private": "true",
|
||||
"description": "socket 2.0 backend",
|
||||
|
||||
"type": "module",
|
||||
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
"build": "parcel build src/index.ts --target node"
|
||||
},
|
||||
|
||||
"author": "modeco80",
|
||||
"license": "MIT",
|
||||
|
||||
"targets": {
|
||||
"node":{
|
||||
"context": "node",
|
||||
"outputFormat": "esmodule"
|
||||
}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"@fastify/websocket": "^10.0.1",
|
||||
"@julusian/jpeg-turbo": "^2.1.0",
|
||||
"@socketcomputer/qemu": "*",
|
||||
"@socketcomputer/shared": "*",
|
||||
"fastify": "^4.26.2",
|
||||
|
@ -19,6 +29,7 @@
|
|||
"canvas": "^2.11.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"parcel": "^2.12.0",
|
||||
"@types/ws": "^8.5.10"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ export function Slot_PCDef(
|
|||
pushOption('-device usb-tablet');
|
||||
|
||||
return {
|
||||
id: "socketvm1",
|
||||
id: "socketvm2-test",
|
||||
command: qCommand
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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 { ExtendableTimer } from './ExtendableTimer.js';
|
||||
import { EventEmitter } from 'node:events';
|
||||
|
@ -20,7 +20,7 @@ const kCanvasJpegQuality = 0.25;
|
|||
class VMUser {
|
||||
public connection: WebSocket;
|
||||
public address: string;
|
||||
public username: string;
|
||||
public username: string = "";
|
||||
private vm: SocketVM;
|
||||
|
||||
|
||||
|
@ -49,10 +49,10 @@ class VMUser {
|
|||
async SendBuffer(buffer: ArrayBuffer): Promise<void> {
|
||||
return new Promise((res, rej) => {
|
||||
if (this.connection.readyState !== WebSocket.CLOSED) {
|
||||
this.connection.send(buffer, (err) => {
|
||||
res();
|
||||
});
|
||||
this.connection.send(buffer);
|
||||
res();
|
||||
}
|
||||
rej(new Error('connection haves closed'));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -73,14 +73,17 @@ type userAndTime = {
|
|||
class TurnQueue extends EventEmitter {
|
||||
private queue: Queue<VMUser> = new Queue<VMUser>();
|
||||
private turnTime = kTurnTimeSeconds;
|
||||
private interval: NodeJS.Timeout = null;
|
||||
private interval: NodeJS.Timeout|null = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CurrentUser(): VMUser {
|
||||
return this.queue.peek();
|
||||
public CurrentUser(): VMUser|null {
|
||||
if(this.queue.peek() == undefined)
|
||||
return null;
|
||||
// We already check if it'll be undefined
|
||||
return this.queue.peek()!;
|
||||
}
|
||||
|
||||
public TryEnqueue(user: VMUser) {
|
||||
|
@ -132,7 +135,7 @@ class TurnQueue extends EventEmitter {
|
|||
}
|
||||
|
||||
private nextTurn() {
|
||||
clearInterval(this.interval);
|
||||
clearInterval(this.interval!);
|
||||
if (this.queue.size === 0) {
|
||||
} else {
|
||||
this.turnTime = kTurnTimeSeconds;
|
||||
|
@ -145,26 +148,24 @@ class TurnQueue extends EventEmitter {
|
|||
|
||||
class SocketVM extends EventEmitter {
|
||||
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 queue: TurnQueue = new TurnQueue();
|
||||
|
||||
constructor(vm: QemuVM) {
|
||||
super();
|
||||
|
||||
this.vm = vm;
|
||||
this.timer = new ExtendableTimer(15);
|
||||
|
||||
this.timer.on('expired', async () => {
|
||||
// bye bye!
|
||||
console.log(`[SocketVM] VM expired, resetting..`);
|
||||
console.log(`[SocketVM] VM timer expired, resetting..`);
|
||||
await this.vm.Stop();
|
||||
});
|
||||
|
||||
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>) => {
|
||||
|
@ -296,14 +297,12 @@ class SocketVM extends EventEmitter {
|
|||
break;
|
||||
|
||||
case Shared.MessageType.Key:
|
||||
console.log("GOT key event", (message as Shared.KeyMessage).keysym, (message as Shared.KeyMessage).pressed)
|
||||
if(user != this.queue.CurrentUser())
|
||||
return;
|
||||
|
||||
if(this.display == null)
|
||||
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);
|
||||
break;
|
||||
|
||||
|
@ -329,7 +328,7 @@ class SocketVM extends EventEmitter {
|
|||
let self = this;
|
||||
|
||||
// Hook up the display
|
||||
this.display.on('resize', async (width, height) => {
|
||||
this.display?.on('resize', async (width: number, height: number) => {
|
||||
if(self.display == null)
|
||||
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);
|
||||
canvas.getContext('2d').putImageData(rect, 0, 0);
|
||||
|
||||
|
@ -376,7 +375,7 @@ class SocketVM extends EventEmitter {
|
|||
|
||||
await user.SendMessage((encoder: Shared.MessageEncoder) => {
|
||||
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();
|
||||
});
|
||||
|
||||
|
@ -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 {
|
||||
private vm: SocketVM = null;
|
||||
private vm: SocketVM|null = null;
|
||||
private fastify: FastifyInstance = fastify({
|
||||
exposeHeadRoutes: false
|
||||
});
|
||||
|
@ -433,12 +445,13 @@ export class SocketComputerServer {
|
|||
CTRoutes(app: FastifyInstance) {
|
||||
let self = this;
|
||||
|
||||
// @ts-ignore (fastify types are broken...)
|
||||
app.get('/', { websocket: true }, (connection: fastifyWebsocket.WebSocket, req: FastifyRequest) => {
|
||||
let address = req.ip;
|
||||
if(req.headers["cf-connecting-ip"] !== undefined) {
|
||||
address = req.headers["cf-connecting-ip"] as string;
|
||||
}
|
||||
new VMUser(connection, self.vm, address);
|
||||
new VMUser(connection, self.vm!, address);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
16
package.json
16
package.json
|
@ -8,15 +8,21 @@
|
|||
"webapp"
|
||||
],
|
||||
"scripts": {
|
||||
"build:frontend": "npm -w shared run build && npm -w webapp run build",
|
||||
"build:service": "npm -w shared run build && npm -w qemu run build && npm -w backend 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:frontend": "npm -w shared run build && npm -w webapp run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"canvas": "^2.11.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"canvas": "^2.11.2"
|
||||
},
|
||||
"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",
|
||||
"prettier": "^3.2.5",
|
||||
"stream-http": "^3.1.0",
|
||||
"typescript": "^5.4.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,17 +3,30 @@
|
|||
"version": "1.0.0",
|
||||
"private": "true",
|
||||
"description": "QEMU runtime for socketcomputer backend",
|
||||
"main": "dist/src/index.js",
|
||||
"exports": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
"build": "parcel build src/index.ts --target node --target types"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"targets": {
|
||||
"types": {},
|
||||
"node": {
|
||||
"context": "node",
|
||||
"isLibrary": true,
|
||||
"outputFormat": "esmodule"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
"canvas": "^2.11.2",
|
||||
"execa": "^8.0.1",
|
||||
"split": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"parcel": "^2.12.0",
|
||||
"@types/node": "^20.12.2",
|
||||
"@types/split": "^1.0.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
KeyboardEvent(keysym, pressed) {
|
||||
KeyboardEvent(keysym: number, pressed: boolean) {
|
||||
this.displayVnc.sendKeyEvent(keysym, pressed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ const kMaxFailCount = 5;
|
|||
|
||||
let gVMShouldSnapshot = false;
|
||||
|
||||
async function Sleep(ms) {
|
||||
async function Sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ export class QemuVM extends EventEmitter {
|
|||
if (this.state !== stateShouldBe) throw new Error(message);
|
||||
}
|
||||
|
||||
private SetState(state) {
|
||||
private SetState(state: VMState) {
|
||||
this.state = state;
|
||||
this.emit('statechange', this.state);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ export class QemuVM extends EventEmitter {
|
|||
return `${kVmTmpPathBase}/socket2-${this.definition.id}-vnc`;
|
||||
}
|
||||
|
||||
private async StartQemu(split) {
|
||||
private async StartQemu(split: Array<string>) {
|
||||
let self = this;
|
||||
|
||||
this.SetState(VMState.Starting);
|
||||
|
@ -227,11 +227,11 @@ export class QemuVM extends EventEmitter {
|
|||
switch (ev.event) {
|
||||
// Handle the STOP event sent when using -no-shutdown
|
||||
case 'STOP':
|
||||
await self.qmpInstance.Execute('system_reset');
|
||||
await self.qmpInstance?.Execute('system_reset');
|
||||
break;
|
||||
case 'RESET':
|
||||
self.VMLog('got a reset event!');
|
||||
await self.qmpInstance.Execute('cont');
|
||||
await self.qmpInstance?.Execute('cont');
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
@ -250,7 +250,7 @@ export class QemuVM extends EventEmitter {
|
|||
|
||||
try {
|
||||
await Sleep(500);
|
||||
this.qmpInstance.ConnectUNIX(this.GetQmpPath());
|
||||
this.qmpInstance?.ConnectUNIX(this.GetQmpPath());
|
||||
} catch (err) {
|
||||
// just try again
|
||||
await Sleep(500);
|
||||
|
@ -261,7 +261,7 @@ export class QemuVM extends EventEmitter {
|
|||
|
||||
private async DisconnectDisplay() {
|
||||
try {
|
||||
this.display.Disconnect();
|
||||
this.display?.Disconnect();
|
||||
this.display = null; // disassociate with that display object.
|
||||
|
||||
await unlink(this.GetVncPath());
|
||||
|
|
|
@ -123,7 +123,7 @@ export default class QmpClient extends Socket {
|
|||
});
|
||||
}
|
||||
|
||||
Connect(host, port) {
|
||||
Connect(host: string, port: number) {
|
||||
super.connect(port, host);
|
||||
this.ConnectImpl();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Copyright 2021 Filipe Calaça Barbosa
|
||||
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
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -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).
|
||||
|
||||
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
|
||||
- some noisy debug prints removed
|
||||
- (some, very tiny) code cleanup
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
|
||||
import { IRectDecoder } from './decoders/decoder.js';
|
||||
import { HextileDecoder } from './decoders/hextile.js';
|
||||
import { RawDecoder } from './decoders/raw.js';
|
||||
import { ZrleDecoder } from './decoders/zrle.js';
|
||||
|
@ -13,57 +15,79 @@ import * as crypto from 'node:crypto';
|
|||
|
||||
import { SocketBuffer } from './socketbuffer.js';
|
||||
|
||||
import { VncRectangle, Color3, PixelFormat, Cursor } from './types.js';
|
||||
|
||||
export class VncClient extends EventEmitter {
|
||||
// These are in no particular order.
|
||||
|
||||
public debug: Boolean;
|
||||
public debug: boolean = false;
|
||||
|
||||
private _connected: Boolean;
|
||||
private _authenticated: Boolean;
|
||||
private _version: string;
|
||||
private _password: string;
|
||||
private _connected: boolean = false;
|
||||
private _authenticated: boolean = false;
|
||||
private _version: string = "";
|
||||
private _password: string = "";
|
||||
|
||||
private _audioChannels: number;
|
||||
private _audioFrequency: number;
|
||||
private _audioChannels: number = 2;
|
||||
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 _timerInterval: number;
|
||||
private _timerPointer;
|
||||
private _timerPointer : NodeJS.Timeout|null = null;
|
||||
|
||||
public fb: Buffer;
|
||||
public fb: Buffer = Buffer.from([]);
|
||||
|
||||
private _handshaked: Boolean;
|
||||
private _waitingServerInit: Boolean;
|
||||
private _expectingChallenge: Boolean;
|
||||
private _challengeResponseSent: Boolean;
|
||||
private _handshaked: boolean = false;
|
||||
private _waitingServerInit: boolean = false;
|
||||
private _expectingChallenge: boolean = false;
|
||||
private _challengeResponseSent: boolean = false;
|
||||
|
||||
private _set8BitColor: Boolean;
|
||||
private _set8BitColor: boolean = false;
|
||||
private _frameBufferReady = false;
|
||||
private _firstFrameReceived = false;
|
||||
private _processingFrame = false;
|
||||
|
||||
private _relativePointer: Boolean;
|
||||
private _relativePointer: boolean = false;
|
||||
|
||||
public bigEndianFlag: Boolean;
|
||||
public bigEndianFlag: boolean = false;
|
||||
|
||||
public clientWidth: number;
|
||||
public clientHeight: number;
|
||||
public clientName: string;
|
||||
public clientWidth: number = 0;
|
||||
public clientHeight: number = 0;
|
||||
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 _audioData: Buffer;
|
||||
private _colorMap: Color3[] = [];
|
||||
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[];
|
||||
|
||||
private _connection: net.Socket;
|
||||
private _connection: net.Socket|null = null;
|
||||
private _socketBuffer: SocketBuffer;
|
||||
|
||||
static get consts() {
|
||||
|
@ -101,7 +125,7 @@ export class VncClient extends EventEmitter {
|
|||
* @returns {number}
|
||||
*/
|
||||
get localPort() {
|
||||
return this._connection ? this._connection.localPort : 0;
|
||||
return this._connection ? this._connection?.localPort : 0;
|
||||
}
|
||||
|
||||
constructor(options: any = { debug: false, fps: 0, encodings: [] }) {
|
||||
|
@ -125,7 +149,7 @@ export class VncClient extends EventEmitter {
|
|||
this._audioFrequency = options.audioFrequency || 22050;
|
||||
|
||||
this._rects = 0;
|
||||
this._decoders = {};
|
||||
|
||||
this._decoders[consts.encodings.raw] = new RawDecoder();
|
||||
// TODO: Implement tight encoding
|
||||
// this._decoders[encodings.tight] = new tightDecoder();
|
||||
|
@ -155,7 +179,7 @@ export class VncClient extends EventEmitter {
|
|||
* Adjuste the configured FPS
|
||||
* @param fps {number} - Number of update requests send by second
|
||||
*/
|
||||
changeFps(fps) {
|
||||
changeFps(fps: number) {
|
||||
if (!Number.isNaN(fps)) {
|
||||
this._fps = Number(fps);
|
||||
this._timerInterval = this._fps > 0 ? 1000 / this._fps : 0;
|
||||
|
@ -178,7 +202,7 @@ export class VncClient extends EventEmitter {
|
|||
* @param options
|
||||
*/
|
||||
connect(
|
||||
options /* = {
|
||||
options: any /* = {
|
||||
host: '',
|
||||
password: '',
|
||||
path: '',
|
||||
|
@ -199,31 +223,31 @@ export class VncClient extends EventEmitter {
|
|||
this._connection = net.connect(options.port || 5900, options.host);
|
||||
|
||||
// disable nagle's algorithm for TCP
|
||||
this._connection.setNoDelay();
|
||||
this._connection?.setNoDelay();
|
||||
} else {
|
||||
// unix socket. bodged in but oh well
|
||||
this._connection = net.connect(options.path);
|
||||
}
|
||||
|
||||
this._connection.on('connect', () => {
|
||||
this._connection?.on('connect', () => {
|
||||
this._connected = true;
|
||||
this.emit('connected');
|
||||
});
|
||||
|
||||
this._connection.on('close', () => {
|
||||
this._connection?.on('close', () => {
|
||||
this.resetState();
|
||||
this.emit('closed');
|
||||
});
|
||||
|
||||
this._connection.on('timeout', () => {
|
||||
this._connection?.on('timeout', () => {
|
||||
this.emit('connectTimeout');
|
||||
});
|
||||
|
||||
this._connection.on('error', (err) => {
|
||||
this._connection?.on('error', (err) => {
|
||||
this.emit('connectError', err);
|
||||
});
|
||||
|
||||
this._connection.on('data', async (data) => {
|
||||
this._connection?.on('data', async (data) => {
|
||||
this._socketBuffer.pushData(data);
|
||||
|
||||
if (!this._handshaked) {
|
||||
|
@ -243,7 +267,7 @@ export class VncClient extends EventEmitter {
|
|||
*/
|
||||
disconnect() {
|
||||
if (this._connection) {
|
||||
this._connection.end();
|
||||
this._connection?.end();
|
||||
this.resetState();
|
||||
this.emit('disconnected');
|
||||
}
|
||||
|
@ -269,7 +293,7 @@ export class VncClient extends EventEmitter {
|
|||
message.writeUInt16BE(width, 6); // Width
|
||||
message.writeUInt16BE(height, 8); // Height
|
||||
|
||||
this._connection.write(message);
|
||||
this._connection?.write(message);
|
||||
|
||||
this._frameBufferReady = true;
|
||||
}
|
||||
|
@ -283,15 +307,15 @@ export class VncClient extends EventEmitter {
|
|||
// Handshake, negotiating protocol version
|
||||
if (this._socketBuffer.toString() === consts.versionString.V3_003) {
|
||||
this._log('Sending 3.3', true);
|
||||
this._connection.write(consts.versionString.V3_003);
|
||||
this._connection?.write(consts.versionString.V3_003);
|
||||
this._version = '3.3';
|
||||
} else if (this._socketBuffer.toString() === consts.versionString.V3_007) {
|
||||
this._log('Sending 3.7', true);
|
||||
this._connection.write(consts.versionString.V3_007);
|
||||
this._connection?.write(consts.versionString.V3_007);
|
||||
this._version = '3.7';
|
||||
} else if (this._socketBuffer.toString() === consts.versionString.V3_008) {
|
||||
this._log('Sending 3.8', true);
|
||||
this._connection.write(consts.versionString.V3_008);
|
||||
this._connection?.write(consts.versionString.V3_008);
|
||||
this._version = '3.8';
|
||||
} else {
|
||||
// Negotiating auth mechanism
|
||||
|
@ -299,10 +323,10 @@ export class VncClient extends EventEmitter {
|
|||
if (this._socketBuffer.includes(0x02) && this._password) {
|
||||
this._log('Password provided and server support VNC auth. Choosing VNC auth.', true);
|
||||
this._expectingChallenge = true;
|
||||
this._connection.write(Buffer.from([0x02]));
|
||||
this._connection?.write(Buffer.from([0x02]));
|
||||
} else if (this._socketBuffer.includes(1)) {
|
||||
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') {
|
||||
this._waitingServerInit = true;
|
||||
} else {
|
||||
|
@ -352,7 +376,7 @@ export class VncClient extends EventEmitter {
|
|||
response.fill(des1.update(this._socketBuffer.buffer.slice(0, 8)), 0, 8);
|
||||
response.fill(des2.update(this._socketBuffer.buffer.slice(8, 16)), 8, 16);
|
||||
|
||||
this._connection.write(response);
|
||||
this._connection?.write(response);
|
||||
this._challengeResponseSent = true;
|
||||
}
|
||||
|
||||
|
@ -363,7 +387,7 @@ export class VncClient extends EventEmitter {
|
|||
* Reverse bits order of a byte
|
||||
* @param buf - Buffer to be flipped
|
||||
*/
|
||||
reverseBits(buf) {
|
||||
reverseBits(buf: Buffer) {
|
||||
for (let x = 0; x < buf.length; x++) {
|
||||
let newByte = 0;
|
||||
newByte += buf[x] & 128 ? 1 : 0;
|
||||
|
@ -390,6 +414,7 @@ export class VncClient extends EventEmitter {
|
|||
|
||||
this.clientWidth = this._socketBuffer.readUInt16BE();
|
||||
this.clientHeight = this._socketBuffer.readUInt16BE();
|
||||
|
||||
this.pixelFormat.bitsPerPixel = this._socketBuffer.readUInt8();
|
||||
this.pixelFormat.depth = this._socketBuffer.readUInt8();
|
||||
this.pixelFormat.bigEndianFlag = this._socketBuffer.readUInt8();
|
||||
|
@ -457,7 +482,7 @@ export class VncClient extends EventEmitter {
|
|||
message.writeUInt8(0, 19); // PixelFormat - Padding
|
||||
|
||||
// Envia um setPixelFormat trocando para mapa de cores
|
||||
this._connection.write(message);
|
||||
this._connection?.write(message);
|
||||
|
||||
this.pixelFormat.bitsPerPixel = 8;
|
||||
this.pixelFormat.depth = 8;
|
||||
|
@ -487,7 +512,7 @@ export class VncClient extends EventEmitter {
|
|||
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._waitingServerInit = true;
|
||||
// Shared bit set
|
||||
this._connection.write('1');
|
||||
this._connection?.write('1');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -558,6 +583,10 @@ export class VncClient extends EventEmitter {
|
|||
data: Buffer.alloc(4)
|
||||
};
|
||||
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);
|
||||
for (var y = 0; y < height; y++) {
|
||||
for (var x = 0; x < width; x++) {
|
||||
|
@ -568,6 +597,7 @@ export class VncClient extends EventEmitter {
|
|||
case 8:
|
||||
console.log(8);
|
||||
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;
|
||||
data.writeIntBE(color, offset, 4);
|
||||
break;
|
||||
|
@ -606,12 +636,14 @@ export class VncClient extends EventEmitter {
|
|||
|
||||
while (this._rects) {
|
||||
await this._socketBuffer.waitBytes(12);
|
||||
const rect: any = {};
|
||||
rect.x = this._socketBuffer.readUInt16BE();
|
||||
rect.y = this._socketBuffer.readUInt16BE();
|
||||
rect.width = this._socketBuffer.readUInt16BE();
|
||||
rect.height = this._socketBuffer.readUInt16BE();
|
||||
rect.encoding = this._socketBuffer.readInt32BE();
|
||||
const rect: VncRectangle = {
|
||||
x: this._socketBuffer.readUInt16BE(),
|
||||
y: this._socketBuffer.readUInt16BE(),
|
||||
width: this._socketBuffer.readUInt16BE(),
|
||||
height: this._socketBuffer.readUInt16BE(),
|
||||
encoding: this._socketBuffer.readInt32BE(),
|
||||
data: null // for now
|
||||
};
|
||||
|
||||
if (rect.encoding === consts.encodings.pseudoQemuAudio) {
|
||||
this.sendAudio(true);
|
||||
|
@ -700,7 +732,7 @@ export class VncClient extends EventEmitter {
|
|||
this._colorMap[firstColor] = {
|
||||
r: 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++;
|
||||
}
|
||||
|
@ -733,7 +765,7 @@ export class VncClient extends EventEmitter {
|
|||
*/
|
||||
resetState() {
|
||||
if (this._connection) {
|
||||
this._connection.end();
|
||||
this._connection?.end();
|
||||
}
|
||||
|
||||
if (this._timerPointer) {
|
||||
|
@ -782,7 +814,7 @@ export class VncClient extends EventEmitter {
|
|||
this._rects = 0;
|
||||
|
||||
this._colorMap = [];
|
||||
this.fb = null;
|
||||
this.fb = Buffer.from([]);
|
||||
|
||||
this._socketBuffer?.flush(false);
|
||||
|
||||
|
@ -792,7 +824,9 @@ export class VncClient extends EventEmitter {
|
|||
x: 0,
|
||||
y: 0,
|
||||
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 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);
|
||||
message.writeUInt8(4); // Message type
|
||||
message.writeUInt8(down ? 1 : 0, 1); // Down flag
|
||||
|
@ -812,7 +846,7 @@ export class VncClient extends EventEmitter {
|
|||
|
||||
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 mask - Raw RFB button mask
|
||||
*/
|
||||
sendPointerEvent(xPosition, yPosition, buttonMask) {
|
||||
sendPointerEvent(xPosition: number, yPosition: number, buttonMask: number) {
|
||||
const message = Buffer.alloc(6);
|
||||
message.writeUInt8(consts.clientMsgTypes.pointerEvent); // Message type
|
||||
message.writeUInt8(buttonMask, 1); // Button Mask
|
||||
|
@ -832,14 +866,14 @@ export class VncClient extends EventEmitter {
|
|||
this._cursor.posX = xPosition;
|
||||
this._cursor.posY = yPosition;
|
||||
|
||||
this._connection.write(message);
|
||||
this._connection?.write(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send client cut message to server
|
||||
* @param text - latin1 encoded
|
||||
*/
|
||||
clientCutText(text) {
|
||||
clientCutText(text: string) {
|
||||
const textBuffer = Buffer.from(text, 'latin1');
|
||||
const message = Buffer.alloc(8 + textBuffer.length);
|
||||
message.writeUInt8(6); // Message type
|
||||
|
@ -849,18 +883,18 @@ export class VncClient extends EventEmitter {
|
|||
message.writeUInt32BE(textBuffer.length, 4); // Padding
|
||||
textBuffer.copy(message, 8);
|
||||
|
||||
this._connection.write(message);
|
||||
this._connection?.write(message);
|
||||
}
|
||||
|
||||
sendAudio(enable) {
|
||||
sendAudio(enable: boolean) {
|
||||
const message = Buffer.alloc(4);
|
||||
message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message type
|
||||
message.writeUInt8(1, 1); // Submessage Type
|
||||
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);
|
||||
message.writeUInt8(consts.clientMsgTypes.qemuAudio); // Message 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(channels, 5); // Number of Channels
|
||||
message.writeUInt32BE(frequency, 6); // Frequency
|
||||
this._connection.write(message);
|
||||
this._connection?.write(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -877,7 +911,7 @@ export class VncClient extends EventEmitter {
|
|||
* @param debug
|
||||
* @private
|
||||
*/
|
||||
_log(text, debug = false) {
|
||||
_log(text: string, debug = false) {
|
||||
if (!debug || (debug && this.debug)) {
|
||||
console.log(text);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
export class CopyRectDecoder {
|
||||
getPixelBytePos(x, y, width, height) {
|
||||
return (y * width + x) * 4;
|
||||
}
|
||||
import { SocketBuffer } from "../socketbuffer";
|
||||
import { IRectDecoder } from "./decoder";
|
||||
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) => {
|
||||
await socket.waitBytes(4);
|
||||
rect.data = socket.readNBytesOffset(4);
|
||||
|
@ -13,8 +15,8 @@ export class CopyRectDecoder {
|
|||
|
||||
for (let h = 0; h < rect.height; h++) {
|
||||
for (let w = 0; w < rect.width; w++) {
|
||||
const fbOrigBytePosOffset = this.getPixelBytePos(x + w, y + h, screenW, screenH);
|
||||
const fbBytePosOffset = this.getPixelBytePos(rect.x + w, rect.y + h, screenW, screenH);
|
||||
const fbOrigBytePosOffset = getPixelBytePos(x + w, 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 + 1), fbBytePosOffset + 1);
|
||||
|
|
7
qemu/src/rfb/decoders/decoder.ts
Normal file
7
qemu/src/rfb/decoders/decoder.ts
Normal 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>;
|
||||
}
|
|
@ -1,27 +1,25 @@
|
|||
export class HextileDecoder {
|
||||
getPixelBytePos(x, y, width, height) {
|
||||
return (y * width + x) * 4;
|
||||
}
|
||||
import { SocketBuffer } from "../socketbuffer";
|
||||
import { IRectDecoder } from "./decoder";
|
||||
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) => {
|
||||
const initialOffset = socket.offset;
|
||||
let dataSize = 0;
|
||||
|
||||
let tiles;
|
||||
let totalTiles;
|
||||
let tilesX;
|
||||
let tilesY;
|
||||
|
||||
let lastSubEncoding;
|
||||
let lastSubEncoding = 0;
|
||||
|
||||
const backgroundColor = { r: 0, g: 0, b: 0, a: 255 };
|
||||
const foregroundColor = { r: 0, g: 0, b: 0, a: 255 };
|
||||
|
||||
tilesX = Math.ceil(rect.width / 16);
|
||||
tilesY = Math.ceil(rect.height / 16);
|
||||
tiles = tilesX * tilesY;
|
||||
totalTiles = tiles;
|
||||
let tilesX = Math.ceil(rect.width / 16);
|
||||
let tilesY = Math.ceil(rect.height / 16);
|
||||
let tiles = tilesX * tilesY;
|
||||
let totalTiles = tiles;
|
||||
|
||||
while (tiles) {
|
||||
await socket.waitBytes(1);
|
||||
|
@ -42,7 +40,7 @@ export class HextileDecoder {
|
|||
// We need to ignore zeroed tile after a raw tile
|
||||
} else {
|
||||
// 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) {
|
||||
// If Raw, ignore all other bits
|
||||
|
@ -50,7 +48,7 @@ export class HextileDecoder {
|
|||
dataSize += th * tw * (bitsPerPixel / 8);
|
||||
for (let h = 0; h < th; h++) {
|
||||
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) {
|
||||
const index = socket.readUInt8();
|
||||
const color = colorMap[index];
|
||||
|
@ -148,7 +146,7 @@ export class HextileDecoder {
|
|||
}
|
||||
|
||||
// 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
|
||||
if (subEncoding & 0x08) {
|
||||
|
@ -206,13 +204,13 @@ export class HextileDecoder {
|
|||
const sw = (wh >> 4) + 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 {
|
||||
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
||||
applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
||||
}
|
||||
} else {
|
||||
this.applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
||||
applyColor(tw, th, tx, ty, screenW, screenH, backgroundColor, fb);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
export class RawDecoder {
|
||||
getPixelBytePos(x, y, width, height) {
|
||||
return (y * width + x) * 4;
|
||||
}
|
||||
import { SocketBuffer } from "../socketbuffer";
|
||||
import { IRectDecoder } from "./decoder";
|
||||
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) => {
|
||||
await socket.waitBytes(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 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) {
|
||||
const bytePosOffset = h * rect.width + w;
|
||||
const index = rect.data.readUInt8(bytePosOffset);
|
||||
|
|
19
qemu/src/rfb/decoders/util.ts
Normal file
19
qemu/src/rfb/decoders/util.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
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 unBuffer: SocketBuffer;
|
||||
|
||||
|
@ -14,11 +18,7 @@ export class ZrleDecoder {
|
|||
});
|
||||
}
|
||||
|
||||
getPixelBytePos(x, y, width, height) {
|
||||
return (y * width + x) * 4;
|
||||
}
|
||||
|
||||
async decode(rect, fb, bitsPerPixel, colorMap, screenW, screenH, socket, depth): Promise<void> {
|
||||
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) => {
|
||||
await socket.waitBytes(4);
|
||||
|
||||
|
@ -35,15 +35,10 @@ export class ZrleDecoder {
|
|||
this.zlib.write(compressedData, async () => {
|
||||
this.zlib.flush();
|
||||
|
||||
let tiles;
|
||||
let totalTiles;
|
||||
let tilesX;
|
||||
let tilesY;
|
||||
|
||||
tilesX = Math.ceil(rect.width / 64);
|
||||
tilesY = Math.ceil(rect.height / 64);
|
||||
tiles = tilesX * tilesY;
|
||||
totalTiles = tiles;
|
||||
let tilesX = Math.ceil(rect.width / 64);
|
||||
let tilesY = Math.ceil(rect.height / 64);
|
||||
let tiles = tilesX * tilesY;
|
||||
let totalTiles = tiles;
|
||||
|
||||
while (tiles) {
|
||||
await this.unBuffer.waitBytes(1, 'tile begin.');
|
||||
|
@ -67,7 +62,7 @@ export class ZrleDecoder {
|
|||
// Raw
|
||||
for (let h = 0; h < th; h++) {
|
||||
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) {
|
||||
await this.unBuffer.waitBytes(1, 'raw 8bits');
|
||||
const index = this.unBuffer.readUInt8();
|
||||
|
@ -105,11 +100,11 @@ export class ZrleDecoder {
|
|||
}
|
||||
} else if (subEncoding === 1) {
|
||||
// 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) {
|
||||
await this.unBuffer.waitBytes(1, 'single color 8bits');
|
||||
const index = this.unBuffer.readUInt8();
|
||||
color = colorMap[index];
|
||||
color = (colorMap[index] as Color4);
|
||||
} else if (bitsPerPixel === 24 || (bitsPerPixel === 32 && depth === 24)) {
|
||||
await this.unBuffer.waitBytes(3, 'single color 24bits');
|
||||
color.r = this.unBuffer.readUInt8();
|
||||
|
@ -122,7 +117,7 @@ export class ZrleDecoder {
|
|||
color.b = 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) {
|
||||
// Palette
|
||||
const palette = [];
|
||||
|
@ -152,7 +147,7 @@ export class ZrleDecoder {
|
|||
// const i = (tw * th) / (8 / bitsPerIndex);
|
||||
// const pixels = [];
|
||||
|
||||
let byte;
|
||||
let byte = 0;
|
||||
let bitPos = 0;
|
||||
|
||||
for (let h = 0; h < th; h++) {
|
||||
|
@ -162,7 +157,7 @@ export class ZrleDecoder {
|
|||
byte = this.unBuffer.readUInt8();
|
||||
bitPos = 0;
|
||||
}
|
||||
let color;
|
||||
let color : Color4 = { r: 0, g: 0, b: 0, a: 255 };
|
||||
switch (bitsPerIndex) {
|
||||
case 1:
|
||||
if (bitPos === 0) {
|
||||
|
@ -216,7 +211,7 @@ export class ZrleDecoder {
|
|||
}
|
||||
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.g ?? 0, fbBytePosOffset + 1);
|
||||
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
|
||||
|
@ -259,7 +254,7 @@ export class ZrleDecoder {
|
|||
totalRun += runLength;
|
||||
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.g ?? 0, fbBytePosOffset + 1);
|
||||
fb.writeUInt8(color.r ?? 0, fbBytePosOffset + 2);
|
||||
|
@ -321,7 +316,7 @@ export class ZrleDecoder {
|
|||
totalRun += runLength;
|
||||
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.g ?? 0, fbBytePosOffset + 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/// this is a pretty poor name.
|
||||
export class SocketBuffer {
|
||||
public buffer?: Buffer;
|
||||
private offset: number;
|
||||
public buffer: Buffer;
|
||||
public offset: number; // :(
|
||||
|
||||
constructor() {
|
||||
this.buffer = Buffer.from([]);
|
||||
this.offset = 0;
|
||||
this.flush();
|
||||
}
|
||||
|
||||
|
@ -21,11 +23,11 @@ export class SocketBuffer {
|
|||
return this.buffer.toString();
|
||||
}
|
||||
|
||||
includes(check) {
|
||||
includes(check: Buffer|number|string) {
|
||||
return this.buffer.includes(check);
|
||||
}
|
||||
|
||||
pushData(data) {
|
||||
pushData(data: Buffer) {
|
||||
this.buffer = Buffer.concat([this.buffer, data]);
|
||||
}
|
||||
|
||||
|
@ -77,17 +79,17 @@ export class SocketBuffer {
|
|||
return data;
|
||||
}
|
||||
|
||||
readNBytes(bytes, offset = this.offset) {
|
||||
readNBytes(bytes: number, offset = this.offset) {
|
||||
return this.buffer.slice(offset, offset + bytes);
|
||||
}
|
||||
|
||||
readNBytesOffset(bytes) {
|
||||
readNBytesOffset(bytes: number) {
|
||||
const data = this.buffer.slice(this.offset, this.offset + bytes);
|
||||
this.offset += bytes;
|
||||
return data;
|
||||
}
|
||||
|
||||
setOffset(n) {
|
||||
setOffset(n: number) {
|
||||
this.offset = n;
|
||||
}
|
||||
|
||||
|
@ -96,7 +98,7 @@ export class SocketBuffer {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
return;
|
||||
}
|
||||
|
@ -114,17 +116,17 @@ export class SocketBuffer {
|
|||
});
|
||||
}
|
||||
|
||||
fill(data) {
|
||||
fill(data: Buffer) {
|
||||
this.buffer.fill(data, this.offset, 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.offset += data.length * repeats;
|
||||
}
|
||||
|
||||
sleep(n): Promise<void> {
|
||||
sleep(n: number): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(resolve, n);
|
||||
});
|
||||
|
|
44
qemu/src/rfb/types.ts
Normal file
44
qemu/src/rfb/types.ts
Normal 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,
|
||||
};
|
||||
|
|
@ -4,14 +4,29 @@
|
|||
"private": "true",
|
||||
"description": "crusttest shared bits",
|
||||
"type": "module",
|
||||
"main": "dist/src/index.js",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
|
||||
"devDependencies": {},
|
||||
"targets": {
|
||||
"types": {},
|
||||
"shared":{
|
||||
"context": "browser",
|
||||
"isLibrary": true,
|
||||
"outputFormat": "esmodule"
|
||||
}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
},
|
||||
|
||||
"devDependencies": {
|
||||
"parcel": "^2.12.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
"build": "parcel build src/index.ts --target shared --target types"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
|
|
|
@ -103,84 +103,90 @@ export type DeserializedMessage = AnyMessage;
|
|||
export const kProtocolHeaderSize = 8;
|
||||
|
||||
export class MessageEncoder {
|
||||
private struct: Struct;
|
||||
private buffer: ArrayBuffer;
|
||||
private struct: Struct|null = null;
|
||||
private buffer: ArrayBuffer|null = null;
|
||||
|
||||
Init(byteSize) {
|
||||
Init(byteSize: number) {
|
||||
this.buffer = new ArrayBuffer(byteSize + kProtocolHeaderSize);
|
||||
this.struct = new Struct(this.buffer);
|
||||
this.InitHeader();
|
||||
}
|
||||
|
||||
SetKeyMessage(keysym, pressed) {
|
||||
SetKeyMessage(keysym: number, pressed: boolean) {
|
||||
this.SetTypeCode(MessageType.Key);
|
||||
this.struct.WriteU16(keysym);
|
||||
this.struct.WriteU8(pressed == true ? 1 : 0);
|
||||
this.struct?.WriteU16(keysym);
|
||||
this.struct?.WriteU8(pressed == true ? 1 : 0);
|
||||
}
|
||||
|
||||
SetMouseMessage(x, y, buttons: MouseButtons) {
|
||||
SetMouseMessage(x: number, y: number, buttons: MouseButtons) {
|
||||
this.SetTypeCode(MessageType.Mouse);
|
||||
this.struct.WriteU16(x);
|
||||
this.struct.WriteU16(y);
|
||||
this.struct.WriteU8(buttons);
|
||||
this.struct?.WriteU16(x);
|
||||
this.struct?.WriteU16(y);
|
||||
this.struct?.WriteU8(buttons);
|
||||
}
|
||||
|
||||
SetTurnMessage() {
|
||||
this.SetTypeCode(MessageType.Turn);
|
||||
}
|
||||
|
||||
SetTurnSrvMessage(ms, usersQueue) {
|
||||
SetTurnSrvMessage(ms: number, usersQueue: Array<string>) {
|
||||
this.SetTypeCode(MessageType.Turn);
|
||||
this.struct.WriteU32(ms);
|
||||
this.struct.WriteArray(usersQueue, this.struct.WriteString);
|
||||
this.struct?.WriteU32(ms);
|
||||
this.struct?.WriteArray(usersQueue, this.struct?.WriteString);
|
||||
}
|
||||
|
||||
SetDisplayRectMessage(x, y, buffer: ArrayBuffer) {
|
||||
SetDisplayRectMessage(x: number, y: number, buffer: ArrayBuffer) {
|
||||
this.SetTypeCode(MessageType.DisplayRect);
|
||||
this.struct.WriteU16(x);
|
||||
this.struct.WriteU16(y);
|
||||
this.struct.WriteBuffer(buffer);
|
||||
this.struct?.WriteU16(x);
|
||||
this.struct?.WriteU16(y);
|
||||
this.struct?.WriteBuffer(buffer);
|
||||
}
|
||||
|
||||
SetDisplaySizeMessage(w, h) {
|
||||
SetDisplaySizeMessage(w: number, h: number) {
|
||||
this.SetTypeCode(MessageType.DisplaySize);
|
||||
this.struct.WriteU16(w);
|
||||
this.struct.WriteU16(h);
|
||||
this.struct?.WriteU16(w);
|
||||
this.struct?.WriteU16(h);
|
||||
}
|
||||
|
||||
|
||||
SetAddUserMessage(user: string) {
|
||||
this.SetTypeCode(MessageType.AddUser);
|
||||
this.struct.WriteString(user);
|
||||
this.struct?.WriteString(user);
|
||||
}
|
||||
|
||||
SetRemUserMessage(user: string) {
|
||||
this.SetTypeCode(MessageType.RemUser);
|
||||
this.struct.WriteString(user);
|
||||
this.struct?.WriteString(user);
|
||||
}
|
||||
|
||||
|
||||
// Setup some stuff and then return the final message
|
||||
Finish() {
|
||||
let endOffset = this.struct.Tell();
|
||||
this.struct.Seek(4); // seek to size offset
|
||||
this.struct.WriteU32(endOffset - kProtocolHeaderSize);
|
||||
this.struct.Seek(endOffset);
|
||||
return this.buffer.slice(0, endOffset);
|
||||
if(this.struct == null || this.buffer == null)
|
||||
throw new Error('no');
|
||||
|
||||
let endOffset :number = this.struct?.Tell();
|
||||
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() {
|
||||
this.struct.Seek(0);
|
||||
this.struct.WriteU16(kProtocolMagic);
|
||||
this.struct.WriteU16(0); // No message type yet
|
||||
this.struct.WriteU32(0); // No payload size yet
|
||||
this.struct?.Seek(0);
|
||||
this.struct?.WriteU16(kProtocolMagic);
|
||||
this.struct?.WriteU16(0); // No message type yet
|
||||
this.struct?.WriteU32(0); // No payload size yet
|
||||
}
|
||||
|
||||
private SetTypeCode(type: MessageType) {
|
||||
let oldOff = this.struct.Tell();
|
||||
this.struct.Seek(2); // seek to type offset
|
||||
this.struct.WriteU16(type);
|
||||
this.struct.Seek(oldOff);
|
||||
if(this.struct == null)
|
||||
throw new Error('no');
|
||||
|
||||
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> {
|
||||
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);
|
||||
res(message);
|
||||
|
||||
if(message != null) {
|
||||
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);
|
||||
|
||||
// Read and verify the header
|
||||
|
|
|
@ -36,7 +36,7 @@ export class Struct {
|
|||
return s;
|
||||
}
|
||||
|
||||
ReadStringLen(maxStringLength) {
|
||||
ReadStringLen(maxStringLength: number) {
|
||||
let stringLength = this.ReadU32();
|
||||
let s = '';
|
||||
|
||||
|
@ -97,20 +97,21 @@ export class Struct {
|
|||
// then copying
|
||||
|
||||
// Add an array with a fixed type
|
||||
WriteArray(arr, functor) {
|
||||
WriteArray(arr: any[], functor: any) {
|
||||
this.WriteU32(arr.length);
|
||||
for (let elem of arr) functor.call(this, elem);
|
||||
}
|
||||
|
||||
// Add a pascal UTF-16 string.
|
||||
WriteString(str) {
|
||||
WriteString(str: string) {
|
||||
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.
|
||||
// will trim strings that are too long
|
||||
WriteStringLen(str, len) {
|
||||
WriteStringLen(str: string, len: number) {
|
||||
let length = len;
|
||||
|
||||
// pick the string length, but ONLY
|
||||
|
@ -125,38 +126,39 @@ export class Struct {
|
|||
this.WriteU16(str.charCodeAt(i));
|
||||
}
|
||||
|
||||
WriteU8(i) {
|
||||
WriteU8(i: number) {
|
||||
this.dv.setUint8(this.byteOffset, i);
|
||||
this.byteOffset++;
|
||||
}
|
||||
|
||||
WriteS8(i) {
|
||||
WriteS8(i: number) {
|
||||
this.dv.setInt8(this.byteOffset, i);
|
||||
this.byteOffset++;
|
||||
}
|
||||
|
||||
WriteU16(i) {
|
||||
WriteU16(i: number) {
|
||||
this.dv.setUint16(this.byteOffset, i, false);
|
||||
this.byteOffset += 2;
|
||||
}
|
||||
|
||||
WriteS16(i) {
|
||||
WriteS16(i: number) {
|
||||
this.dv.setInt16(this.byteOffset, i, false);
|
||||
this.byteOffset += 2;
|
||||
}
|
||||
|
||||
WriteU32(i) {
|
||||
WriteU32(i: number) {
|
||||
this.dv.setUint32(this.byteOffset, i, false);
|
||||
this.byteOffset += 4;
|
||||
}
|
||||
|
||||
WriteS32(i) {
|
||||
WriteS32(i: number) {
|
||||
this.dv.setInt32(this.byteOffset, i, false);
|
||||
this.byteOffset += 4;
|
||||
}
|
||||
|
||||
WriteBuffer(buffer: ArrayBuffer) {
|
||||
let u8ar = new Uint8Array(buffer);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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..?
|
||||
}
|
||||
}
|
|
@ -1,27 +1,10 @@
|
|||
// This is the base tsconfig the entire Socket2 project uses
|
||||
{
|
||||
"files": [],
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"noEmitOnError": true,
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": "./",
|
||||
|
||||
"paths": {
|
||||
"@socketcomputer/shared*": [ "shared/src/*" ],
|
||||
"@socketcomputer/backend*": [ "backend/src/*" ],
|
||||
"@socketcomputer/qemu*": [ "qemu/src/*" ]
|
||||
},
|
||||
},
|
||||
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
],
|
||||
|
||||
"references": [
|
||||
{ "path": "./backend" },
|
||||
{ "path": "./qemu" },
|
||||
{ "path": "./shared" },
|
||||
]
|
||||
"target": "ES2022",
|
||||
"module": "ES2022",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,8 @@
|
|||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@parcel/transformer-sass": "^2.12.0",
|
||||
"parcel": "^2.12.0",
|
||||
"typescript": "^5.4.3"
|
||||
"parcel": "^2.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"nanoevents": "^9.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,10 @@ import * as Shared from '@socketcomputer/shared';
|
|||
import {GetKeysym} from "./keyboard";
|
||||
import {Mouse} from "./mouse";
|
||||
|
||||
|
||||
type UserRecord = {
|
||||
username: string
|
||||
};
|
||||
|
||||
let turnInt: number = -1;
|
||||
|
||||
async function sleep(ms: number) : Promise<void> {
|
||||
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 timer = document.querySelector('.turn-timer') as HTMLDivElement;
|
||||
|
||||
|
@ -24,6 +25,7 @@ function waitingTimer(text, ms, dot: boolean = true) {
|
|||
clearInterval(turnInt);
|
||||
}
|
||||
|
||||
// @ts-ignore (for some reason it's assuming these are Node)
|
||||
turnInt = setInterval(() => {
|
||||
ms -= 1000;
|
||||
let seconds = Math.floor(ms / 1000);
|
||||
|
@ -47,7 +49,7 @@ function waitingTimer(text, ms, dot: boolean = true) {
|
|||
|
||||
// client for
|
||||
class SocketClient {
|
||||
private websocket: WebSocket = null;
|
||||
private websocket: WebSocket|null = null;
|
||||
private url = "";
|
||||
|
||||
private selfNamed = false;
|
||||
|
@ -57,8 +59,8 @@ class SocketClient {
|
|||
private hasTurn = false;
|
||||
private mouse = new Mouse();
|
||||
|
||||
private canvas:HTMLCanvasElement = null;
|
||||
private canvasCtx : CanvasRenderingContext2D = null;
|
||||
private canvas:HTMLCanvasElement|null = null;
|
||||
private canvasCtx : CanvasRenderingContext2D|null = null;
|
||||
|
||||
|
||||
constructor(url: string, canvas: HTMLCanvasElement) {
|
||||
|
@ -219,9 +221,9 @@ class SocketClient {
|
|||
}
|
||||
|
||||
private async onWsClose() {
|
||||
this.websocket.removeEventListener("open", this.onWsOpen);
|
||||
this.websocket.removeEventListener("message", this.onWsMessage);
|
||||
this.websocket.removeEventListener("close", this.onWsClose);
|
||||
this.websocket?.removeEventListener("open", this.onWsOpen);
|
||||
this.websocket?.removeEventListener("message", this.onWsMessage);
|
||||
this.websocket?.removeEventListener("close", this.onWsClose);
|
||||
this.websocket = null;
|
||||
|
||||
// reset state
|
||||
|
@ -245,7 +247,7 @@ class SocketClient {
|
|||
|
||||
async SendBuffer(buffer: ArrayBuffer): Promise<void> {
|
||||
return new Promise((res, rej) => {
|
||||
this.websocket.send(buffer);
|
||||
this.websocket?.send(buffer);
|
||||
res();
|
||||
});
|
||||
}
|
||||
|
@ -275,8 +277,10 @@ class SocketClient {
|
|||
}
|
||||
|
||||
private resizeDisplay(message: Shared.DisplaySizeMessage) {
|
||||
this.canvas.width = message.width;
|
||||
this.canvas.height = message.height;
|
||||
if(this.canvas == null)
|
||||
return;
|
||||
this.canvas!.width = message.width;
|
||||
this.canvas!.height = message.height;
|
||||
}
|
||||
|
||||
private updateUserCount() {
|
||||
|
@ -327,7 +331,7 @@ class SocketClient {
|
|||
let blob = new Blob([message.data]);
|
||||
createImageBitmap(blob)
|
||||
.then((image) => {
|
||||
this.canvasCtx.drawImage(image, message.x, message.y);
|
||||
this.canvasCtx?.drawImage(image, message.x, message.y);
|
||||
}).catch((err) => {
|
||||
console.error(`Error decoding rect for some reason...`, err);
|
||||
});
|
||||
|
|
|
@ -1,19 +1,6 @@
|
|||
{
|
||||
"extends": "../tsconfig-base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
|
||||
"lib": ["DOM", "ESNext"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"target": "ES6",
|
||||
|
||||
"outDir": "./dist",
|
||||
"baseUrl": "."
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../shared" }
|
||||
]
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM"],
|
||||
}
|
||||
}
|
||||
|
|
323
yarn.lock
323
yarn.lock
|
@ -83,11 +83,36 @@
|
|||
dependencies:
|
||||
"@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":
|
||||
version "2.8.5"
|
||||
resolved "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.8.5.tgz"
|
||||
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":
|
||||
version "1.0.11"
|
||||
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"
|
||||
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":
|
||||
version "3.0.2"
|
||||
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==
|
||||
|
||||
"@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":
|
||||
version "2.12.0"
|
||||
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-svg" "2.12.0"
|
||||
|
||||
"@parcel/core@^2.12.0", "@parcel/core@2.12.0":
|
||||
"@parcel/core@2.12.0":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.npmjs.org/@parcel/core/-/core-2.12.0.tgz"
|
||||
integrity sha512-s+6pwEj+GfKf7vqGUzN9iSEPueUssCCQrCBUlcAfKrJe0a22hTUCjewpB0I7lNrCIULt8dkndD+sMdOrXsRl6Q==
|
||||
|
@ -415,6 +465,13 @@
|
|||
"@parcel/utils" "2.12.0"
|
||||
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":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.npmjs.org/@parcel/packager-wasm/-/packager-wasm-2.12.0.tgz"
|
||||
|
@ -667,6 +724,25 @@
|
|||
posthtml-render "^3.0.0"
|
||||
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":
|
||||
version "2.12.0"
|
||||
resolved "https://registry.npmjs.org/@parcel/types/-/types-2.12.0.tgz"
|
||||
|
@ -694,6 +770,41 @@
|
|||
chalk "^4.1.0"
|
||||
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":
|
||||
version "2.4.1"
|
||||
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"
|
||||
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":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz"
|
||||
|
@ -739,35 +865,30 @@
|
|||
"@parcel/utils" "2.12.0"
|
||||
nullthrows "^1.1.1"
|
||||
|
||||
"@socketcomputer/backend@file:/home/lily/source/socket-revamp/backend":
|
||||
version "1.0.0"
|
||||
resolved "file:backend"
|
||||
dependencies:
|
||||
"@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"
|
||||
"@swc/core-darwin-arm64@1.4.11":
|
||||
version "1.4.11"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.11.tgz#91ef40816e10495a4038a98dc6c8dfcc85d9c59b"
|
||||
integrity sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==
|
||||
|
||||
"@socketcomputer/qemu@*", "@socketcomputer/qemu@file:/home/lily/source/socket-revamp/qemu":
|
||||
version "1.0.0"
|
||||
resolved "file:qemu"
|
||||
dependencies:
|
||||
canvas "^2.11.2"
|
||||
execa "^8.0.1"
|
||||
split "^1.0.1"
|
||||
"@swc/core-darwin-x64@1.4.11":
|
||||
version "1.4.11"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.11.tgz#6f71e3cd4687ef5df226ba0b8a20adc52fa7dc9e"
|
||||
integrity sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==
|
||||
|
||||
"@socketcomputer/shared@*", "@socketcomputer/shared@file:/home/lily/source/socket-revamp/shared":
|
||||
version "1.0.0"
|
||||
resolved "file:shared"
|
||||
"@swc/core-linux-arm-gnueabihf@1.4.11":
|
||||
version "1.4.11"
|
||||
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":
|
||||
version "1.0.0"
|
||||
resolved "file:webapp"
|
||||
dependencies:
|
||||
nanoevents "^9.0.0"
|
||||
"@swc/core-linux-arm64-gnu@1.4.11":
|
||||
version "1.4.11"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.11.tgz#9485bc591aa573b282d08b168b80a60badb8df9b"
|
||||
integrity sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==
|
||||
|
||||
"@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":
|
||||
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"
|
||||
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":
|
||||
version "1.4.11"
|
||||
resolved "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz"
|
||||
|
@ -829,6 +965,21 @@
|
|||
dependencies:
|
||||
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":
|
||||
version "8.5.10"
|
||||
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:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
browserslist@^4.6.6, "browserslist@>= 4.21.0":
|
||||
browserslist@^4.6.6:
|
||||
version "4.23.0"
|
||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz"
|
||||
integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
|
||||
|
@ -1029,6 +1180,11 @@ buffer@^6.0.3:
|
|||
base64-js "^1.3.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:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
|
||||
|
@ -1137,16 +1293,16 @@ color-convert@^2.0.1:
|
|||
dependencies:
|
||||
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:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
||||
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:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz"
|
||||
|
@ -1229,7 +1385,7 @@ csso@^4.2.0:
|
|||
dependencies:
|
||||
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"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
|
||||
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"
|
||||
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
|
||||
|
||||
detect-libc@^2.0.0:
|
||||
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:
|
||||
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==
|
||||
|
@ -1527,6 +1678,11 @@ fs.realpath@^1.0.0:
|
|||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||
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:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz"
|
||||
|
@ -1675,7 +1831,7 @@ inflight@^1.0.4:
|
|||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@^2.0.3, inherits@2:
|
||||
inherits@2, inherits@^2.0.3, inherits@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
@ -1791,6 +1947,36 @@ light-my-request@^5.11.0:
|
|||
process-warning "^3.0.0"
|
||||
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:
|
||||
version "1.24.1"
|
||||
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"
|
||||
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:
|
||||
version "1.24.1"
|
||||
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"
|
||||
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:
|
||||
version "5.1.0"
|
||||
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"
|
||||
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:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/split/-/split-1.0.1.tgz"
|
||||
|
@ -2499,12 +2690,7 @@ split@^1.0.1:
|
|||
dependencies:
|
||||
through "2"
|
||||
|
||||
split2@^4.0.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz"
|
||||
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
|
||||
|
||||
srcset@4, srcset@4.0.0:
|
||||
srcset@4:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz"
|
||||
integrity sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==
|
||||
|
@ -2514,18 +2700,21 @@ stable@^0.1.8:
|
|||
resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz"
|
||||
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:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz"
|
||||
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:
|
||||
version "4.2.3"
|
||||
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"
|
||||
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:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||
|
@ -2566,7 +2762,7 @@ supports-color@^7.1.0:
|
|||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
svgo@^2.4.0, svgo@^3.0.2:
|
||||
svgo@^2.4.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz"
|
||||
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
|
||||
|
@ -2736,6 +2932,11 @@ ws@^8.0.0:
|
|||
resolved "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz"
|
||||
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:
|
||||
version "5.0.8"
|
||||
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
|
||||
|
|
Loading…
Reference in a new issue