Merge pull request #49 from Maix0/nigel/socketio

This commit is contained in:
Nigel 2025-12-04 19:18:22 +01:00 committed by GitHub
commit bfa0bce812
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 955 additions and 429 deletions

View file

@ -122,7 +122,7 @@ services:
- JWT_SECRET=KRUGKIDROVUWG2ZAMJZG653OEBTG66BANJ2W24DTEBXXMZLSEB2GQZJANRQXU6JA
- DATABASE_DIR=/volumes/database
- PROVIDER_FILE=/extra/providers.toml
- SESSION_MANAGER=${SESSION_MANAGER}
###############
# USER #

View file

@ -11,7 +11,7 @@
"devDependencies": {
"@types/js-cookie": "^3.0.6",
"typescript": "~5.9.3",
"vite": "^7.2.4",
"vite": "^7.2.6",
"vite-tsconfig-paths": "^5.1.4"
},
"dependencies": {

View file

@ -10,7 +10,7 @@ importers:
dependencies:
'@tailwindcss/vite':
specifier: ^4.1.17
version: 4.1.17(vite@7.2.4(jiti@2.6.1)(lightningcss@1.30.2))
version: 4.1.17(vite@7.2.6(jiti@2.6.1)(lightningcss@1.30.2))
js-cookie:
specifier: ^3.0.5
version: 3.0.5
@ -31,11 +31,11 @@ importers:
specifier: ~5.9.3
version: 5.9.3
vite:
specifier: ^7.2.4
version: 7.2.4(jiti@2.6.1)(lightningcss@1.30.2)
specifier: ^7.2.6
version: 7.2.6(jiti@2.6.1)(lightningcss@1.30.2)
vite-tsconfig-paths:
specifier: ^5.1.4
version: 5.1.4(typescript@5.9.3)(vite@7.2.4(jiti@2.6.1)(lightningcss@1.30.2))
version: 5.1.4(typescript@5.9.3)(vite@7.2.6(jiti@2.6.1)(lightningcss@1.30.2))
packages:
@ -635,8 +635,8 @@ packages:
vite:
optional: true
vite@7.2.4:
resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==}
vite@7.2.6:
resolution: {integrity: sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
@ -919,12 +919,12 @@ snapshots:
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.17
'@tailwindcss/oxide-win32-x64-msvc': 4.1.17
'@tailwindcss/vite@4.1.17(vite@7.2.4(jiti@2.6.1)(lightningcss@1.30.2))':
'@tailwindcss/vite@4.1.17(vite@7.2.6(jiti@2.6.1)(lightningcss@1.30.2))':
dependencies:
'@tailwindcss/node': 4.1.17
'@tailwindcss/oxide': 4.1.17
tailwindcss: 4.1.17
vite: 7.2.4(jiti@2.6.1)(lightningcss@1.30.2)
vite: 7.2.6(jiti@2.6.1)(lightningcss@1.30.2)
'@types/estree@1.0.8': {}
@ -1139,18 +1139,18 @@ snapshots:
typescript@5.9.3: {}
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.4(jiti@2.6.1)(lightningcss@1.30.2)):
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.6(jiti@2.6.1)(lightningcss@1.30.2)):
dependencies:
debug: 4.4.3
globrex: 0.1.2
tsconfck: 3.1.6(typescript@5.9.3)
optionalDependencies:
vite: 7.2.4(jiti@2.6.1)(lightningcss@1.30.2)
vite: 7.2.6(jiti@2.6.1)(lightningcss@1.30.2)
transitivePeerDependencies:
- supports-color
- typescript
vite@7.2.4(jiti@2.6.1)(lightningcss@1.30.2):
vite@7.2.6(jiti@2.6.1)(lightningcss@1.30.2):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)

View file

@ -9,4 +9,6 @@ declare global {
dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K]): void;
}
}
export { }; //keep that for TS compiler.

View file

@ -2,7 +2,6 @@ apis/OpenapiOtherApi.ts
apis/index.ts
index.ts
models/ChatTest200Response.ts
models/ChatTest500Response.ts
models/DisableOtp200Response.ts
models/DisableOtp401Response.ts
models/DisableOtp500Response.ts

View file

@ -16,7 +16,6 @@
import * as runtime from '../runtime';
import type {
ChatTest200Response,
ChatTest500Response,
DisableOtp200Response,
DisableOtp401Response,
DisableOtp500Response,
@ -50,8 +49,6 @@ import type {
import {
ChatTest200ResponseFromJSON,
ChatTest200ResponseToJSON,
ChatTest500ResponseFromJSON,
ChatTest500ResponseToJSON,
DisableOtp200ResponseFromJSON,
DisableOtp200ResponseToJSON,
DisableOtp401ResponseFromJSON,
@ -135,7 +132,7 @@ export class OpenapiOtherApi extends runtime.BaseAPI {
/**
*/
async chatTestRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ChatTest200Response | StatusOtp401Response | ChatTest500Response>> {
async chatTestRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ChatTest200Response | StatusOtp401Response>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
@ -162,19 +159,15 @@ export class OpenapiOtherApi extends runtime.BaseAPI {
// Object response for status 401
return new runtime.JSONApiResponse(response, (jsonValue) => StatusOtp401ResponseFromJSON(jsonValue));
}
if (response.status === 500) {
// Object response for status 500
return new runtime.JSONApiResponse(response, (jsonValue) => ChatTest500ResponseFromJSON(jsonValue));
}
// CHANGED: Throw error if status code is not handled by any of the defined responses
// This ensures all code paths return a value and provides clear error messages for unexpected status codes
// Only throw if responses were defined but none matched the actual status code
throw new runtime.ResponseError(response, `Unexpected status code: ${response.status}. Expected one of: 200, 401, 500`);
throw new runtime.ResponseError(response, `Unexpected status code: ${response.status}. Expected one of: 200, 401`);
}
/**
*/
async chatTest(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<ChatTest200Response | StatusOtp401Response | ChatTest500Response> {
async chatTest(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<ChatTest200Response | StatusOtp401Response> {
const response = await this.chatTestRaw(initOverrides);
return await response.value();
}

View file

@ -1,7 +1,6 @@
/* tslint:disable */
/* eslint-disable */
export * from './ChatTest200Response';
export * from './ChatTest500Response';
export * from './DisableOtp200Response';
export * from './DisableOtp401Response';
export * from './DisableOtp500Response';

View file

@ -1,39 +1,56 @@
@import "tailwindcss";
@font-face {
font-family: "Nimbus Mono L";
src: url("/fonts/NimbusMonoL.woff2") format("woff2");
}
.btn-style {
@apply
w-[100px]
h-[32px]
border-2 border-black
w-[100px]
h-[32px]
border-1
border-gray-500
rounded-3xl
bg-gray-500
text-white
cursor-pointer
shadow-[0_2px_0_0_black]
transition-all
hover:bg-blue-200
active:bg-white
text-black
cursor-pointer;
active:bg-gray-400
active:translate-y-[1px]
active:shadow-[0_2px_0_0_black];
}
.send-btn-style {
@apply
w-[50px]
h-[50px]
border-2 border-black
border-1
border-gray-500
rounded-3xl
hover:bg-blue-200
active:bg-white
text-black
cursor-pointer;
bg-red-100
text-red-700
cursor-pointer
shadow-[0_2px_0_0_black]
transition-all
active:bg-gray-400
active:translate-y-[1px]
active:shadow-[0_2px_0_0_black];;
}
.chatbox-style {
@apply
w-[600px]
h-[150px] /* increase height if needed */
p-[10px]
border-1 border-black
shadow-sm
w-[650px]
h-[300px] /* increase height if needed */
p-[8px]
border-1
border-black
shadow-2xl
text-left
text-gray-800
text-gray-700
bg-white
rounded-3xl
overflow-y-auto
whitespace-pre-line
@ -42,16 +59,43 @@
mx-auto;
}
.system-info {
@apply
h-[40px]
bg-gray-200
text-gray-700
p-3
rounded-3xl
mb-2 border
border-gray-200
text-center
shadow
overflow-y-auto
justify-end /* 👈 forces text to bottom */
relative; /* needed for overlay */
}
.text-info {
@apply
text-blue-800
}
.chat-window-style {
@apply
w-[400px]
h-[50px]
p-[10px]
border-1 border-black
border-1
border-black
shadow-sm
flex-1
rounded-3xl
focus:bg-gray-300
hover:bg-blue-200
focus:bg-blue-300
hover:bg-blue-200
bg-white
text-gray-800;
}
@ -62,7 +106,8 @@
flex
items-center
justify-center
bg-gray-100;
bg-[#43536b];
}
.mainboxDisplay {
@ -72,7 +117,7 @@
left-1/2
-translate-x-1/2
-translate-y-1/2
bg-white w-[650px]
bg-gray-200 w-[850px]
p-6 rounded-xl
shadow-2xl
text-center z-50;
@ -80,20 +125,59 @@
.mainboxDisplay button {
@apply
cursor-pointer;
cursor-pointer
}
.title {
@apply
text-6xl
font-bold
text-gray-800
}
.ping-box {
@apply
w-[150px]
ml-2 border-1
border-gray-500
bg-white
rounded-2xl
p-2
shadow-md
flex flex-col
gap-1
h-[350px];
}
.ping-title {
@apply
text-sm
font-semibold
text-blue-800;
}
div-buddies-list {
@apply
text-black
whitespace-pre-wrap;
}
p {
@apply
text-black
}
.div-test {
div-test {
@apply
italic
text-red-800
text-right;
}
div-notlog {
@apply
text-red-800
text-3xl
text-center;
}

View file

@ -1,19 +1,42 @@
<div class="displaybox">
<div id="mainbox" class="mainboxDisplay">
<button id="b-whoami" class="btn-style absolute top-6 left-6">Who am i</button>
<h1 class="text-3xl font-bold text-gray-800">
Chat Box <span id="t-username"></span>
</h1><br>
<button id="b-clear" class="btn-style absolute top-6 right-6">Clear Text</button>
<button id="b-help" class="btn-style absolute top-18 left-6">Connected</button>
<p>Welcome <span id="username"></span></p></br>
<div id="t-chatbox" class="chatbox-style"></div>
</br>
<div class="flex gap-2">
<input id="t-chat-window" placeholder="Type your message..." class="chat-window-style flex-1" />
<button id="b-send" class="send-btn-style">Send</button>
</div>
</br>
<p class="text-gray-400">From this Chat Box you can send messages to other players</p>
</div>
</div>
<div id="mainbox" class="mainboxDisplay">
<button id="b-whoami" class="btn-style absolute top-4 left-6">Who am i</button>
<h1 class="text-3xl font-bold text-gray-800">
ChatterBox<span id="t-username"></span>
</h1><br>
<button id="b-clear" class="btn-style absolute top-4 right-6">Clear Text</button>
<button id="b-quit" class="btn-style absolute top-14 right-6">Quit Chat</button>
<button id="b-help" class="btn-style absolute top-14 left-6">Connected</button>
<!-- Horizontal Message Box -->
<div id="system-box" class="system-info">System: connecting ... </div>
<div class="flex justify-center mt-2">
<!-- Center wrapper for chat + vertical box -->
<!-- Groupe Chat + vertical box container -->
<div id = "g-boxes" class="flex gap-2">
<!-- Text Chat box panel + send -->
<div id="g-textBoxes" class="flex flex-col">
<div id="t-chatbox" class="chatbox-style"></div>
<div id="t-input-send" class="flex gap-1 mt-2">
<input id="t-chat-window" placeholder="Type your message..." class="chat-window-style" />
<button id="b-send" class="send-btn-style">Send</button>
</div>
</div>
<!-- Vertical Ping Buddies box panel-->
<div id="ping-box" class="ping-box">
<p id="ping-title" class="ping-title">Ping Buddies</p>
<div id="ping-list" class="flex-1 overflow-y-auto">
<div id = "div-buddies">
<!-- <p>Alice</p>
<p>Bob</p>
<p>Charlie</p> -->
</div>
</div>
</div>
</div>
</div>
<p class="text-gray-400 mt-2">From this Chat Box you can send messages to other players</p>
</div>
</div>

View file

@ -4,6 +4,27 @@ import authHtml from './chat.html?raw';
import client from '@app/api'
import { getUser, updateUser } from "@app/auth";
import io, { Socket } from 'socket.io-client';
// import type { ClientMessage } from "@app/@types/dom";
const color = {
red: 'color: red;',
green: 'color: green;',
yellow: 'color: orange;',
blue: 'color: blue;',
reset: '',
};
export type ClientMessage = {
destination: string;
user: string;
text: string;
SenderWindowID: string;
};
// get the name of the machine used to connect
const machineHostName = window.location.hostname;
console.log('connect to login at %chttps://' + machineHostName + ':8888/app/login',color.yellow);
let __socket: Socket | undefined = undefined;
document.addEventListener('ft:pageChange', () => {
@ -12,9 +33,13 @@ document.addEventListener('ft:pageChange', () => {
__socket = undefined;
console.log("Page changed");
})
function getSocket(): Socket {
// let addressHost = `wss://${machineHostName}:8888`;
let addressHost = `wss://localhost:8888`;
if (__socket === undefined)
__socket = io("wss://localhost:8888", {
__socket = io(addressHost, {
path: "/api/chat/socket.io/",
secure: false,
transports: ["websocket"],
@ -23,12 +48,90 @@ function getSocket(): Socket {
}
async function isLoggedIn() {
return getUser() || null;
}
async function windowStateHidden() {
const socketId = __socket || undefined;
// let oldName = localStorage.getItem("oldName") ?? undefined;
let oldName: string;
if (socketId === undefined) return;
let userName = await updateUser();
oldName = userName?.name ?? "";
if (oldName === "") return;
localStorage.setItem('oldName', oldName);
socketId.emit('client_left', {
user: userName?.name,
why: 'tab window hidden - socket not dead',
});
return;
}
async function windowStateVisable() {
const socketId = __socket || undefined;
let oldName = localStorage.getItem("oldName") || undefined;
console.log("%c WINDOW VISIBLE - oldName :'" + oldName + "'", color.green);
if (socketId === undefined || oldName === undefined) {console.log("%SOCKET ID", color.red); return;}
// const res = await client.guestLogin();
let user = await updateUser();
if(user === null) return;
console.log("%cUserName :'" + user?.name + "'", color.green);
socketId.emit('client_entered', {
userName: oldName,
user: user?.name,
});
setTitle('Chat Page');
return;
}
async function listBuddies(buddies: HTMLDivElement, listBuddies: string ) {
if (!buddies) return;
const messageElement = document.createElement("div-buddies-list");
messageElement.textContent = listBuddies + '\n';
buddies.appendChild(messageElement);
buddies.scrollTop = buddies.scrollHeight;
console.log(`Added buddies: ${listBuddies}`)
return ;
}
function waitSocketConnected(socket: Socket): Promise<void> {
return new Promise(resolve => {
if (socket.connected) return resolve(); // already connected
socket.on("connect", () => resolve());
});
}
const bconnected = document.getElementById('b-help') as HTMLButtonElement;
if (bconnected) {
bconnected.click();
}
function logout(socket: Socket) {
socket.emit("logout"); // notify server
socket.disconnect(); // actually close the socket
localStorage.clear();
if (__socket !== undefined)
__socket.close();
// window.location.href = "/login";
}
function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn {
let socket = getSocket();
// Listen for the 'connect' event
socket.on("connect", () => {
socket.on("connect", async () => {
await waitSocketConnected(socket);
console.log("I AM Connected to the server:", socket.id);
const user = getUser()?.name;
// Ensure we have a user AND socket is connected
@ -43,31 +146,54 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
};
socket.emit('message', JSON.stringify(message));
});
// Listen for messages from the server "MsgObjectServer"
socket.on("MsgObjectServer", (data: any) => {
console.log("Message Obj Recieved:", data.message);
console.log("Recieved data.message.text: ", data.message.text);
console.log("Recieved data.message.user: ", data.message.user);
console.log("Recieved data.message.type: ", data.message.type);
console.log("Recieved data.message.token: ", data.message.token);
console.log("Recieved data.message.timestamp: ", data.message.timestamp);
socket.on("MsgObjectServer", (data: { message: ClientMessage}) => {
console.log("Message Obj Recieved:", data);
console.log("%cRecieved data.message.text: ", color.blue, data.message.text);
console.log("%cRecieved data.message.user: ", color.blue, data.message.user);
// Display the message in the chat window
const systemWindow = document.getElementById('system-box') as HTMLDivElement;
const chatWindow = document.getElementById("t-chatbox") as HTMLDivElement;
if (chatWindow) {
const bconnected = document.getElementById('b-help') as HTMLButtonElement;
if (bconnected) {
bconnected.click();
}
if (chatWindow && data.message.destination === "") {
const messageElement = document.createElement("div");
// if (getUser()?.id !== `${data.message.id}`) {
console.log('==================> HERE');
messageElement.textContent = `${data.message.user}: ${data.message.text}`;
// } else {
// console.log('==================>AND HERE');
// messageElement.textContent = `here`;
// }
chatWindow.appendChild(messageElement);
chatWindow.scrollTop = chatWindow.scrollHeight;
}
const MAX_SYSTEM_MESSAGES = 10;
if (systemWindow && data.message.destination === "system-info") {
const messageElement = document.createElement("div");
messageElement.textContent = `${data.message.user}: ${data.message.text}`;
systemWindow.appendChild(messageElement);
// keep only last 10
while (systemWindow.children.length > MAX_SYSTEM_MESSAGES) {
systemWindow.removeChild(systemWindow.firstChild!);
}
systemWindow.scrollTop = systemWindow.scrollHeight;
}
console.log("Getuser():", getUser());
});
socket.on('logout', () => {
const bquit = document.getElementById('b-quit') as HTMLDivElement | null;
if (bquit instanceof HTMLDivElement) {
bquit.click();
}
});
type Providers = {
name: string,
display_name: string,
@ -75,7 +201,25 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
color?: { default: string, hover: string },
};
// function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn {
let toggle = false
window.addEventListener("focus", () => {
const bwhoami = document.getElementById('b-whoami') as HTMLButtonElement;
if (window.location.pathname === '/app/chat') {
console.log("%cWindow is focused on /chat:" + socket.id, color.green);
if (socket.id)
windowStateVisable();
bwhoami.click();
toggle = true;
}
});
window.addEventListener("blur", () => {
console.log("%cWindow is not focused on /chat", color.red);
if (socket.id)
windowStateHidden();
toggle = false;
});
setTitle('Chat Page');
// Listen for the 'connect' event
@ -89,34 +233,53 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
const bwhoami = document.getElementById('b-whoami') as HTMLButtonElement;
const bconnected = document.getElementById('b-help') as HTMLButtonElement;
const username = document.getElementById('username') as HTMLDivElement;
const buddies = document.getElementById('div-buddies') as HTMLDivElement;
const bquit = document.getElementById('b-quit') as HTMLDivElement;
chatWindow.textContent = '';
chatWindow.innerHTML = '';
buddies.textContent = '';
buddies.innerHTML = '';
const value = await client.chatTest();
if (value.kind === "success") {
console.log(value.payload);
} else if (value.kind === "notLoggedIn") {
console.log('not logged in');
} else {
console.log('unknown response: ', value);
}
if (value.kind === "success") {
console.log(value.payload);
} else if (value.kind === "notLoggedIn") {
console.log('not logged in');
} else {
console.log('unknown response: ', value);
}
const addMessage = (text: string) => {
if (!chatWindow) return;
const messageElement = document.createElement("div");
const messageElement = document.createElement("div-test");
messageElement.textContent = text;
chatWindow.appendChild(messageElement);
chatWindow.scrollTop = chatWindow.scrollHeight;
console.log(`Added new message: ${text}`)
return ;
};
socket.once('welcome', (data) => {
chatWindow.textContent = '';
chatWindow.innerHTML = '';
buddies.textContent = '';
buddies.innerHTML = '';
bconnected.click();
addMessage (`${data.msg} ` + getUser()?.name);
});
// Send button
sendButton?.addEventListener("click", () => {
if (sendtextbox && sendtextbox.value.trim()) {
const msgText = sendtextbox.value.trim();
bconnected.click();
addMessage(msgText);
const user = getUser();
if (user && socket?.connected) {
const message = {
destination: "",
type: "chat",
user: user.name,
token: document.cookie,
@ -124,31 +287,66 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
timestamp: Date.now(),
SenderWindowID: socket.id,
};
socket.send(JSON.stringify(message));
socket.emit('message', JSON.stringify(message));
}
sendtextbox.value = "";
}
});
// Clear Text button
clearText?.addEventListener("click", () => {
if (chatWindow) {
bconnected.click();
chatWindow.innerHTML = '';
}
});
bquit?.addEventListener('click', () => {
if (socket) {
logout(socket);
setTitle('Chat Page');
bconnected.click();
} else {
getSocket();
}
});
setInterval(async () => {
//bconnected.click();
}, 10000); // every 10 second
// Help Text button
bconnected?.addEventListener("click", async () => {
if (chatWindow) {
addMessage('@list - lists all connected users in the chat');
await socket.emit('list');
}
const loggedIn = await isLoggedIn();
console.log('%cloggedIn:',color.blue, loggedIn?.name);
let oldUser = localStorage.getItem("oldName") ?? "";
console.log('%coldUser:',color.yellow, oldUser);
if (loggedIn?.name === undefined) {console.log('');return ;}
oldUser = loggedIn.name || "undefined";
const res = await client.guestLogin();
let user = await updateUser();
console.log('%cUser?name:',color.yellow, user?.name);
localStorage.setItem("oldName", oldUser);
buddies.textContent = "";
// if (chatWindow) {
// addMessage('@list - lists all connected users in the chat');
socket.emit('list', {
oldUser: oldUser,
user: user?.name,
});
// }
});
socket.on('listObj', (list: string) => {
console.log('List chat clients connected ', list);
addMessage(list);
socket.on('listBud', (myBuddies: string) => {
console.log('List buddies connected ', myBuddies);
listBuddies(buddies,myBuddies);
});
@ -162,10 +360,18 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
// Whoami button to display user name
bwhoami?.addEventListener('click', async () => {
try {
const loggedIn = await isLoggedIn();
const res = await client.guestLogin();
switch (res.kind) {
case 'success': {
let user = await updateUser();
if (chatWindow) {
socket.emit('updateClientName', {
oldUser: '',
user: user?.name
});
}
if (user === null)
return showError('Failed to get user: no user ?');
setTitle(`Welcome ${user.guest ? '[GUEST] ' : ''}${user.name}`);
@ -184,3 +390,4 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
}
};
addRoute('/chat', handleChat, { bypass_auth: true });

View file

@ -20,8 +20,8 @@
"fastify-plugin": "^5.1.0",
"joi": "^18.0.2",
"otp": "^1.1.2",
"typebox": "^1.0.55",
"uuidv7": "^1.0.2"
"typebox": "^1.0.61",
"uuidv7": "^1.1.0"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.13",

View file

@ -4,11 +4,13 @@ import { FastifyInstance, FastifyPluginAsync } from 'fastify';
import { isNullish } from '@shared/utils';
import { Database as DbImpl } from './mixin/_base';
import { IUserDb, UserImpl } from './mixin/user';
import { IBlockedDb, BlockedImpl } from './mixin/blocked';
Object.assign(DbImpl.prototype, UserImpl);
Object.assign(DbImpl.prototype, BlockedImpl);
export interface Database extends DbImpl, IUserDb { }
export interface Database extends DbImpl, IUserDb, IBlockedDb { }
// When using .decorate you have to specify added properties for Typescript
declare module 'fastify' {

View file

@ -7,3 +7,17 @@ CREATE TABLE IF NOT EXISTS user (
guest INTEGER NOT NULL DEFAULT 0,
oauth2 TEXT DEFAULT NULL
);
CREATE TABLE IF NOT EXISTS blocked (
id INTEGER PRIMARY KEY NOT NULL,
user TEXT NOT NULL,
blocked TEXT NOT NULL,
FOREIGN KEY(user) REFERENCES user(id)
FOREIGN KEY(blocked) REFERENCES user(id)
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_blocked_user_pair
ON blocked(user, blocked);

View file

@ -0,0 +1,72 @@
import { isNullish } from '@shared/utils';
import type { Database } from './_base';
import { UserId } from './user';
// describe every function in the object
export interface IBlockedDb extends Database {
getBlockedUserFor(id: UserId): BlockedData[],
addBlockedUserFor(id: UserId, blocked: UserId): void,
removeBlockedUserFor(id: UserId, blocked: UserId): void,
unblockAllUserFor(id: UserId): void,
getAllBlockedUsers(this: IBlockedDb): BlockedData[] | undefined,
};
export const BlockedImpl: Omit<IBlockedDb, keyof Database> = {
getBlockedUserFor(this: IBlockedDb, id: UserId): BlockedData[] {
const query = this.prepare('SELECT * FROM blocked WHERE user = @id');
const data = query.all({ id }) as Partial<BlockedData>[];
return data.map(blockedFromRow).filter(b => !isNullish(b));
},
unblockAllUserFor(this: IBlockedDb, id: UserId): void {
this.prepare('DELETE FROM blocked WHERE user = @id').run({ id });
},
addBlockedUserFor(this: IBlockedDb, id: UserId, blocked: UserId): void {
this.prepare('INSERT OR IGNORE INTO blocked (user, blocked) VALUES (@id, @blocked)').run({ id, blocked });
},
removeBlockedUserFor(this: IBlockedDb, id: UserId, blocked: UserId): void {
this.prepare('DELETE FROM blocked WHERE user = @id AND blocked = @blocked').run({ id, blocked });
},
/**
* Get all blocked user
*
* @param
*
* @returns The list of users if it exists, undefined otherwise
*/
getAllBlockedUsers(this: IBlockedDb): BlockedData[] {
const rows = this.prepare('SELECT * FROM blocked').all() as Partial<BlockedData>[];
return rows
.map(row => blockedFromRow(row))
.filter((u): u is BlockedData => u !== undefined);
},
};
export type BlockedId = number & { readonly __brand: unique symbol };
export type BlockedData = {
readonly id: BlockedId;
readonly user: UserId;
readonly blocked: UserId;
};
/**
* Get a blocked from a row
*
* @param row The data from sqlite
*
* @returns The blocked if it exists, undefined otherwise
*/
export function blockedFromRow(row?: Partial<BlockedData>): BlockedData | undefined {
if (isNullish(row)) return undefined;
if (isNullish(row.id)) return undefined;
if (isNullish(row.user)) return undefined;
if (isNullish(row.blocked)) return undefined;
return row as BlockedData;
}

View file

@ -18,6 +18,8 @@ export interface IUserDb extends Database {
ensureUserOtpSecret(id: UserId): string | undefined,
deleteUserOtpSecret(id: UserId): void,
getAllUserFromProvider(provider: string): User[] | undefined,
getAllUsers(this: IUserDb): User[] | undefined,
};
export const UserImpl: Omit<IUserDb, keyof Database> = {
@ -36,6 +38,15 @@ export const UserImpl: Omit<IUserDb, keyof Database> = {
);
},
getAllUsers(this: IUserDb): User[] {
const rows = this.prepare('SELECT * FROM user').all() as Partial<User>[];
return rows
.map(row => userFromRow(row))
.filter((u): u is User => u !== undefined);
},
/**
* Get a user from a raw [UserId]
*

View file

@ -21,18 +21,18 @@
"@fastify/autoload": "^6.3.1",
"@fastify/formbody": "^8.0.2",
"@fastify/multipart": "^9.3.0",
"@fastify/sensible": "^6.0.3",
"@fastify/sensible": "^6.0.4",
"@fastify/static": "^8.3.0",
"confbox": "^0.2.2",
"fastify": "^5.6.2",
"fastify-cli": "^7.4.1",
"fastify-plugin": "^5.1.0",
"typebox": "^1.0.55"
"typebox": "^1.0.61"
},
"devDependencies": {
"@types/node": "^22.19.1",
"rollup-plugin-node-externals": "^8.1.2",
"vite": "^7.2.4",
"vite": "^7.2.6",
"vite-tsconfig-paths": "^5.1.4"
}
}

View file

@ -112,32 +112,6 @@
}
}
}
},
"500": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failed"
]
},
"msg": {
"enum": [
"chat.failed.generic"
]
}
}
}
}
}
}
}
}

View file

@ -21,18 +21,18 @@
"@fastify/autoload": "^6.3.1",
"@fastify/formbody": "^8.0.2",
"@fastify/multipart": "^9.3.0",
"@fastify/sensible": "^6.0.3",
"@fastify/sensible": "^6.0.4",
"@fastify/static": "^8.3.0",
"@fastify/websocket": "^11.2.0",
"@sinclair/typebox": "^0.34.41",
"fastify": "^5.6.2",
"fastify-plugin": "^5.1.0",
"socket.io": "^4.8.1"
"socket.io": "^4.8.1",
"typebox": "^1.0.61"
},
"devDependencies": {
"@types/node": "^22.19.1",
"rollup-plugin-node-externals": "^8.1.2",
"vite": "^7.2.4",
"vite": "^7.2.6",
"vite-tsconfig-paths": "^5.1.4"
}
}

View file

@ -7,11 +7,40 @@ import * as swagger from '@shared/swagger';
import * as utils from '@shared/utils';
import { Server, Socket } from 'socket.io';
// colors for console.log
export const color = {
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
reset: '\x1b[0m',
};
// shows address for connection au server transcendance
const session = process.env.SESSION_MANAGER ?? '';
if (session) {
const part = session.split('/')[1];
const machineName = part.split('.')[0];
console.log(color.yellow, 'Connect at : https://' + machineName + ':8888/app/login');
}
declare const __SERVICE_NAME: string;
// Global map of clients
// key = socket, value = clientname
const clientChat = new Map<string, string>();
interface ClientInfo {
user: string;
lastSeen: number;
}
export type ClientMessage = {
destination: string;
user: string;
text: string;
SenderWindowID: string;
};
const clientChat = new Map<string, ClientInfo>();
// @ts-expect-error: import.meta.glob is a vite thing. Typescript doesn't know this...
const plugins = import.meta.glob('./plugins/**/*.ts', { eager: true });
@ -47,20 +76,6 @@ const app: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
export default app;
export { app };
export const color = {
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
reset: '\x1b[0m',
};
type ClientMessage = {
user: string;
text: string;
SenderWindowID: string;
};
// When using .decorate you have to specify added properties for Typescript
declare module 'fastify' {
interface FastifyInstance {
@ -68,7 +83,12 @@ declare module 'fastify' {
hello: (message: string) => string;
MsgObjectServer: (data: { message: ClientMessage }) => void;
message: (msg: string) => void;
listBud: (msg: string) => void;
testend: (sock_id_client: string) => void;
client_entered: (userName: string, user: string) => void;
client_left: (userName: string, why: string) => void;
list: (oldUser: string, user: string) => void;
updateClientName: (oldUser: string, user: string) => void;
}>;
}
}
@ -85,7 +105,7 @@ async function onReady(fastify: FastifyInstance) {
clientChat.delete(socketId);
continue;
}
if (typeof username !== 'string' || username.length === 0) {
if (typeof username.user !== 'string' || username.user.length === 0) {
clientChat.delete(socketId);
continue;
}
@ -102,18 +122,17 @@ async function onReady(fastify: FastifyInstance) {
}
// Skip duplicates (DO NOT delete them — just don't count)
if (seen.has(username)) {
if (seen.has(username.user)) {
continue;
}
// socket exists and is connected
seen.add(username);
seen.add(username.user);
count++;
// console.log(color.green,"count: ", count);
console.log(color.yellow, 'Client:', color.reset, username);
console.log(color.yellow, 'Client:', color.reset, username.user);
const targetSocketId = target;
io.to(targetSocketId!).emit('listObj', username);
io.to(targetSocketId!).emit('listBud', username.user);
console.log(
color.yellow,
'Chat Socket ID:',
@ -138,28 +157,33 @@ async function onReady(fastify: FastifyInstance) {
socketId,
);
}
return count;
}
function broadcast(data: ClientMessage, sender?: string) {
fastify.io.fetchSockets().then((sockets) => {
for (const s of sockets) {
if (s.id !== sender) {
// Send REAL JSON object
const clientName = clientChat.get(s.id) || null;
if (clientName !== null) {
s.emit('MsgObjectServer', { message: data });
}
console.log(' Target window socket ID:', s.id);
console.log(' Target window ID:', [...s.rooms]);
console.log(' Sender window ID:', sender ? sender : 'none');
// Skip sender's own socket
if (s.id === sender) continue;
// Get client name from map
const clientInfo = clientChat.get(s.id);
if (!clientInfo?.user) {
console.log(color.yellow, `Skipping socket ${s.id} (no user found)`);
continue;
}
// Emit structured JSON object
s.emit('MsgObjectServer', { message: data });
// Debug logs
console.log(color.green, 'Broadcast to:', clientInfo.user);
console.log(' Target socket ID:', s.id);
console.log(' Target rooms:', [...s.rooms]);
console.log(' Sender socket ID:', sender ?? 'none');
}
});
}
fastify.io.on('connection', (socket: Socket) => {
socket.on('message', (message: string) => {
console.info(
color.blue,
@ -175,13 +199,17 @@ async function onReady(fastify: FastifyInstance) {
);
const obj: ClientMessage = JSON.parse(message) as ClientMessage;
clientChat.set(socket.id, obj.user);
clientChat.set(socket.id, { user: obj.user, lastSeen: Date.now() });
console.log(
color.green,
'Message from client',
color.reset,
`Sender: login name: "${obj.user}" - windowID "${obj.SenderWindowID}" - text message: "${obj.text}"`,
`Sender: login name: ${obj.user} - windowID ${obj.SenderWindowID} - text message: ${obj.text}`,
);
socket.emit('welcome', {
msg: 'Welcome to the chat! : ',
});
// Send object directly — DO NOT wrap it in a string
broadcast(obj, obj.SenderWindowID);
console.log(
@ -196,13 +224,68 @@ async function onReady(fastify: FastifyInstance) {
console.log('testend received from client socket id:', sock_id_cl);
});
socket.on('list', () => {
console.log(color.red, 'list activated', color.reset, socket.id);
socket.on('list', (object) => {
const userFromFrontend = object || null;
const client = clientChat.get(socket.id) || null;
console.log(color.red, 'list activated', userFromFrontend, color.reset, socket.id);
if (userFromFrontend.oldUser !== userFromFrontend.user) {
console.log(color.red, 'list activated', userFromFrontend.oldUser, color.reset);
// if (client?.user === null) {
// console.log('ERROR: clientName is NULL');
// return;
// };
if (client) {
client.user = userFromFrontend.user;
}
}
connectedUser(fastify.io, socket.id);
});
socket.on('updateClientName', (object) => {
const userFromFrontend = object || null;
const client = clientChat.get(socket.id) || null;
console.log(color.red, 'whoAMi activated', userFromFrontend, color.reset, socket.id);
if (userFromFrontend.oldUser !== userFromFrontend.user) {
console.log(color.red, 'whoAMi activated', userFromFrontend.oldUser, color.reset);
// if (client === null) {
// console.log('ERROR: clientName is NULL');
// return;
// };
if (client) {
client.user = userFromFrontend.user;
console.log(color.green, 'client.user is: ', client.user);
}
}
});
socket.on('logout', () => {
const clientInfo = clientChat.get(socket.id);
const clientName = clientInfo?.user;
if (!clientName) return;
console.log(color.green, `Client logging out: ${clientName} (${socket.id})`);
const obj = {
destination: 'system-info',
type: 'chat' as const,
user: clientName,
token: '',
text: 'LEFT the chat',
timestamp: Date.now(),
SenderWindowID: socket.id,
};
broadcast(obj, socket.id);
// Optional: remove from map
clientChat.delete(socket.id);
// Ensure socket is fully disconnected
if (socket.connected) socket.disconnect(true);
});
socket.on('disconnecting', (reason) => {
const clientName = clientChat.get(socket.id) || null;
const clientName = clientChat.get(socket.id)?.user || null;
console.log(
color.green,
`Client disconnecting: ${clientName} (${socket.id}) reason:`,
@ -212,6 +295,7 @@ async function onReady(fastify: FastifyInstance) {
if (clientName !== null) {
const obj = {
destination: 'system-info',
type: 'chat',
user: clientName,
token: '',
@ -221,8 +305,78 @@ async function onReady(fastify: FastifyInstance) {
};
broadcast(obj, obj.SenderWindowID);
}
});
socket.on('client_left', (data) => {
const clientName = clientChat.get(socket.id)?.user || null;
const leftChat = data || null;
console.log(
color.green,
`Left the Chat User: ${clientName} id Socket: ${socket.id} reason:`,
leftChat.why,
);
if (clientName !== null) {
const obj = {
destination: 'system-info',
type: 'chat',
user: clientName,
token: '',
text: 'LEFT the chat but the window is still open',
timestamp: Date.now(),
SenderWindowID: socket.id,
};
console.log(color.blue, 'BROADCASTS OUT :', obj.SenderWindowID);
broadcast(obj, obj.SenderWindowID);
// clientChat.delete(obj.user);
}
});
socket.on('client_entered', (data) => {
// data may be undefined (when frontend calls emit with no payload)
const userNameFromFrontend = data?.userName || null;
const userFromFrontend = data?.user || null;
let clientName = clientChat.get(socket.id)?.user || null;
// const client = clientChat.get(socket.id) || null;
let text = 'is back in the chat';
if (clientName === null) {
console.log('ERROR: clientName is NULL'); return;
};
// if (client === null) {
// console.log('ERROR: client is NULL'); return;
// };
if (userNameFromFrontend !== userFromFrontend) {
text = `'is back in the chat, I used to be called '${userNameFromFrontend}`;
clientName = userFromFrontend;
if (clientName === null) {
console.log('ERROR: clientName is NULL'); return;
};
// if (client) {
// client.user = clientName;
// }
}
console.log(
color.green,
`Client entered the Chat: ${clientName} (${socket.id})`,
);
if (clientName !== null) {
const obj = {
destination: 'system-info',
type: 'chat',
user: clientName,
frontendUserName: userNameFromFrontend,
frontendUser: userFromFrontend,
token: '',
text: text,
timestamp: Date.now(),
SenderWindowID: socket.id,
};
broadcast(obj, obj.SenderWindowID);
}
});
});
}

View file

@ -1,6 +1,17 @@
import { FastifyPluginAsync } from 'fastify';
import { MakeStaticResponse, typeResponse } from '@shared/utils';
import { Type } from '@sinclair/typebox';
import { Type } from 'typebox';
// import { UserId } from '@shared/database/mixin/user';
// import { Server } from 'socket.io';
// colors for console.log
export const color = {
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
reset: '\x1b[0m',
};
export const ChatRes = {
200: typeResponse('success', 'chat.success', {
@ -23,8 +34,19 @@ const route: FastifyPluginAsync = async (fastify): Promise<void> => {
config: { requireAuth: true },
},
async (req, res) => {
// console.log('/api/chat/test called =================>');
res.makeResponse(200, 'success', 'CCChat.success', { name: 'My_namw', 'id': req.authUser!.id, guest: false });
// const users = fastify.db.getAllUsers();
// console.log('ALL USERS EVER CONNECTED:', users);
// if (!users) return;
// for (const user of users) {
// console.log(color.yellow, 'USER:', user.name);
// }
// // const usersBlocked = fastify.db.getAllBlockedUsers();
// // console.log(color.red, "ALL BLOCKED USERS:", usersBlocked);
// fastify.db.addBlockedUserFor(users[0].id, users[1].id);
// const usersBlocked2 = fastify.db.getAllBlockedUsers();
// console.log(color.green, 'ALL BLOCKED USERS:', usersBlocked2);
res.makeResponse(200, 'success', 'CCChat.success', { name: 'name', 'id': req.authUser!.id, guest: false });
},
);
};

View file

@ -20,7 +20,7 @@
"@fastify/autoload": "^6.3.1",
"@fastify/formbody": "^8.0.2",
"@fastify/multipart": "^9.3.0",
"@fastify/sensible": "^6.0.3",
"@fastify/sensible": "^6.0.4",
"@fastify/static": "^8.3.0",
"fastify": "^5.6.2",
"fastify-cli": "^7.4.1",
@ -31,7 +31,7 @@
"devDependencies": {
"@types/node": "^22.19.1",
"rollup-plugin-node-externals": "^8.1.2",
"vite": "^7.2.4",
"vite": "^7.2.6",
"vite-tsconfig-paths": "^5.1.4"
}
}

View file

@ -1294,32 +1294,6 @@
}
}
}
},
"500": {
"description": "Default Response",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"kind",
"msg"
],
"properties": {
"kind": {
"enum": [
"failed"
]
},
"msg": {
"enum": [
"chat.failed.generic"
]
}
}
}
}
}
}
},
"tags": [

View file

@ -24,19 +24,19 @@
"devDependencies": {
"@eslint/js": "^9.39.1",
"@openapitools/openapi-generator-cli": "^2.25.2",
"@typescript-eslint/eslint-plugin": "^8.48.0",
"@typescript-eslint/parser": "^8.48.0",
"@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.48.1",
"eslint": "^9.39.1",
"husky": "^9.1.7",
"lint-staged": "^16.2.7",
"openapi-generator-cli": "^1.0.0",
"openapi-typescript": "^7.10.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.48.0",
"vite": "^7.2.4"
"typescript-eslint": "^8.48.1",
"vite": "^7.2.6"
},
"dependencies": {
"@redocly/cli": "^2.11.1",
"@redocly/cli": "^2.12.1",
"bindings": "^1.5.0"
}
}

420
src/pnpm-lock.yaml generated
View file

@ -9,8 +9,8 @@ importers:
.:
dependencies:
'@redocly/cli':
specifier: ^2.11.1
version: 2.11.1(@opentelemetry/api@1.9.0)(ajv@8.17.1)(core-js@3.47.0)
specifier: ^2.12.1
version: 2.12.1(@opentelemetry/api@1.9.0)(ajv@8.17.1)(core-js@3.47.0)
bindings:
specifier: ^1.5.0
version: 1.5.0
@ -22,11 +22,11 @@ importers:
specifier: ^2.25.2
version: 2.25.2(@types/node@24.10.1)
'@typescript-eslint/eslint-plugin':
specifier: ^8.48.0
version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)
specifier: ^8.48.1
version: 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: ^8.48.0
version: 8.48.0(eslint@9.39.1)(typescript@5.9.3)
specifier: ^8.48.1
version: 8.48.1(eslint@9.39.1)(typescript@5.9.3)
eslint:
specifier: ^9.39.1
version: 9.39.1
@ -46,11 +46,11 @@ importers:
specifier: ^5.9.3
version: 5.9.3
typescript-eslint:
specifier: ^8.48.0
version: 8.48.0(eslint@9.39.1)(typescript@5.9.3)
specifier: ^8.48.1
version: 8.48.1(eslint@9.39.1)(typescript@5.9.3)
vite:
specifier: ^7.2.4
version: 7.2.4(@types/node@24.10.1)(yaml@2.8.1)
specifier: ^7.2.6
version: 7.2.6(@types/node@24.10.1)(yaml@2.8.2)
'@shared':
dependencies:
@ -88,11 +88,11 @@ importers:
specifier: ^1.1.2
version: 1.1.2
typebox:
specifier: ^1.0.55
version: 1.0.55
specifier: ^1.0.61
version: 1.0.61
uuidv7:
specifier: ^1.0.2
version: 1.0.2
specifier: ^1.1.0
version: 1.1.0
devDependencies:
'@types/better-sqlite3':
specifier: ^7.6.13
@ -113,8 +113,8 @@ importers:
specifier: ^9.3.0
version: 9.3.0
'@fastify/sensible':
specifier: ^6.0.3
version: 6.0.3
specifier: ^6.0.4
version: 6.0.4
'@fastify/static':
specifier: ^8.3.0
version: 8.3.0
@ -131,8 +131,8 @@ importers:
specifier: ^5.1.0
version: 5.1.0
typebox:
specifier: ^1.0.55
version: 1.0.55
specifier: ^1.0.61
version: 1.0.61
devDependencies:
'@types/node':
specifier: ^22.19.1
@ -141,11 +141,11 @@ importers:
specifier: ^8.1.2
version: 8.1.2(rollup@4.53.3)
vite:
specifier: ^7.2.4
version: 7.2.4(@types/node@22.19.1)(yaml@2.8.1)
specifier: ^7.2.6
version: 7.2.6(@types/node@22.19.1)(yaml@2.8.2)
vite-tsconfig-paths:
specifier: ^5.1.4
version: 5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@22.19.1)(yaml@2.8.1))
version: 5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.19.1)(yaml@2.8.2))
chat:
dependencies:
@ -159,17 +159,14 @@ importers:
specifier: ^9.3.0
version: 9.3.0
'@fastify/sensible':
specifier: ^6.0.3
version: 6.0.3
specifier: ^6.0.4
version: 6.0.4
'@fastify/static':
specifier: ^8.3.0
version: 8.3.0
'@fastify/websocket':
specifier: ^11.2.0
version: 11.2.0
'@sinclair/typebox':
specifier: ^0.34.41
version: 0.34.41
fastify:
specifier: ^5.6.2
version: 5.6.2
@ -179,6 +176,9 @@ importers:
socket.io:
specifier: ^4.8.1
version: 4.8.1
typebox:
specifier: ^1.0.61
version: 1.0.61
devDependencies:
'@types/node':
specifier: ^22.19.1
@ -187,11 +187,11 @@ importers:
specifier: ^8.1.2
version: 8.1.2(rollup@4.53.3)
vite:
specifier: ^7.2.4
version: 7.2.4(@types/node@22.19.1)(yaml@2.8.1)
specifier: ^7.2.6
version: 7.2.6(@types/node@22.19.1)(yaml@2.8.2)
vite-tsconfig-paths:
specifier: ^5.1.4
version: 5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@22.19.1)(yaml@2.8.1))
version: 5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.19.1)(yaml@2.8.2))
icons:
dependencies:
@ -205,8 +205,8 @@ importers:
specifier: ^9.3.0
version: 9.3.0
'@fastify/sensible':
specifier: ^6.0.3
version: 6.0.3
specifier: ^6.0.4
version: 6.0.4
'@fastify/static':
specifier: ^8.3.0
version: 8.3.0
@ -233,11 +233,11 @@ importers:
specifier: ^8.1.2
version: 8.1.2(rollup@4.53.3)
vite:
specifier: ^7.2.4
version: 7.2.4(@types/node@22.19.1)(yaml@2.8.1)
specifier: ^7.2.6
version: 7.2.6(@types/node@22.19.1)(yaml@2.8.2)
vite-tsconfig-paths:
specifier: ^5.1.4
version: 5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@22.19.1)(yaml@2.8.1))
version: 5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.19.1)(yaml@2.8.2))
user:
dependencies:
@ -251,8 +251,8 @@ importers:
specifier: ^9.3.0
version: 9.3.0
'@fastify/sensible':
specifier: ^6.0.3
version: 6.0.3
specifier: ^6.0.4
version: 6.0.4
'@fastify/static':
specifier: ^8.3.0
version: 8.3.0
@ -266,8 +266,8 @@ importers:
specifier: ^5.1.0
version: 5.1.0
typebox:
specifier: ^1.0.55
version: 1.0.55
specifier: ^1.0.61
version: 1.0.61
devDependencies:
'@types/node':
specifier: ^22.19.1
@ -276,11 +276,11 @@ importers:
specifier: ^8.1.2
version: 8.1.2(rollup@4.53.3)
vite:
specifier: ^7.2.4
version: 7.2.4(@types/node@22.19.1)(yaml@2.8.1)
specifier: ^7.2.6
version: 7.2.6(@types/node@22.19.1)(yaml@2.8.2)
vite-tsconfig-paths:
specifier: ^5.1.4
version: 5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@22.19.1)(yaml@2.8.1))
version: 5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.19.1)(yaml@2.8.2))
packages:
@ -489,8 +489,8 @@ packages:
resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/eslintrc@3.3.1':
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
'@eslint/eslintrc@3.3.3':
resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/js@9.39.1':
@ -557,8 +557,8 @@ packages:
'@fastify/send@4.1.0':
resolution: {integrity: sha512-TMYeQLCBSy2TOFmV95hQWkiTYgC/SEx7vMdV+wnZVX4tt8VBLKzmH8vV9OzJehV0+XBfg+WxPMt5wp+JBUKsVw==}
'@fastify/sensible@6.0.3':
resolution: {integrity: sha512-Iyn8698hp/e5+v8SNBBruTa7UfrMEP52R16dc9jMpqSyEcPsvWFQo+R6WwHCUnJiLIsuci2ZoEZ7ilrSSCPIVg==}
'@fastify/sensible@6.0.4':
resolution: {integrity: sha512-1vxcCUlPMew6WroK8fq+LVOwbsLtX+lmuRuqpcp6eYqu6vmkLwbKTdBWAZwbeaSgCfW4tzUpTIHLLvTiQQ1BwQ==}
'@fastify/static@8.3.0':
resolution: {integrity: sha512-yKxviR5PH1OKNnisIzZKmgZSus0r2OZb8qCSbqmw34aolT4g3UlzYfeBRym+HJ1J471CR8e2ldNub4PubD1coA==}
@ -940,33 +940,30 @@ packages:
'@protobufjs/utf8@1.1.0':
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
'@redocly/ajv@8.11.4':
resolution: {integrity: sha512-77MhyFgZ1zGMwtCpqsk532SJEc3IJmSOXKTCeWoMTAvPnQOkuOgxEip1n5pG5YX1IzCTJ4kCvPKr8xYyzWFdhg==}
'@redocly/ajv@8.17.1':
resolution: {integrity: sha512-EDtsGZS964mf9zAUXAl9Ew16eYbeyAFWhsPr0fX6oaJxgd8rApYlPBf0joyhnUHz88WxrigyFtTaqqzXNzPgqw==}
'@redocly/cli@2.11.1':
resolution: {integrity: sha512-doNs+sdrFzzXmyf1yIeJbPh8OChacHWkvTE9N0QbuCmnYQ4k0v1IMP20qsitkwR+fK8O1hXSnFnSTVvIunMVVw==}
'@redocly/cli@2.12.1':
resolution: {integrity: sha512-XGD28QjjZEzN+J9WOROzw4fHNi+Fyw/gCyDZDgI4nX4j9gEBT1PcxN75wWpMoDGHKAUj8ghrhMHtfQoUuR90zg==}
engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'}
hasBin: true
'@redocly/config@0.22.2':
resolution: {integrity: sha512-roRDai8/zr2S9YfmzUfNhKjOF0NdcOIqF7bhf4MVC5UxpjIysDjyudvlAiVbpPHp3eDRWbdzUgtkK1a7YiDNyQ==}
'@redocly/config@0.38.0':
resolution: {integrity: sha512-kSgMG3rRzgXIP/6gWMRuWbu9/ms0Cyuphcx19dPR9qlgc1tt9IKYPsFQ+KhJuEtqd3bcY/+Uflysf33dQkZWVQ==}
'@redocly/config@0.40.0':
resolution: {integrity: sha512-MZQZs7QEGnue3rVN9Q9QvDbcGjesxbpKXUvDeckS69R1xjtgsnT9B39VA25zmwSJtgUeA9ST+sMf9GxIqixNbw==}
'@redocly/openapi-core@1.34.5':
resolution: {integrity: sha512-0EbE8LRbkogtcCXU7liAyC00n9uNG9hJ+eMyHFdUsy9lB/WGqnEBgwjA9q2cyzAVcdTkQqTBBU1XePNnN3OijA==}
engines: {node: '>=18.17.0', npm: '>=9.5.0'}
'@redocly/openapi-core@2.11.1':
resolution: {integrity: sha512-FVCDnZxaoUJwLQxfW4inCojxUO56J3ntu7dDAE2qyWd6tJBK45CnXMQQUxpqeRTeXROr3jYQoApAw+GCEnyBeg==}
'@redocly/openapi-core@2.12.1':
resolution: {integrity: sha512-xMlKf4dnZsxP3JYBNZFsMNBJqVxWlwLuyGLhGc36hXw50YOla1UjrVZ5psIyzLXgUPI3QJDA1XmGcJ8rcex/ow==}
engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'}
'@redocly/respect-core@2.11.1':
resolution: {integrity: sha512-jSMJvCJeo5gmhQfg82AhuwCG0h8gbW5vqHyRITBu8KHVsBiQTgvfhXepu8SKHeJu0OexYtEc0nUnGLJlefevYw==}
'@redocly/respect-core@2.12.1':
resolution: {integrity: sha512-ADm+JMHWGYeOwzdGEQ8CYKjmMBLU0ycZTwJbCkQsUulXSNkNA7GzA8lrMM2+I8cPMRk25G5PmtfAR7U+a0o1ew==}
engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'}
'@rollup/rollup-android-arm-eabi@4.53.3':
@ -1079,9 +1076,6 @@ packages:
cpu: [x64]
os: [win32]
'@sinclair/typebox@0.34.41':
resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==}
'@socket.io/component-emitter@3.1.2':
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
@ -1125,63 +1119,63 @@ packages:
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
'@typescript-eslint/eslint-plugin@8.48.0':
resolution: {integrity: sha512-XxXP5tL1txl13YFtrECECQYeZjBZad4fyd3cFV4a19LkAY/bIp9fev3US4S5fDVV2JaYFiKAZ/GRTOLer+mbyQ==}
'@typescript-eslint/eslint-plugin@8.48.1':
resolution: {integrity: sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.48.0
'@typescript-eslint/parser': ^8.48.1
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/parser@8.48.0':
resolution: {integrity: sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==}
'@typescript-eslint/parser@8.48.1':
resolution: {integrity: sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/project-service@8.48.0':
resolution: {integrity: sha512-Ne4CTZyRh1BecBf84siv42wv5vQvVmgtk8AuiEffKTUo3DrBaGYZueJSxxBZ8fjk/N3DrgChH4TOdIOwOwiqqw==}
'@typescript-eslint/project-service@8.48.1':
resolution: {integrity: sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/scope-manager@8.48.0':
resolution: {integrity: sha512-uGSSsbrtJrLduti0Q1Q9+BF1/iFKaxGoQwjWOIVNJv0o6omrdyR8ct37m4xIl5Zzpkp69Kkmvom7QFTtue89YQ==}
'@typescript-eslint/scope-manager@8.48.1':
resolution: {integrity: sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.48.0':
resolution: {integrity: sha512-WNebjBdFdyu10sR1M4OXTt2OkMd5KWIL+LLfeH9KhgP+jzfDV/LI3eXzwJ1s9+Yc0Kzo2fQCdY/OpdusCMmh6w==}
'@typescript-eslint/tsconfig-utils@8.48.1':
resolution: {integrity: sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/type-utils@8.48.0':
resolution: {integrity: sha512-zbeVaVqeXhhab6QNEKfK96Xyc7UQuoFWERhEnj3mLVnUWrQnv15cJNseUni7f3g557gm0e46LZ6IJ4NJVOgOpw==}
'@typescript-eslint/type-utils@8.48.1':
resolution: {integrity: sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/types@8.48.0':
resolution: {integrity: sha512-cQMcGQQH7kwKoVswD1xdOytxQR60MWKM1di26xSUtxehaDs/32Zpqsu5WJlXTtTTqyAVK8R7hvsUnIXRS+bjvA==}
'@typescript-eslint/types@8.48.1':
resolution: {integrity: sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.48.0':
resolution: {integrity: sha512-ljHab1CSO4rGrQIAyizUS6UGHHCiAYhbfcIZ1zVJr5nMryxlXMVWS3duFPSKvSUbFPwkXMFk1k0EMIjub4sRRQ==}
'@typescript-eslint/typescript-estree@8.48.1':
resolution: {integrity: sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/utils@8.48.0':
resolution: {integrity: sha512-yTJO1XuGxCsSfIVt1+1UrLHtue8xz16V8apzPYI06W0HbEbEWHxHXgZaAgavIkoh+GeV6hKKd5jm0sS6OYxWXQ==}
'@typescript-eslint/utils@8.48.1':
resolution: {integrity: sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/visitor-keys@8.48.0':
resolution: {integrity: sha512-T0XJMaRPOH3+LBbAfzR2jalckP1MSG/L9eUtY0DEzUyVaXJ/t6zN0nR7co5kz0Jko/nkSYCBRkz1djvjajVTTg==}
'@typescript-eslint/visitor-keys@8.48.1':
resolution: {integrity: sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
abort-controller@3.0.0:
@ -1209,14 +1203,6 @@ packages:
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
engines: {node: '>= 14'}
ajv-formats@2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
ajv: ^8.0.0
peerDependenciesMeta:
ajv:
optional: true
ajv-formats@3.0.1:
resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==}
peerDependencies:
@ -1479,12 +1465,16 @@ packages:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
content-type@1.0.5:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
cookie@0.7.2:
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
engines: {node: '>= 0.6'}
cookie@1.0.2:
resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==}
cookie@1.1.1:
resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
engines: {node: '>=18'}
core-js@3.47.0:
@ -1726,8 +1716,8 @@ packages:
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
engines: {node: '>=6'}
fast-copy@3.0.2:
resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==}
fast-copy@4.0.0:
resolution: {integrity: sha512-/oA0gx1xyXE9R2YlV4FXwZJXngFdm9Du0zN8FhY38jnLkhp1u35h6bCyKgRhlsA6C9I+1vfXE4KISdt7xc6M9w==}
fast-decode-uri-component@1.0.1:
resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
@ -2019,8 +2009,8 @@ packages:
resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
engines: {node: '>= 12'}
ipaddr.js@2.2.0:
resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==}
ipaddr.js@2.3.0:
resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==}
engines: {node: '>= 10'}
is-binary-path@2.1.0:
@ -2187,8 +2177,8 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
lru-cache@11.2.2:
resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==}
lru-cache@11.2.4:
resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==}
engines: {node: 20 || >=22}
lru-cache@7.18.3:
@ -2213,9 +2203,9 @@ packages:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
media-typer@0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
media-typer@1.1.0:
resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
engines: {node: '>= 0.8'}
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
@ -2225,10 +2215,18 @@ packages:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
mime-db@1.54.0:
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
engines: {node: '>= 0.6'}
mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
mime-types@3.0.2:
resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
engines: {node: '>=18'}
mime@3.0.0:
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
engines: {node: '>=10.0.0'}
@ -2521,8 +2519,11 @@ packages:
pino-abstract-transport@2.0.0:
resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==}
pino-pretty@13.1.2:
resolution: {integrity: sha512-3cN0tCakkT4f3zo9RXDIhy6GTvtYD6bK4CRBLN9j3E/ePqN1tugAXD5rGVfoChW6s0hiek+eyYlLNqc/BG7vBQ==}
pino-abstract-transport@3.0.0:
resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==}
pino-pretty@13.1.3:
resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==}
hasBin: true
pino-std-serializers@7.0.0:
@ -3021,15 +3022,15 @@ packages:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
type-is@1.6.18:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
type-is@2.0.1:
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
engines: {node: '>= 0.6'}
typebox@1.0.55:
resolution: {integrity: sha512-TP02wN0B6tDZngprrGVu/Z9s/QUyVEmR7VIg1yEOtsqyDdXXEoQPSfWdkD2PsA2lGLxu6GgwOTtGZVS9CAoERg==}
typebox@1.0.61:
resolution: {integrity: sha512-5KeeL5QoPBoYm8Z7tGR1Pw9FjWA75MLhVuiSMCRgtgTg/d2+kTvolFddhOUua9FxpIaqXznFPZcc3sl6cEpafw==}
typescript-eslint@8.48.0:
resolution: {integrity: sha512-fcKOvQD9GUn3Xw63EgiDqhvWJ5jsyZUaekl3KVpGsDJnN46WJTe3jWxtQP9lMZm1LJNkFLlTaWAxK2vUQR+cqw==}
typescript-eslint@8.48.1:
resolution: {integrity: sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@ -3071,9 +3072,6 @@ packages:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
uri-js-replace@1.0.1:
resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==}
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@ -3088,8 +3086,8 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
uuidv7@1.0.2:
resolution: {integrity: sha512-8JQkH4ooXnm1JCIhqTMbtmdnYEn6oKukBxHn1Ic9878jMkL7daTI7anTExfY18VRCX7tcdn5quzvCb6EWrR8PA==}
uuidv7@1.1.0:
resolution: {integrity: sha512-2VNnOC0+XQlwogChUDzy6pe8GQEys9QFZBGOh54l6qVfwoCUwwRvk7rDTgaIsRgsF5GFa5oiNg8LqXE3jofBBg==}
hasBin: true
vary@1.1.2:
@ -3104,8 +3102,8 @@ packages:
vite:
optional: true
vite@7.2.4:
resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==}
vite@7.2.6:
resolution: {integrity: sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
@ -3238,8 +3236,8 @@ packages:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
yaml@2.8.1:
resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==}
yaml@2.8.2:
resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
engines: {node: '>= 14.6'}
hasBin: true
@ -3395,7 +3393,7 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
'@eslint/eslintrc@3.3.1':
'@eslint/eslintrc@3.3.3':
dependencies:
ajv: 6.12.6
debug: 4.4.3(supports-color@10.2.2)
@ -3436,7 +3434,7 @@ snapshots:
'@fastify/cookie@11.0.2':
dependencies:
cookie: 1.0.2
cookie: 1.1.1
fastify-plugin: 5.1.0
'@fastify/deepmerge@3.1.0': {}
@ -3477,7 +3475,7 @@ snapshots:
'@fastify/proxy-addr@5.1.0':
dependencies:
'@fastify/forwarded': 3.0.1
ipaddr.js: 2.2.0
ipaddr.js: 2.3.0
'@fastify/send@4.1.0':
dependencies:
@ -3487,14 +3485,14 @@ snapshots:
http-errors: 2.0.1
mime: 3.0.0
'@fastify/sensible@6.0.3':
'@fastify/sensible@6.0.4':
dependencies:
'@lukeed/ms': 2.0.2
dequal: 2.0.3
fastify-plugin: 5.1.0
forwarded: 0.2.0
http-errors: 2.0.1
type-is: 1.6.18
type-is: 2.0.1
vary: 1.1.2
'@fastify/static@8.3.0':
@ -3512,7 +3510,7 @@ snapshots:
fastify-plugin: 5.1.0
openapi-types: 12.1.3
rfdc: 1.4.1
yaml: 2.8.1
yaml: 2.8.2
'@fastify/swagger@9.6.1':
dependencies:
@ -3520,7 +3518,7 @@ snapshots:
json-schema-resolver: 3.0.0
openapi-types: 12.1.3
rfdc: 1.4.1
yaml: 2.8.1
yaml: 2.8.2
transitivePeerDependencies:
- supports-color
@ -3859,13 +3857,6 @@ snapshots:
'@protobufjs/utf8@1.1.0': {}
'@redocly/ajv@8.11.4':
dependencies:
fast-deep-equal: 3.1.3
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
uri-js-replace: 1.0.1
'@redocly/ajv@8.17.1':
dependencies:
fast-deep-equal: 3.1.3
@ -3873,14 +3864,14 @@ snapshots:
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
'@redocly/cli@2.11.1(@opentelemetry/api@1.9.0)(ajv@8.17.1)(core-js@3.47.0)':
'@redocly/cli@2.12.1(@opentelemetry/api@1.9.0)(ajv@8.17.1)(core-js@3.47.0)':
dependencies:
'@opentelemetry/exporter-trace-otlp-http': 0.202.0(@opentelemetry/api@1.9.0)
'@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0)
'@opentelemetry/sdk-trace-node': 2.0.1(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.34.0
'@redocly/openapi-core': 2.11.1(ajv@8.17.1)
'@redocly/respect-core': 2.11.1(ajv@8.17.1)
'@redocly/openapi-core': 2.12.1(ajv@8.17.1)
'@redocly/respect-core': 2.12.1(ajv@8.17.1)
abort-controller: 3.0.0
chokidar: 3.6.0
colorette: 1.4.0
@ -3913,7 +3904,7 @@ snapshots:
'@redocly/config@0.22.2': {}
'@redocly/config@0.38.0':
'@redocly/config@0.40.0':
dependencies:
json-schema-to-ts: 2.7.2
@ -3931,11 +3922,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@redocly/openapi-core@2.11.1(ajv@8.17.1)':
'@redocly/openapi-core@2.12.1(ajv@8.17.1)':
dependencies:
'@redocly/ajv': 8.17.1
'@redocly/config': 0.38.0
ajv-formats: 2.1.1(ajv@8.17.1)
'@redocly/config': 0.40.0
ajv-formats: 3.0.1(ajv@8.17.1)
colorette: 1.4.0
js-levenshtein: 1.1.6
js-yaml: 4.1.1
@ -3945,12 +3936,12 @@ snapshots:
transitivePeerDependencies:
- ajv
'@redocly/respect-core@2.11.1(ajv@8.17.1)':
'@redocly/respect-core@2.12.1(ajv@8.17.1)':
dependencies:
'@faker-js/faker': 7.6.0
'@noble/hashes': 1.8.0
'@redocly/ajv': 8.11.4
'@redocly/openapi-core': 2.11.1(ajv@8.17.1)
'@redocly/ajv': 8.17.1
'@redocly/openapi-core': 2.12.1(ajv@8.17.1)
better-ajv-errors: 1.2.0(ajv@8.17.1)
colorette: 2.0.20
json-pointer: 0.6.2
@ -4026,8 +4017,6 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.53.3':
optional: true
'@sinclair/typebox@0.34.41': {}
'@socket.io/component-emitter@3.1.2': {}
'@standard-schema/spec@1.0.0': {}
@ -4073,14 +4062,14 @@ snapshots:
'@types/trusted-types@2.0.7':
optional: true
'@typescript-eslint/eslint-plugin@8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)':
'@typescript-eslint/eslint-plugin@8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.48.0(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.48.0
'@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/utils': 8.48.0(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.48.0
'@typescript-eslint/parser': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.48.1
'@typescript-eslint/type-utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.48.1
eslint: 9.39.1
graphemer: 1.4.0
ignore: 7.0.5
@ -4090,41 +4079,41 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.9.3)':
'@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.48.0
'@typescript-eslint/types': 8.48.0
'@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.48.0
'@typescript-eslint/scope-manager': 8.48.1
'@typescript-eslint/types': 8.48.1
'@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.48.1
debug: 4.4.3(supports-color@10.2.2)
eslint: 9.39.1
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/project-service@8.48.0(typescript@5.9.3)':
'@typescript-eslint/project-service@8.48.1(typescript@5.9.3)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.9.3)
'@typescript-eslint/types': 8.48.0
'@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.3)
'@typescript-eslint/types': 8.48.1
debug: 4.4.3(supports-color@10.2.2)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/scope-manager@8.48.0':
'@typescript-eslint/scope-manager@8.48.1':
dependencies:
'@typescript-eslint/types': 8.48.0
'@typescript-eslint/visitor-keys': 8.48.0
'@typescript-eslint/types': 8.48.1
'@typescript-eslint/visitor-keys': 8.48.1
'@typescript-eslint/tsconfig-utils@8.48.0(typescript@5.9.3)':
'@typescript-eslint/tsconfig-utils@8.48.1(typescript@5.9.3)':
dependencies:
typescript: 5.9.3
'@typescript-eslint/type-utils@8.48.0(eslint@9.39.1)(typescript@5.9.3)':
'@typescript-eslint/type-utils@8.48.1(eslint@9.39.1)(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 8.48.0
'@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.48.0(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/types': 8.48.1
'@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3)
'@typescript-eslint/utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
debug: 4.4.3(supports-color@10.2.2)
eslint: 9.39.1
ts-api-utils: 2.1.0(typescript@5.9.3)
@ -4132,14 +4121,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types@8.48.0': {}
'@typescript-eslint/types@8.48.1': {}
'@typescript-eslint/typescript-estree@8.48.0(typescript@5.9.3)':
'@typescript-eslint/typescript-estree@8.48.1(typescript@5.9.3)':
dependencies:
'@typescript-eslint/project-service': 8.48.0(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.9.3)
'@typescript-eslint/types': 8.48.0
'@typescript-eslint/visitor-keys': 8.48.0
'@typescript-eslint/project-service': 8.48.1(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.3)
'@typescript-eslint/types': 8.48.1
'@typescript-eslint/visitor-keys': 8.48.1
debug: 4.4.3(supports-color@10.2.2)
minimatch: 9.0.5
semver: 7.7.3
@ -4149,20 +4138,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.48.0(eslint@9.39.1)(typescript@5.9.3)':
'@typescript-eslint/utils@8.48.1(eslint@9.39.1)(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1)
'@typescript-eslint/scope-manager': 8.48.0
'@typescript-eslint/types': 8.48.0
'@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.48.1
'@typescript-eslint/types': 8.48.1
'@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3)
eslint: 9.39.1
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/visitor-keys@8.48.0':
'@typescript-eslint/visitor-keys@8.48.1':
dependencies:
'@typescript-eslint/types': 8.48.0
'@typescript-eslint/types': 8.48.1
eslint-visitor-keys: 4.2.1
abort-controller@3.0.0:
@ -4184,10 +4173,6 @@ snapshots:
agent-base@7.1.4: {}
ajv-formats@2.1.1(ajv@8.17.1):
optionalDependencies:
ajv: 8.17.1
ajv-formats@3.0.1(ajv@8.17.1):
optionalDependencies:
ajv: 8.17.1
@ -4446,9 +4431,11 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
content-type@1.0.5: {}
cookie@0.7.2: {}
cookie@1.0.2: {}
cookie@1.1.1: {}
core-js@3.47.0: {}
@ -4656,7 +4643,7 @@ snapshots:
'@eslint/config-array': 0.21.1
'@eslint/config-helpers': 0.4.2
'@eslint/core': 0.17.0
'@eslint/eslintrc': 3.3.1
'@eslint/eslintrc': 3.3.3
'@eslint/js': 9.39.1
'@eslint/plugin-kit': 0.4.1
'@humanfs/node': 0.16.7
@ -4714,7 +4701,7 @@ snapshots:
expand-template@2.0.3: {}
fast-copy@3.0.2: {}
fast-copy@4.0.0: {}
fast-decode-uri-component@1.0.1: {}
@ -4769,7 +4756,7 @@ snapshots:
generify: 4.2.0
help-me: 5.0.0
is-docker: 2.2.1
pino-pretty: 13.1.2
pino-pretty: 13.1.3
pkg-up: 3.1.0
resolve-from: 5.0.0
semver: 7.7.3
@ -5058,7 +5045,7 @@ snapshots:
ip-address@10.1.0: {}
ipaddr.js@2.2.0: {}
ipaddr.js@2.3.0: {}
is-binary-path@2.1.0:
dependencies:
@ -5167,7 +5154,7 @@ snapshots:
light-my-request@6.6.0:
dependencies:
cookie: 1.0.2
cookie: 1.1.1
process-warning: 4.0.1
set-cookie-parser: 2.7.2
@ -5179,7 +5166,7 @@ snapshots:
nano-spawn: 2.0.0
pidtree: 0.6.0
string-argv: 0.3.2
yaml: 2.8.1
yaml: 2.8.2
listr2@9.0.5:
dependencies:
@ -5224,7 +5211,7 @@ snapshots:
dependencies:
js-tokens: 4.0.0
lru-cache@11.2.2: {}
lru-cache@11.2.4: {}
lru-cache@7.18.3: {}
@ -5240,7 +5227,7 @@ snapshots:
math-intrinsics@1.1.0: {}
media-typer@0.3.0: {}
media-typer@1.1.0: {}
micromatch@4.0.8:
dependencies:
@ -5249,10 +5236,16 @@ snapshots:
mime-db@1.52.0: {}
mime-db@1.54.0: {}
mime-types@2.1.35:
dependencies:
mime-db: 1.52.0
mime-types@3.0.2:
dependencies:
mime-db: 1.54.0
mime@3.0.0: {}
mimic-fn@2.1.0: {}
@ -5501,7 +5494,7 @@ snapshots:
path-scurry@2.0.1:
dependencies:
lru-cache: 11.2.2
lru-cache: 11.2.4
minipass: 7.1.2
path-to-regexp@8.3.0: {}
@ -5520,17 +5513,21 @@ snapshots:
dependencies:
split2: 4.2.0
pino-pretty@13.1.2:
pino-abstract-transport@3.0.0:
dependencies:
split2: 4.2.0
pino-pretty@13.1.3:
dependencies:
colorette: 2.0.20
dateformat: 4.6.3
fast-copy: 3.0.2
fast-copy: 4.0.0
fast-safe-stringify: 2.1.1
help-me: 5.0.0
joycon: 3.1.1
minimist: 1.2.8
on-exit-leak-free: 2.1.2
pino-abstract-transport: 2.0.0
pino-abstract-transport: 3.0.0
pump: 3.0.3
secure-json-parse: 4.1.0
sonic-boom: 4.2.0
@ -6151,19 +6148,20 @@ snapshots:
type-fest@4.41.0: {}
type-is@1.6.18:
type-is@2.0.1:
dependencies:
media-typer: 0.3.0
mime-types: 2.1.35
content-type: 1.0.5
media-typer: 1.1.0
mime-types: 3.0.2
typebox@1.0.55: {}
typebox@1.0.61: {}
typescript-eslint@8.48.0(eslint@9.39.1)(typescript@5.9.3):
typescript-eslint@8.48.1(eslint@9.39.1)(typescript@5.9.3):
dependencies:
'@typescript-eslint/eslint-plugin': 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/parser': 8.48.0(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.48.0(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/parser': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.3)
'@typescript-eslint/utils': 8.48.1(eslint@9.39.1)(typescript@5.9.3)
eslint: 9.39.1
typescript: 5.9.3
transitivePeerDependencies:
@ -6190,8 +6188,6 @@ snapshots:
unpipe@1.0.0: {}
uri-js-replace@1.0.1: {}
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
@ -6204,22 +6200,22 @@ snapshots:
util-deprecate@1.0.2: {}
uuidv7@1.0.2: {}
uuidv7@1.1.0: {}
vary@1.1.2: {}
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@22.19.1)(yaml@2.8.1)):
vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.19.1)(yaml@2.8.2)):
dependencies:
debug: 4.4.3(supports-color@10.2.2)
globrex: 0.1.2
tsconfck: 3.1.6(typescript@5.9.3)
optionalDependencies:
vite: 7.2.4(@types/node@22.19.1)(yaml@2.8.1)
vite: 7.2.6(@types/node@22.19.1)(yaml@2.8.2)
transitivePeerDependencies:
- supports-color
- typescript
vite@7.2.4(@types/node@22.19.1)(yaml@2.8.1):
vite@7.2.6(@types/node@22.19.1)(yaml@2.8.2):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
@ -6230,9 +6226,9 @@ snapshots:
optionalDependencies:
'@types/node': 22.19.1
fsevents: 2.3.3
yaml: 2.8.1
yaml: 2.8.2
vite@7.2.4(@types/node@24.10.1)(yaml@2.8.1):
vite@7.2.6(@types/node@24.10.1)(yaml@2.8.2):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
@ -6243,7 +6239,7 @@ snapshots:
optionalDependencies:
'@types/node': 24.10.1
fsevents: 2.3.3
yaml: 2.8.1
yaml: 2.8.2
walker@1.0.8:
dependencies:
@ -6308,7 +6304,7 @@ snapshots:
yaml@1.10.2: {}
yaml@2.8.1: {}
yaml@2.8.2: {}
yargs-parser@20.2.9: {}

View file

@ -21,17 +21,17 @@
"@fastify/autoload": "^6.3.1",
"@fastify/formbody": "^8.0.2",
"@fastify/multipart": "^9.3.0",
"@fastify/sensible": "^6.0.3",
"@fastify/sensible": "^6.0.4",
"@fastify/static": "^8.3.0",
"fastify": "^5.6.2",
"fastify-cli": "^7.4.1",
"fastify-plugin": "^5.1.0",
"typebox": "^1.0.55"
"typebox": "^1.0.61"
},
"devDependencies": {
"@types/node": "^22.19.1",
"rollup-plugin-node-externals": "^8.1.2",
"vite": "^7.2.4",
"vite": "^7.2.6",
"vite-tsconfig-paths": "^5.1.4"
}
}