bring over removal of node canvas

This commit is contained in:
Lily Tsuru 2024-07-24 04:47:12 -04:00
parent 203e8c258c
commit b127e37323
16 changed files with 666 additions and 398 deletions

2
.gitignore vendored
View file

@ -5,3 +5,5 @@ node_modules/
/.parcel-cache /.parcel-cache
# nvm it does now ok # nvm it does now ok
/webapp/.parcel-cache /webapp/.parcel-cache
/jpeg-rs/target

Binary file not shown.

View file

@ -17,8 +17,8 @@
"dependencies": { "dependencies": {
"@computernewb/superqemu": "^0.1.0", "@computernewb/superqemu": "^0.1.0",
"@fastify/websocket": "^10.0.1", "@fastify/websocket": "^10.0.1",
"@socketcomputer/jpeg-rs": "*",
"@socketcomputer/shared": "*", "@socketcomputer/shared": "*",
"canvas": "^2.11.2",
"fastify": "^4.26.2", "fastify": "^4.26.2",
"mnemonist": "^0.39.8" "mnemonist": "^0.39.8"
}, },

View file

@ -0,0 +1,20 @@
import * as jpeg from '@socketcomputer/jpeg-rs';
import { Size, Rect } from '@computernewb/superqemu';
let gJpegQuality = 20;
export class JPEGEncoder {
static SetQuality(quality: number) {
gJpegQuality = quality;
}
static async Encode(canvas: Buffer, displaySize: Size, rect: Rect): Promise<Buffer> {
let offset = (rect.y * displaySize.width + rect.x) * 4;
return jpeg.jpegEncode({
width: rect.width,
height: rect.height,
stride: displaySize.width,
buffer: canvas.subarray(offset)
});
}
}

View file

@ -1,21 +1,14 @@
import { EventEmitter } from 'node:events'; import { EventEmitter } from 'node:events';
import { TurnQueue, UserTimeTuple, kTurnTimeSeconds } from './TurnQueue.js'; import { TurnQueue, UserTimeTuple, kTurnTimeSeconds } from './TurnQueue.js';
import { VMUser } from './VMUser.js'; import { VMUser } from './VMUser.js';
import { QemuDisplay, QemuVM, VMState } from '@computernewb/superqemu'; import { QemuDisplay, QemuVM, Rect, Size, VMState } from '@computernewb/superqemu';
import { ExtendableTimer } from './ExtendableTimer.js'; import { ExtendableTimer } from './ExtendableTimer.js';
import { kMaxUserNameLength } from '@socketcomputer/shared'; import { kMaxUserNameLength } from '@socketcomputer/shared';
import * as Shared from '@socketcomputer/shared'; import * as Shared from '@socketcomputer/shared';
import { Canvas } from 'canvas';
import pino from 'pino'; import pino from 'pino';
import { JPEGEncoder } from './JPEGEncoder.js';
// for the maximum socket.io experience
const kCanvasJpegQuality = 0.25;
function EncodeCanvas(canvas: Canvas): Buffer {
return canvas.toBuffer('image/jpeg', { quality: kCanvasJpegQuality });
}
export class SocketVM extends EventEmitter { export class SocketVM extends EventEmitter {
private vm: QemuVM; private vm: QemuVM;
@ -195,52 +188,70 @@ export class SocketVM extends EventEmitter {
} }
} }
private async InsertCD(isoPath: string) {
await this.vm.ChangeRemovableMedia('vm.cd', isoPath);
}
private async VMRunning() { private async VMRunning() {
let self = this; let self = this;
// Hook up the display this.display = this.vm.GetDisplay();
this.display?.on('resize', async (width: number, height: number) => {
if (self.display == null) return;
let buffers = this.MakeFullScreenData();
for (let buffer of buffers) await self.BroadcastBuffer(buffer);
});
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);
let buffer = EncodeCanvas(canvas);
await this.BroadcastMessage((encoder: Shared.MessageEncoder) => {
encoder.Init(buffer.length + 8);
encoder.SetDisplayRectMessage(x, y, buffer);
return encoder.Finish();
});
});
this.display?.on('resize', (size: Size) => self.OnDisplayResized(size));
this.display?.on('rect', (rect: Rect) => self.OnDisplayRectangle(rect));
this.timer.Start(); this.timer.Start();
} }
private MakeFullScreenData(): Array<Buffer> { private async OnDisplayRectangle(rect: Rect) {
let encoded = await this.MakeRectData(rect);
await this.BroadcastMessage((encoder: Shared.MessageEncoder) => {
encoder.Init(encoded.length + 8);
encoder.SetDisplayRectMessage(rect.x, rect.y, encoded);
return encoder.Finish();
});
}
private async OnDisplayResized(size: Size) {
let arr = await this.MakeFullScreen();
for(let user of this.users) {
for(let msg of arr) {
await user.SendBuffer(msg);
}
}
}
private async MakeRectData(rect: Rect) {
let display = this.vm.GetDisplay();
// TODO: actually throw an error here
if (display == null) return Buffer.from('no');
let displaySize = display.Size();
let encoded = await JPEGEncoder.Encode(display.Buffer(), displaySize, rect);
return encoded;
}
private async MakeFullScreen() {
let disp = this.display;
if (disp == null) return [];
let dispSize = disp.Size();
let arr: Array<Buffer> = []; let arr: Array<Buffer> = [];
const addMessage = (enc: (encoder: Shared.MessageEncoder) => ArrayBuffer) => { const addMessage = (enc: (encoder: Shared.MessageEncoder) => ArrayBuffer) => {
arr.push(Buffer.from(enc(new Shared.MessageEncoder()))); arr.push(Buffer.from(enc(new Shared.MessageEncoder())));
}; };
if (this.display == null) return arr; let buffer = await this.MakeRectData({
x: 0,
let buffer = EncodeCanvas(this.display.GetCanvas()); y: 0,
width: dispSize.width,
height: dispSize.height
});
addMessage((encoder: Shared.MessageEncoder) => { addMessage((encoder: Shared.MessageEncoder) => {
encoder.Init(8); encoder.Init(8);
encoder.SetDisplaySizeMessage(this.display!.Size().width, this.display!.Size().height); encoder.SetDisplaySizeMessage(dispSize.width, dispSize.height);
return encoder.Finish(); return encoder.Finish();
}); });
@ -249,19 +260,17 @@ export class SocketVM extends EventEmitter {
encoder.SetDisplayRectMessage(0, 0, buffer); encoder.SetDisplayRectMessage(0, 0, buffer);
return encoder.Finish(); return encoder.Finish();
}); });
return arr; return arr;
} }
private async SendInitialScreen(user: VMUser) { private async SendInitialScreen(user: VMUser) {
if (this.display == null) return; let arr = await this.MakeFullScreen();
for (let buffer of arr) await user.SendBuffer(buffer);
let buffers = this.MakeFullScreenData();
for (let buffer of buffers) await user.SendBuffer(buffer);
} }
private async VMStopped() { private async VMStopped() {
this.display = null;
await this.vm.Start(); await this.vm.Start();
} }
} }

333
jpeg-rs/Cargo.lock generated Normal file
View file

@ -0,0 +1,333 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anyhow"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "backtrace"
version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "cc"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cmake"
version = "0.1.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
dependencies = [
"cc",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gimli"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
[[package]]
name = "jpeg-rs"
version = "0.1.0"
dependencies = [
"neon",
"once_cell",
"tokio",
"turbojpeg-sys",
]
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
]
[[package]]
name = "neon"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d75440242411c87dc39847b0e33e961ec1f10326a9d8ecf9c1ea64a3b3c13dc"
dependencies = [
"getrandom",
"libloading",
"neon-macros",
"once_cell",
"semver",
"send_wrapper",
"smallvec",
]
[[package]]
name = "neon-macros"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6813fde79b646e47e7ad75f480aa80ef76a5d9599e2717407961531169ee38b"
dependencies = [
"quote",
"syn",
"syn-mid",
]
[[package]]
name = "object"
version = "0.36.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pkg-config"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "semver"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "send_wrapper"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "syn"
version = "2.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn-mid"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5dc35bb08dd1ca3dfb09dce91fd2d13294d6711c88897d9a9d60acf39bce049"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.39.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a"
dependencies = [
"backtrace",
"pin-project-lite",
]
[[package]]
name = "turbojpeg-sys"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fa6daade3b979fb7454cce5ebcb9772ce7a1cf476ea27ed20ed06e13d9bc983"
dependencies = [
"anyhow",
"cmake",
"libc",
"pkg-config",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

17
jpeg-rs/Cargo.toml Normal file
View file

@ -0,0 +1,17 @@
[package]
name = "jpeg-rs"
description = "JPEG utility library for socket2"
version = "0.1.0"
edition = "2021"
exclude = ["index.node"]
[lib]
crate-type = ["cdylib"]
[dependencies]
neon = "1"
# Required for JPEG
once_cell = "1.19.0"
tokio = { version = "1.38.0", features = [ "rt", "rt-multi-thread" ] }
turbojpeg-sys = "1.0.0"

15
jpeg-rs/index.d.ts vendored Normal file
View file

@ -0,0 +1,15 @@
//
interface JpegInputArgs {
width: number,
height: number,
stride: number, // The width of your input framebuffer OR your image width (if encoding a full image)
buffer: Buffer
// TODO: Allow different formats, or export a boxed ffi object which can store a format
// (i.e: new JpegEncoder(FORMAT_xxx)).
}
/// Performs JPEG encoding.
export function jpegEncode(input: JpegInputArgs) : Promise<Buffer>;

6
jpeg-rs/index.js Normal file
View file

@ -0,0 +1,6 @@
// *sigh*
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
export let {guacDecode, guacEncode, jpegEncode} = require('./index.node');

BIN
jpeg-rs/index.node Executable file

Binary file not shown.

16
jpeg-rs/package.json Normal file
View file

@ -0,0 +1,16 @@
{
"name": "@socketcomputer/jpeg-rs",
"version": "0.1.0",
"packageManager": "yarn@4.3.1",
"type": "module",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"build": "cargo-cp-artifact -nc index.node -- cargo build --release --message-format=json-render-diagnostics",
"install": "yarn build",
"test": "cargo test"
},
"devDependencies": {
"cargo-cp-artifact": "^0.1"
}
}

View file

@ -0,0 +1,82 @@
use turbojpeg_sys::*;
pub struct Image<'a> {
pub buffer: &'a [u8],
pub width: u32,
pub height: u32,
pub stride: u32,
pub format: TJPF,
}
pub struct JpegCompressor {
handle: tjhandle,
subsamp: TJSAMP,
quality: u32,
}
unsafe impl Send for JpegCompressor {}
impl JpegCompressor {
pub fn new() -> Self {
unsafe {
let init = Self {
handle: tjInitCompress(),
subsamp: TJSAMP_TJSAMP_422,
quality: 95,
};
return init;
}
}
pub fn set_quality(&mut self, quality: u32) {
self.quality = quality;
}
pub fn set_subsamp(&mut self, samp: TJSAMP) {
self.subsamp = samp;
}
pub fn compress_buffer<'a>(&self, image: &Image<'a>) -> Vec<u8> {
unsafe {
let size: usize =
tjBufSize(image.width as i32, image.height as i32, self.subsamp) as usize;
let mut vec = Vec::with_capacity(size);
vec.resize(size, 0);
let mut ptr: *mut u8 = vec.as_mut_ptr();
let mut size: u64 = 0;
let res = tjCompress2(
self.handle,
image.buffer.as_ptr(),
image.width as i32,
image.stride as i32,
image.height as i32,
image.format,
std::ptr::addr_of_mut!(ptr),
std::ptr::addr_of_mut!(size),
self.subsamp,
self.quality as i32,
(TJFLAG_NOREALLOC) as i32,
);
// TODO: Result sex so we can actually notify failure
if res == -1 {
return Vec::new();
}
// Truncate down to the size we're given back
vec.truncate(size as usize);
return vec;
}
}
}
impl Drop for JpegCompressor {
fn drop(&mut self) {
unsafe {
tjDestroy(self.handle);
}
}
}

87
jpeg-rs/src/jpeg_js.rs Normal file
View file

@ -0,0 +1,87 @@
use std::sync::{Arc, Mutex};
use neon::prelude::*;
use neon::types::buffer::TypedArray;
use once_cell::sync::OnceCell;
use tokio::runtime::Runtime;
use std::cell::RefCell;
use crate::jpeg_compressor::*;
/// Gives a static Tokio runtime. We should replace this with
/// rayon or something, but for now tokio works.
fn runtime<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static Runtime> {
static RUNTIME: OnceCell<Runtime> = OnceCell::new();
RUNTIME
.get_or_try_init(Runtime::new)
.or_else(|err| cx.throw_error(&err.to_string()))
}
thread_local! {
static COMPRESSOR: RefCell<JpegCompressor> = RefCell::new(JpegCompressor::new());
}
fn jpeg_encode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsPromise> {
let input = cx.argument::<JsObject>(0)?;
// Get our input arguments here
let width: u64 = input.get::<JsNumber, _, _>(cx, "width")?.value(cx) as u64;
let height: u64 = input.get::<JsNumber, _, _>(cx, "height")?.value(cx) as u64;
let stride: u64 = input.get::<JsNumber, _, _>(cx, "stride")?.value(cx) as u64;
let buffer: Handle<JsBuffer> = input.get(cx, "buffer")?;
let (deferred, promise) = cx.promise();
let channel = cx.channel();
let runtime = runtime(cx)?;
let buf = buffer.as_slice(cx);
let copy: Arc<Mutex<Vec<u8>>> = Arc::new(Mutex::new(Vec::with_capacity(buf.len())));
// Copy from the node buffer to our temporary buffer
{
let mut locked = copy.lock().unwrap();
let cap = locked.capacity();
locked.resize(cap, 0);
locked.copy_from_slice(buf);
}
// Spawn off a tokio blocking pool thread that will do the work for us
runtime.spawn_blocking(move || {
let clone = Arc::clone(&copy);
let locked = clone.lock().unwrap();
let image: Image = Image {
buffer: locked.as_slice(),
width: width as u32,
height: height as u32,
stride: (stride * 4u64) as u32, // I think?
format: turbojpeg_sys::TJPF_TJPF_RGBA,
};
let vec = COMPRESSOR.with(|lazy| {
let mut b = lazy.borrow_mut();
b.set_quality(35);
b.set_subsamp(turbojpeg_sys::TJSAMP_TJSAMP_420);
b.compress_buffer(&image)
});
// Fulfill the Javascript promise with our encoded buffer
deferred.settle_with(&channel, move |mut cx| {
let mut buf = cx.buffer(vec.len())?;
let slice = buf.as_mut_slice(&mut cx);
slice.copy_from_slice(vec.as_slice());
Ok(buf)
});
});
Ok(promise)
}
pub fn jpeg_encode(mut cx: FunctionContext) -> JsResult<JsPromise> {
jpeg_encode_impl(&mut cx)
}

13
jpeg-rs/src/lib.rs Normal file
View file

@ -0,0 +1,13 @@
mod jpeg_compressor;
mod jpeg_js;
use neon::prelude::*;
#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
// Mostly transitionary, later on API should change
cx.export_function("jpegEncode", jpeg_js::jpeg_encode)?;
Ok(())
}

View file

@ -2,6 +2,7 @@
"name": "socketcomputer-repo", "name": "socketcomputer-repo",
"workspaces": [ "workspaces": [
"shared", "shared",
"jpeg-rs",
"backend", "backend",
"webapp" "webapp"
], ],
@ -11,7 +12,6 @@
"build:frontend": "npm -w shared run build && npm -w webapp run build" "build:frontend": "npm -w shared run build && npm -w webapp run build"
}, },
"dependencies": { "dependencies": {
"canvas": "^2.11.2",
"pino": "^9.3.1" "pino": "^9.3.1"
}, },
"devDependencies": { "devDependencies": {

370
yarn.lock
View file

@ -171,25 +171,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@mapbox/node-pre-gyp@npm:^1.0.0":
version: 1.0.11
resolution: "@mapbox/node-pre-gyp@npm:1.0.11"
dependencies:
detect-libc: "npm:^2.0.0"
https-proxy-agent: "npm:^5.0.0"
make-dir: "npm:^3.1.0"
node-fetch: "npm:^2.6.7"
nopt: "npm:^5.0.0"
npmlog: "npm:^5.0.1"
rimraf: "npm:^3.0.2"
semver: "npm:^7.3.5"
tar: "npm:^6.1.11"
bin:
node-pre-gyp: bin/node-pre-gyp
checksum: 10c0/2b24b93c31beca1c91336fa3b3769fda98e202fb7f9771f0f4062588d36dcc30fcf8118c36aa747fa7f7610d8cf601872bdaaf62ce7822bb08b545d1bbe086cc
languageName: node
linkType: hard
"@mischnic/json-sourcemap@npm:^0.1.0": "@mischnic/json-sourcemap@npm:^0.1.0":
version: 0.1.1 version: 0.1.1
resolution: "@mischnic/json-sourcemap@npm:0.1.1" resolution: "@mischnic/json-sourcemap@npm:0.1.1"
@ -1159,15 +1140,23 @@ __metadata:
dependencies: dependencies:
"@computernewb/superqemu": "npm:^0.1.0" "@computernewb/superqemu": "npm:^0.1.0"
"@fastify/websocket": "npm:^10.0.1" "@fastify/websocket": "npm:^10.0.1"
"@socketcomputer/jpeg-rs": "npm:*"
"@socketcomputer/shared": "npm:*" "@socketcomputer/shared": "npm:*"
"@types/ws": "npm:^8.5.10" "@types/ws": "npm:^8.5.10"
canvas: "npm:^2.11.2"
fastify: "npm:^4.26.2" fastify: "npm:^4.26.2"
mnemonist: "npm:^0.39.8" mnemonist: "npm:^0.39.8"
parcel: "npm:^2.12.0" parcel: "npm:^2.12.0"
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@socketcomputer/jpeg-rs@npm:*, @socketcomputer/jpeg-rs@workspace:jpeg-rs":
version: 0.0.0-use.local
resolution: "@socketcomputer/jpeg-rs@workspace:jpeg-rs"
dependencies:
cargo-cp-artifact: "npm:^0.1"
languageName: unknown
linkType: soft
"@socketcomputer/shared@npm:*, @socketcomputer/shared@workspace:shared": "@socketcomputer/shared@npm:*, @socketcomputer/shared@workspace:shared":
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "@socketcomputer/shared@workspace:shared" resolution: "@socketcomputer/shared@workspace:shared"
@ -1350,13 +1339,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"abbrev@npm:1":
version: 1.1.1
resolution: "abbrev@npm:1.1.1"
checksum: 10c0/3f762677702acb24f65e813070e306c61fafe25d4b2583f9dfc935131f774863f3addd5741572ed576bd69cabe473c5af18e1e108b829cb7b6b4747884f726e6
languageName: node
linkType: hard
"abbrev@npm:^2.0.0": "abbrev@npm:^2.0.0":
version: 2.0.0 version: 2.0.0
resolution: "abbrev@npm:2.0.0" resolution: "abbrev@npm:2.0.0"
@ -1387,15 +1369,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"agent-base@npm:6":
version: 6.0.2
resolution: "agent-base@npm:6.0.2"
dependencies:
debug: "npm:4"
checksum: 10c0/dc4f757e40b5f3e3d674bc9beb4f1048f4ee83af189bae39be99f57bf1f48dde166a8b0a5342a84b5944ee8e6ed1e5a9d801858f4ad44764e84957122fe46261
languageName: node
linkType: hard
"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": "agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1":
version: 7.1.1 version: 7.1.1
resolution: "agent-base@npm:7.1.1" resolution: "agent-base@npm:7.1.1"
@ -1490,13 +1463,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"aproba@npm:^1.0.3 || ^2.0.0":
version: 2.0.0
resolution: "aproba@npm:2.0.0"
checksum: 10c0/d06e26384a8f6245d8c8896e138c0388824e259a329e0c9f196b4fa533c82502a6fd449586e3604950a0c42921832a458bb3aa0aa9f0ba449cfd4f50fd0d09b5
languageName: node
linkType: hard
"archy@npm:^1.0.0": "archy@npm:^1.0.0":
version: 1.0.0 version: 1.0.0
resolution: "archy@npm:1.0.0" resolution: "archy@npm:1.0.0"
@ -1504,16 +1470,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"are-we-there-yet@npm:^2.0.0":
version: 2.0.0
resolution: "are-we-there-yet@npm:2.0.0"
dependencies:
delegates: "npm:^1.0.0"
readable-stream: "npm:^3.6.0"
checksum: 10c0/375f753c10329153c8d66dc95e8f8b6c7cc2aa66e05cb0960bd69092b10dae22900cacc7d653ad11d26b3ecbdbfe1e8bfb6ccf0265ba8077a7d979970f16b99c
languageName: node
linkType: hard
"argparse@npm:^2.0.1": "argparse@npm:^2.0.1":
version: 2.0.1 version: 2.0.1
resolution: "argparse@npm:2.0.1" resolution: "argparse@npm:2.0.1"
@ -1577,16 +1533,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"brace-expansion@npm:^1.1.7":
version: 1.1.11
resolution: "brace-expansion@npm:1.1.11"
dependencies:
balanced-match: "npm:^1.0.0"
concat-map: "npm:0.0.1"
checksum: 10c0/695a56cd058096a7cb71fb09d9d6a7070113c7be516699ed361317aca2ec169f618e28b8af352e02ab4233fb54eb0168460a40dc320bab0034b36ab59aaad668
languageName: node
linkType: hard
"brace-expansion@npm:^2.0.1": "brace-expansion@npm:^2.0.1":
version: 2.0.1 version: 2.0.1
resolution: "brace-expansion@npm:2.0.1" resolution: "brace-expansion@npm:2.0.1"
@ -1670,15 +1616,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"canvas@npm:^2.11.2": "cargo-cp-artifact@npm:^0.1":
version: 2.11.2 version: 0.1.9
resolution: "canvas@npm:2.11.2" resolution: "cargo-cp-artifact@npm:0.1.9"
dependencies: bin:
"@mapbox/node-pre-gyp": "npm:^1.0.0" cargo-cp-artifact: bin/cargo-cp-artifact.js
nan: "npm:^2.17.0" checksum: 10c0/60eb1845917cfb021920fcf600a72379890b385396f9c69107face3b16b347960b66cd3d82cc169c6ac8b1212cf0706584125bc36fbc08353b033310c17ca0a6
node-gyp: "npm:latest"
simple-get: "npm:^3.0.3"
checksum: 10c0/943368798ad1b66b18633aa34b6181e1038dac5433fc9727cd07be35f0a633f572b60d9edb95f5ff90b6a9128e86d5312035f91a2934101c73185b15d906230a
languageName: node languageName: node
linkType: hard linkType: hard
@ -1782,15 +1725,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"color-support@npm:^1.1.2":
version: 1.1.3
resolution: "color-support@npm:1.1.3"
bin:
color-support: bin.js
checksum: 10c0/8ffeaa270a784dc382f62d9be0a98581db43e11eee301af14734a6d089bd456478b1a8b3e7db7ca7dc5b18a75f828f775c44074020b51c05fc00e6d0992b1cc6
languageName: node
linkType: hard
"commander@npm:^7.0.0, commander@npm:^7.2.0": "commander@npm:^7.0.0, commander@npm:^7.2.0":
version: 7.2.0 version: 7.2.0
resolution: "commander@npm:7.2.0" resolution: "commander@npm:7.2.0"
@ -1798,20 +1732,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"concat-map@npm:0.0.1":
version: 0.0.1
resolution: "concat-map@npm:0.0.1"
checksum: 10c0/c996b1cfdf95b6c90fee4dae37e332c8b6eb7d106430c17d538034c0ad9a1630cb194d2ab37293b1bdd4d779494beee7786d586a50bd9376fd6f7bcc2bd4c98f
languageName: node
linkType: hard
"console-control-strings@npm:^1.0.0, console-control-strings@npm:^1.1.0":
version: 1.1.0
resolution: "console-control-strings@npm:1.1.0"
checksum: 10c0/7ab51d30b52d461412cd467721bb82afe695da78fff8f29fe6f6b9cbaac9a2328e27a22a966014df9532100f6dd85370460be8130b9c677891ba36d96a343f50
languageName: node
linkType: hard
"cookie@npm:^0.6.0": "cookie@npm:^0.6.0":
version: 0.6.0 version: 0.6.0
resolution: "cookie@npm:0.6.0" resolution: "cookie@npm:0.6.0"
@ -1910,22 +1830,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"decompress-response@npm:^4.2.0":
version: 4.2.1
resolution: "decompress-response@npm:4.2.1"
dependencies:
mimic-response: "npm:^2.0.0"
checksum: 10c0/5e4821be332e80e3639acee2441c41d245fc07ac3ee85a6f28893c10c079d66d9bf09e8d84bffeae5656a4625e09e9b93fb4a5705adbe6b07202eea64fae1c8d
languageName: node
linkType: hard
"delegates@npm:^1.0.0":
version: 1.0.0
resolution: "delegates@npm:1.0.0"
checksum: 10c0/ba05874b91148e1db4bf254750c042bf2215febd23a6d3cda2e64896aef79745fbd4b9996488bd3cafb39ce19dbce0fd6e3b6665275638befffe1c9b312b91b5
languageName: node
linkType: hard
"detect-libc@npm:^1.0.3": "detect-libc@npm:^1.0.3":
version: 1.0.3 version: 1.0.3
resolution: "detect-libc@npm:1.0.3" resolution: "detect-libc@npm:1.0.3"
@ -1935,7 +1839,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"detect-libc@npm:^2.0.0, detect-libc@npm:^2.0.1": "detect-libc@npm:^2.0.1":
version: 2.0.3 version: 2.0.3
resolution: "detect-libc@npm:2.0.3" resolution: "detect-libc@npm:2.0.3"
checksum: 10c0/88095bda8f90220c95f162bf92cad70bd0e424913e655c20578600e35b91edc261af27531cf160a331e185c0ced93944bc7e09939143225f56312d7fd800fdb7 checksum: 10c0/88095bda8f90220c95f162bf92cad70bd0e424913e655c20578600e35b91edc261af27531cf160a331e185c0ced93944bc7e09939143225f56312d7fd800fdb7
@ -2295,13 +2199,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"fs.realpath@npm:^1.0.0":
version: 1.0.0
resolution: "fs.realpath@npm:1.0.0"
checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948
languageName: node
linkType: hard
"fsevents@npm:~2.3.2": "fsevents@npm:~2.3.2":
version: 2.3.3 version: 2.3.3
resolution: "fsevents@npm:2.3.3" resolution: "fsevents@npm:2.3.3"
@ -2321,23 +2218,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"gauge@npm:^3.0.0":
version: 3.0.2
resolution: "gauge@npm:3.0.2"
dependencies:
aproba: "npm:^1.0.3 || ^2.0.0"
color-support: "npm:^1.1.2"
console-control-strings: "npm:^1.0.0"
has-unicode: "npm:^2.0.1"
object-assign: "npm:^4.1.1"
signal-exit: "npm:^3.0.0"
string-width: "npm:^4.2.3"
strip-ansi: "npm:^6.0.1"
wide-align: "npm:^1.1.2"
checksum: 10c0/75230ccaf216471e31025c7d5fcea1629596ca20792de50c596eb18ffb14d8404f927cd55535aab2eeecd18d1e11bd6f23ec3c2e9878d2dda1dc74bccc34b913
languageName: node
linkType: hard
"get-port@npm:^4.2.0": "get-port@npm:^4.2.0":
version: 4.2.0 version: 4.2.0
resolution: "get-port@npm:4.2.0" resolution: "get-port@npm:4.2.0"
@ -2377,20 +2257,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"glob@npm:^7.1.3":
version: 7.2.3
resolution: "glob@npm:7.2.3"
dependencies:
fs.realpath: "npm:^1.0.0"
inflight: "npm:^1.0.4"
inherits: "npm:2"
minimatch: "npm:^3.1.1"
once: "npm:^1.3.0"
path-is-absolute: "npm:^1.0.0"
checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe
languageName: node
linkType: hard
"globals@npm:^13.2.0": "globals@npm:^13.2.0":
version: 13.24.0 version: 13.24.0
resolution: "globals@npm:13.24.0" resolution: "globals@npm:13.24.0"
@ -2421,13 +2287,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"has-unicode@npm:^2.0.1":
version: 2.0.1
resolution: "has-unicode@npm:2.0.1"
checksum: 10c0/ebdb2f4895c26bb08a8a100b62d362e49b2190bcfd84b76bc4be1a3bd4d254ec52d0dd9f2fbcc093fc5eb878b20c52146f9dfd33e2686ed28982187be593b47c
languageName: node
linkType: hard
"htmlnano@npm:^2.0.0": "htmlnano@npm:^2.0.0":
version: 2.1.0 version: 2.1.0
resolution: "htmlnano@npm:2.1.0" resolution: "htmlnano@npm:2.1.0"
@ -2494,16 +2353,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"https-proxy-agent@npm:^5.0.0":
version: 5.0.1
resolution: "https-proxy-agent@npm:5.0.1"
dependencies:
agent-base: "npm:6"
debug: "npm:4"
checksum: 10c0/6dd639f03434003577c62b27cafdb864784ef19b2de430d8ae2a1d45e31c4fd60719e5637b44db1a88a046934307da7089e03d6089ec3ddacc1189d8de8897d1
languageName: node
linkType: hard
"https-proxy-agent@npm:^7.0.1": "https-proxy-agent@npm:^7.0.1":
version: 7.0.5 version: 7.0.5
resolution: "https-proxy-agent@npm:7.0.5" resolution: "https-proxy-agent@npm:7.0.5"
@ -2568,17 +2417,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"inflight@npm:^1.0.4": "inherits@npm:^2.0.3, inherits@npm:^2.0.4":
version: 1.0.6
resolution: "inflight@npm:1.0.6"
dependencies:
once: "npm:^1.3.0"
wrappy: "npm:1"
checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2
languageName: node
linkType: hard
"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4":
version: 2.0.4 version: 2.0.4
resolution: "inherits@npm:2.0.4" resolution: "inherits@npm:2.0.4"
checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2
@ -2922,15 +2761,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"make-dir@npm:^3.1.0":
version: 3.1.0
resolution: "make-dir@npm:3.1.0"
dependencies:
semver: "npm:^6.0.0"
checksum: 10c0/56aaafefc49c2dfef02c5c95f9b196c4eb6988040cf2c712185c7fe5c99b4091591a7fc4d4eafaaefa70ff763a26f6ab8c3ff60b9e75ea19876f49b18667ecaa
languageName: node
linkType: hard
"make-fetch-happen@npm:^13.0.0": "make-fetch-happen@npm:^13.0.0":
version: 13.0.1 version: 13.0.1
resolution: "make-fetch-happen@npm:13.0.1" resolution: "make-fetch-happen@npm:13.0.1"
@ -2982,22 +2812,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"mimic-response@npm:^2.0.0":
version: 2.1.0
resolution: "mimic-response@npm:2.1.0"
checksum: 10c0/717475c840f20deca87a16cb2f7561f9115f5de225ea2377739e09890c81aec72f43c81fd4984650c4044e66be5a846fa7a517ac7908f01009e1e624e19864d5
languageName: node
linkType: hard
"minimatch@npm:^3.1.1":
version: 3.1.2
resolution: "minimatch@npm:3.1.2"
dependencies:
brace-expansion: "npm:^1.1.7"
checksum: 10c0/0262810a8fc2e72cca45d6fd86bd349eee435eb95ac6aa45c9ea2180e7ee875ef44c32b55b5973ceabe95ea12682f6e3725cbb63d7a2d1da3ae1163c8b210311
languageName: node
linkType: hard
"minimatch@npm:^9.0.4": "minimatch@npm:^9.0.4":
version: 9.0.5 version: 9.0.5
resolution: "minimatch@npm:9.0.5" resolution: "minimatch@npm:9.0.5"
@ -3159,15 +2973,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"nan@npm:^2.17.0":
version: 2.19.0
resolution: "nan@npm:2.19.0"
dependencies:
node-gyp: "npm:latest"
checksum: 10c0/b8d05d75f92ee9d94affa50d0aa41b6c698254c848529452d7ab67c2e0d160a83f563bfe2cbd53e077944eceb48c757f83c93634c7c9ff404c9ec1ed4e5ced1a
languageName: node
linkType: hard
"negotiator@npm:^0.6.3": "negotiator@npm:^0.6.3":
version: 0.6.3 version: 0.6.3
resolution: "negotiator@npm:0.6.3" resolution: "negotiator@npm:0.6.3"
@ -3193,20 +2998,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"node-fetch@npm:^2.6.7":
version: 2.7.0
resolution: "node-fetch@npm:2.7.0"
dependencies:
whatwg-url: "npm:^5.0.0"
peerDependencies:
encoding: ^0.1.0
peerDependenciesMeta:
encoding:
optional: true
checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8
languageName: node
linkType: hard
"node-gyp-build-optional-packages@npm:5.0.7": "node-gyp-build-optional-packages@npm:5.0.7":
version: 5.0.7 version: 5.0.7
resolution: "node-gyp-build-optional-packages@npm:5.0.7" resolution: "node-gyp-build-optional-packages@npm:5.0.7"
@ -3258,17 +3049,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"nopt@npm:^5.0.0":
version: 5.0.0
resolution: "nopt@npm:5.0.0"
dependencies:
abbrev: "npm:1"
bin:
nopt: bin/nopt.js
checksum: 10c0/fc5c4f07155cb455bf5fc3dd149fac421c1a40fd83c6bfe83aa82b52f02c17c5e88301321318adaa27611c8a6811423d51d29deaceab5fa158b585a61a551061
languageName: node
linkType: hard
"nopt@npm:^7.0.0": "nopt@npm:^7.0.0":
version: 7.2.1 version: 7.2.1
resolution: "nopt@npm:7.2.1" resolution: "nopt@npm:7.2.1"
@ -3296,18 +3076,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"npmlog@npm:^5.0.1":
version: 5.0.1
resolution: "npmlog@npm:5.0.1"
dependencies:
are-we-there-yet: "npm:^2.0.0"
console-control-strings: "npm:^1.1.0"
gauge: "npm:^3.0.0"
set-blocking: "npm:^2.0.0"
checksum: 10c0/489ba519031013001135c463406f55491a17fc7da295c18a04937fe3a4d523fd65e88dd418a28b967ab743d913fdeba1e29838ce0ad8c75557057c481f7d49fa
languageName: node
linkType: hard
"nth-check@npm:^2.0.1": "nth-check@npm:^2.0.1":
version: 2.1.1 version: 2.1.1
resolution: "nth-check@npm:2.1.1" resolution: "nth-check@npm:2.1.1"
@ -3324,13 +3092,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"object-assign@npm:^4.1.1":
version: 4.1.1
resolution: "object-assign@npm:4.1.1"
checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414
languageName: node
linkType: hard
"obliterator@npm:^2.0.1": "obliterator@npm:^2.0.1":
version: 2.0.4 version: 2.0.4
resolution: "obliterator@npm:2.0.4" resolution: "obliterator@npm:2.0.4"
@ -3345,7 +3106,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": "once@npm:^1.4.0":
version: 1.4.0 version: 1.4.0
resolution: "once@npm:1.4.0" resolution: "once@npm:1.4.0"
dependencies: dependencies:
@ -3431,13 +3192,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"path-is-absolute@npm:^1.0.0":
version: 1.0.1
resolution: "path-is-absolute@npm:1.0.1"
checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078
languageName: node
linkType: hard
"path-key@npm:^3.1.0": "path-key@npm:^3.1.0":
version: 3.1.1 version: 3.1.1
resolution: "path-key@npm:3.1.1" resolution: "path-key@npm:3.1.1"
@ -3770,17 +3524,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"rimraf@npm:^3.0.2":
version: 3.0.2
resolution: "rimraf@npm:3.0.2"
dependencies:
glob: "npm:^7.1.3"
bin:
rimraf: bin.js
checksum: 10c0/9cb7757acb489bd83757ba1a274ab545eafd75598a9d817e0c3f8b164238dd90eba50d6b848bd4dcc5f3040912e882dc7ba71653e35af660d77b25c381d402e8
languageName: node
linkType: hard
"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0": "safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0":
version: 5.2.1 version: 5.2.1
resolution: "safe-buffer@npm:5.2.1" resolution: "safe-buffer@npm:5.2.1"
@ -3831,15 +3574,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"semver@npm:^6.0.0":
version: 6.3.1
resolution: "semver@npm:6.3.1"
bin:
semver: bin/semver.js
checksum: 10c0/e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d
languageName: node
linkType: hard
"semver@npm:^7.3.5, semver@npm:^7.5.2, semver@npm:^7.5.4": "semver@npm:^7.3.5, semver@npm:^7.5.2, semver@npm:^7.5.4":
version: 7.6.0 version: 7.6.0
resolution: "semver@npm:7.6.0" resolution: "semver@npm:7.6.0"
@ -3851,13 +3585,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"set-blocking@npm:^2.0.0":
version: 2.0.0
resolution: "set-blocking@npm:2.0.0"
checksum: 10c0/9f8c1b2d800800d0b589de1477c753492de5c1548d4ade52f57f1d1f5e04af5481554d75ce5e5c43d4004b80a3eb714398d6907027dc0534177b7539119f4454
languageName: node
linkType: hard
"set-cookie-parser@npm:^2.4.1": "set-cookie-parser@npm:^2.4.1":
version: 2.6.0 version: 2.6.0
resolution: "set-cookie-parser@npm:2.6.0" resolution: "set-cookie-parser@npm:2.6.0"
@ -3881,13 +3608,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"signal-exit@npm:^3.0.0":
version: 3.0.7
resolution: "signal-exit@npm:3.0.7"
checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912
languageName: node
linkType: hard
"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": "signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0":
version: 4.1.0 version: 4.1.0
resolution: "signal-exit@npm:4.1.0" resolution: "signal-exit@npm:4.1.0"
@ -3895,24 +3615,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"simple-concat@npm:^1.0.0":
version: 1.0.1
resolution: "simple-concat@npm:1.0.1"
checksum: 10c0/62f7508e674414008910b5397c1811941d457dfa0db4fd5aa7fa0409eb02c3609608dfcd7508cace75b3a0bf67a2a77990711e32cd213d2c76f4fd12ee86d776
languageName: node
linkType: hard
"simple-get@npm:^3.0.3":
version: 3.1.1
resolution: "simple-get@npm:3.1.1"
dependencies:
decompress-response: "npm:^4.2.0"
once: "npm:^1.3.1"
simple-concat: "npm:^1.0.0"
checksum: 10c0/438c78844ea1b1e7268d13ee0b3a39c7d644183367aec916aed3b676b45d3037a61d9f975c200a49b42eb851f29f03745118af1e13c01e60a7b4044f2fd60be7
languageName: node
linkType: hard
"smart-buffer@npm:^4.2.0": "smart-buffer@npm:^4.2.0":
version: 4.2.0 version: 4.2.0
resolution: "smart-buffer@npm:4.2.0" resolution: "smart-buffer@npm:4.2.0"
@ -3928,7 +3630,6 @@ __metadata:
"@parcel/transformer-sass": "npm:^2.12.0" "@parcel/transformer-sass": "npm:^2.12.0"
"@parcel/transformer-typescript-types": "npm:2.12.0" "@parcel/transformer-typescript-types": "npm:2.12.0"
"@types/node": "npm:^20.12.2" "@types/node": "npm:^20.12.2"
canvas: "npm:^2.11.2"
parcel: "npm:^2.12.0" parcel: "npm:^2.12.0"
pino: "npm:^9.3.1" pino: "npm:^9.3.1"
prettier: "npm:^3.2.5" prettier: "npm:^3.2.5"
@ -4046,7 +3747,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.3": "string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0":
version: 4.2.3 version: 4.2.3
resolution: "string-width@npm:4.2.3" resolution: "string-width@npm:4.2.3"
dependencies: dependencies:
@ -4199,13 +3900,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"tr46@npm:~0.0.3":
version: 0.0.3
resolution: "tr46@npm:0.0.3"
checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11
languageName: node
linkType: hard
"tslib@npm:^2.4.0": "tslib@npm:^2.4.0":
version: 2.6.2 version: 2.6.2
resolution: "tslib@npm:2.6.2" resolution: "tslib@npm:2.6.2"
@ -4309,23 +4003,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"webidl-conversions@npm:^3.0.0":
version: 3.0.1
resolution: "webidl-conversions@npm:3.0.1"
checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db
languageName: node
linkType: hard
"whatwg-url@npm:^5.0.0":
version: 5.0.0
resolution: "whatwg-url@npm:5.0.0"
dependencies:
tr46: "npm:~0.0.3"
webidl-conversions: "npm:^3.0.0"
checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5
languageName: node
linkType: hard
"which@npm:^2.0.1": "which@npm:^2.0.1":
version: 2.0.2 version: 2.0.2
resolution: "which@npm:2.0.2" resolution: "which@npm:2.0.2"
@ -4348,15 +4025,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"wide-align@npm:^1.1.2":
version: 1.1.5
resolution: "wide-align@npm:1.1.5"
dependencies:
string-width: "npm:^1.0.2 || 2 || 3 || 4"
checksum: 10c0/1d9c2a3e36dfb09832f38e2e699c367ef190f96b82c71f809bc0822c306f5379df87bab47bed27ea99106d86447e50eb972d3c516c2f95782807a9d082fbea95
languageName: node
linkType: hard
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version: 7.0.0 version: 7.0.0
resolution: "wrap-ansi@npm:7.0.0" resolution: "wrap-ansi@npm:7.0.0"