commit c3d80f0c61323a1f892e7868f386394bb23cc6b9 Author: KCar Date: Sat Aug 23 13:04:42 2025 +0000 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..17278e9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +# syntax=docker/dockerfile:1 + +# Use a base image with node and build essentials +FROM node:20-buster + +# Install dependencies and Bun +RUN apt-get update && \ + apt-get install -y curl git unzip && \ + curl -fsSL https://bun.sh/install | bash + +# Add Bun to PATH +ENV PATH="/root/.bun/bin:${PATH}" + +# Set working directory +WORKDIR /app + +# Copy package files first +COPY package*.json ./ + +# Install dependencies using bun +RUN bun install + +# Copy the rest of the application code +COPY . . + +# Create logs directory +RUN mkdir -p /app/logs && chmod 777 /app/logs + +# Expose port 5002 explicitly +EXPOSE 5002 + +# Set environment variables +ENV LOG_PATH=/app/logs + +# Use npm/bun scripts to run the server +CMD ["bun", "run", "dev-server-bun"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e000c4b --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Node/Bun server example + +This is a simple example of how to integrate tldraw's sync engine with a Node server or a Bun server. + +Run `yarn dev-node` or `yarn dev-bun` in this folder to start the server + client. diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json new file mode 100644 index 0000000..a892cb6 --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "scripts": { + "dev-server-bun": "bun --watch ./src/server/server.bun.ts" + }, + "dependencies": { + "@dagrejs/dagre": "^1.1.4", + "@fastify/cors": "^9.0.1", + "@fastify/websocket": "^10.0.1", + "@tldraw/sync": "3.6.1", + "@tldraw/sync-core": "3.6.1", + "@tldraw/tlschema": "3.6.1", + "@vitejs/plugin-react-swc": "^3.7.0", + "axios": "^1.7.2", + "cheerio": "^1.0.0-rc.12", + "crypto-browserify": "^3.12.0", + "fastify": "^4.28.1", + "itty-router": "^5.0.17", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.24.1", + "socket.io-client": "^4.8.0", + "unfurl.js": "^6.4.0", + "vite": "^5.3.3", + "ws": "^8.16.0" + }, + "devDependencies": { + "@types/bun": "^1.1.6", + "@types/express": "^4.17.21", + "@types/node": "^20.11.0", + "@types/ws": "^8.5.10", + "concurrently": "^8.2.2", + "lazyrepo": "0.0.0-alpha.27", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@babel/core": "^7.23.3", + "@babel/preset-react": "^7.23.3", + "typescript": "^5.3.3" + } +} \ No newline at end of file diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..2d52e28 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/axiosConfig.ts b/src/axiosConfig.ts new file mode 100644 index 0000000..82a29d0 --- /dev/null +++ b/src/axiosConfig.ts @@ -0,0 +1,2 @@ +import axios from 'axios'; +export default axios; \ No newline at end of file diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000..49cdadb --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,46 @@ +import { existsSync, mkdirSync } from 'fs'; +import { join } from 'path'; + +const LOG_DIR = process.env.LOG_PATH || './logs'; +const LOG_FILE = join(LOG_DIR, 'server.log'); + +// Ensure log directory exists +if (!existsSync(LOG_DIR)) { + mkdirSync(LOG_DIR, { recursive: true }); +} + +type LogLevel = 'INFO' | 'ERROR' | 'DEBUG' | 'WARN'; + +function formatLog(level: LogLevel, message: string, data?: any): string { + const timestamp = new Date().toISOString(); + const dataStr = data ? `\n${JSON.stringify(data, null, 2)}` : ''; + return `[${timestamp}] [${level}] ${message}${dataStr}\n`; +} + +export const logger = { + info: (message: string, data?: any) => { + const log = formatLog('INFO', message, data); + console.log(log); + Bun.write(LOG_FILE, log, { append: true }); + }, + + error: (message: string, data?: any) => { + const log = formatLog('ERROR', message, data); + console.error(log); + Bun.write(LOG_FILE, log, { append: true }); + }, + + debug: (message: string, data?: any) => { + if (process.env.NODE_ENV === 'development') { + const log = formatLog('DEBUG', message, data); + console.debug(log); + Bun.write(LOG_FILE, log, { append: true }); + } + }, + + warn: (message: string, data?: any) => { + const log = formatLog('WARN', message, data); + console.warn(log); + Bun.write(LOG_FILE, log, { append: true }); + } +}; \ No newline at end of file diff --git a/src/server/assets.ts b/src/server/assets.ts new file mode 100644 index 0000000..8b47c1a --- /dev/null +++ b/src/server/assets.ts @@ -0,0 +1,53 @@ +import { mkdir, readFile, writeFile } from 'fs/promises' +import { join, resolve } from 'path' +import { Readable } from 'stream' +import crypto from 'crypto' + +// We are just using the filesystem to store assets +const DIR = resolve('./.assets') + +function hashFileName(fileName: string): string { + return crypto.createHash('md5').update(fileName).digest('hex') +} + +export async function storeAsset(id: string, stream: Readable) { + console.log(`Storing asset with ID: ${id}`) + console.log(`Asset directory: ${DIR}`) + + try { + await mkdir(DIR, { recursive: true }) + console.log(`Directory created or already exists: ${DIR}`) + + const hashedFileName = hashFileName(id) + const filePath = join(DIR, hashedFileName) + console.log(`Writing file to path: ${filePath}`) + + const chunks = [] + for await (const chunk of stream) { + chunks.push(chunk) + } + const buffer = Buffer.concat(chunks) + + await writeFile(filePath, buffer) + console.log(`Asset stored successfully with ID: ${id}`) + } catch (error) { + console.error(`Error storing asset with ID: ${id}`, error) + throw error + } +} + +export async function loadAsset(id: string) { + console.log(`Loading asset with ID: ${id}`) + const hashedFileName = hashFileName(id) + const filePath = join(DIR, hashedFileName) + console.log(`Reading file from path: ${filePath}`) + + try { + const data = await readFile(filePath) + console.log(`Asset loaded successfully with ID: ${id}`) + return data + } catch (error) { + console.error(`Error loading asset with ID: ${id}`, error) + throw error + } +} \ No newline at end of file diff --git a/src/server/rooms.ts b/src/server/rooms.ts new file mode 100644 index 0000000..9a9ff61 --- /dev/null +++ b/src/server/rooms.ts @@ -0,0 +1,121 @@ +import { RoomSnapshot, TLSocketRoom } from '@tldraw/sync-core' +import { TLStoreSchema } from '@tldraw/tlschema' +import { mkdir, readFile, writeFile } from 'fs/promises' +import { join } from 'path' +import { TLSchema, TLStore, TLStoreOptions } from 'tldraw' +import { logger } from './../logger' + +// For this example we're just saving data to the local filesystem +const DIR = './.rooms' +async function readSnapshotIfExists(roomId: string) { + try { + const data = await readFile(join(DIR, roomId)) + const snapshot = JSON.parse(data.toString()) ?? undefined; + logger.info(`📥 Loaded snapshot for room: ${roomId}`); + return snapshot; + } catch (e) { + logger.warn(`⚠️ No existing snapshot found for room: ${roomId}`); + return undefined; + } +} + +async function saveSnapshot(roomId: string, snapshot: RoomSnapshot) { + try { + await mkdir(DIR, { recursive: true }); + await writeFile(join(DIR, roomId), JSON.stringify(snapshot)); + logger.info(`💾 Saved snapshot for room: ${roomId}`); + } catch (error) { + logger.error(`❌ Failed to save snapshot for room: ${roomId}`); + } +} + +// We'll keep an in-memory map of rooms and their data +interface RoomState { + room: TLSocketRoom + id: string + needsPersist: boolean + lastActivity: number + connectedSessions: Set +} + +const rooms = new Map() + +// Very simple mutex using promise chaining, to avoid race conditions +// when loading rooms. In production you probably want one mutex per room +// to avoid unnecessary blocking! +let mutex = Promise.resolve(null) + +export async function makeOrLoadRoom( + roomId: string, + schema: TLSchema, + options?: Partial +): Promise> { + mutex = mutex + .then(async () => { + if (rooms.has(roomId)) { + const roomState = await rooms.get(roomId)! + if (!roomState.room.isClosed()) { + logger.info(`🔄 Using existing room: ${roomId}`); + return null // all good + } + } + logger.info(`🔄 Loading room: ${roomId}`); + const initialSnapshot = await readSnapshotIfExists(roomId) + + const roomState: RoomState = { + needsPersist: false, + id: roomId, + lastActivity: Date.now(), + connectedSessions: new Set(), + room: new TLSocketRoom({ + initialSnapshot, + schema: schema, + onSessionRemoved(room, args) { + logger.info(`👋 Client disconnected from room: ${roomId}`); + roomState.connectedSessions.delete(args.sessionId); + roomState.lastActivity = Date.now(); + if (args.numSessionsRemaining === 0) { + logger.info(`🔒 Closing empty room: ${roomId}`); + room.close(); + } + }, + onDataChange() { + roomState.needsPersist = true; + roomState.lastActivity = Date.now(); + } + }), + } + rooms.set(roomId, roomState) + return null // all good + }) + .catch((error) => { + logger.error(`❌ Error making/loading room: ${roomId}`); + // return errors as normal values to avoid stopping the mutex chain + return error + }) + + const err = await mutex + if (err) throw err + return rooms.get(roomId)!.room +} + +// Do persistence on a regular interval. +// In production you probably want a smarter system with throttling. +setInterval(() => { + const now = Date.now(); + for (const roomState of rooms.values()) { + if (roomState.needsPersist) { + // persist room + roomState.needsPersist = false; + logger.info(`💾 Saving snapshot for room: ${roomState.id}`); + saveSnapshot(roomState.id, roomState.room.getCurrentSnapshot()); + } + if (roomState.room.isClosed()) { + logger.info(`🗑️ Deleting closed room: ${roomState.id}`); + rooms.delete(roomState.id); + } else if (now - roomState.lastActivity > 30 * 60 * 1000) { // 30 minutes inactivity + logger.info(`⏰ Closing inactive room: ${roomState.id}`); + roomState.room.close(); + } + } +}, 2000) diff --git a/src/server/schema.ts b/src/server/schema.ts new file mode 100644 index 0000000..475c3fe --- /dev/null +++ b/src/server/schema.ts @@ -0,0 +1,199 @@ +import { createTLSchema, defaultShapeSchemas, defaultBindingSchemas } from '@tldraw/tlschema' +import { ccBindingProps, ccShapeProps } from '../utils/tldraw/cc-base/cc-props' +import { ccBindingMigrations, ccShapeMigrations } from '../utils/tldraw/cc-base/cc-migrations' +import { ccGraphShapeProps } from '../utils/tldraw/cc-base/cc-graph-props' +import { ccGraphMigrations } from '../utils/tldraw/cc-base/cc-graph-migrations' + +export const server_schema_default = createTLSchema({ + shapes: { + ...defaultShapeSchemas, + 'cc-base': { + props: ccShapeProps.base, + migrations: ccShapeMigrations.base, + }, + 'cc-live-transcription': { + props: ccShapeProps.liveTranscription, + migrations: ccShapeMigrations.liveTranscription, + }, + 'cc-calendar': { + props: ccShapeProps.calendar, + migrations: ccShapeMigrations.calendar, + }, + 'cc-settings': { + props: ccShapeProps.settings, + migrations: ccShapeMigrations.settings, + }, + 'cc-slideshow': { + props: ccShapeProps.slideshow, + migrations: ccShapeMigrations.slideshow, + }, + 'cc-slide': { + props: ccShapeProps.slide, + migrations: ccShapeMigrations.slide, + }, + 'cc-web-browser': { + props: ccShapeProps.webBrowser, + migrations: ccShapeMigrations.webBrowser, + }, + 'cc-search': { + props: ccShapeProps.search, + migrations: ccShapeMigrations.search, + }, + 'cc-youtube-embed': { + props: ccShapeProps['cc-youtube-embed'], + migrations: ccShapeMigrations['cc-youtube-embed'], + }, + // Graph shapes + 'cc-user-node': { + props: ccGraphShapeProps['cc-user-node'], + migrations: ccGraphMigrations['cc-user-node'], + }, + 'cc-teacher-node': { + props: ccGraphShapeProps['cc-teacher-node'], + migrations: ccGraphMigrations['cc-teacher-node'], + }, + 'cc-student-node': { + props: ccGraphShapeProps['cc-student-node'], + migrations: ccGraphMigrations['cc-student-node'], + }, + 'cc-calendar-node': { + props: ccGraphShapeProps['cc-calendar-node'], + migrations: ccGraphMigrations['cc-calendar-node'], + }, + 'cc-calendar-year-node': { + props: ccGraphShapeProps['cc-calendar-year-node'], + migrations: ccGraphMigrations['cc-calendar-year-node'], + }, + 'cc-calendar-month-node': { + props: ccGraphShapeProps['cc-calendar-month-node'], + migrations: ccGraphMigrations['cc-calendar-month-node'], + }, + 'cc-calendar-week-node': { + props: ccGraphShapeProps['cc-calendar-week-node'], + migrations: ccGraphMigrations['cc-calendar-week-node'], + }, + 'cc-calendar-day-node': { + props: ccGraphShapeProps['cc-calendar-day-node'], + migrations: ccGraphMigrations['cc-calendar-day-node'], + }, + 'cc-calendar-time-chunk-node': { + props: ccGraphShapeProps['cc-calendar-time-chunk-node'], + migrations: ccGraphMigrations['cc-calendar-time-chunk-node'], + }, + 'cc-school-node': { + props: ccGraphShapeProps['cc-school-node'], + migrations: ccGraphMigrations['cc-school-node'], + }, + 'cc-department-node': { + props: ccGraphShapeProps['cc-department-node'], + migrations: ccGraphMigrations['cc-department-node'], + }, + 'cc-room-node': { + props: ccGraphShapeProps['cc-room-node'], + migrations: ccGraphMigrations['cc-room-node'], + }, + 'cc-subject-class-node': { + props: ccGraphShapeProps['cc-subject-class-node'], + migrations: ccGraphMigrations['cc-subject-class-node'], + }, + 'cc-pastoral-structure-node': { + props: ccGraphShapeProps['cc-pastoral-structure-node'], + migrations: ccGraphMigrations['cc-pastoral-structure-node'], + }, + 'cc-year-group-node': { + props: ccGraphShapeProps['cc-year-group-node'], + migrations: ccGraphMigrations['cc-year-group-node'], + }, + 'cc-curriculum-structure-node': { + props: ccGraphShapeProps['cc-curriculum-structure-node'], + migrations: ccGraphMigrations['cc-curriculum-structure-node'], + }, + 'cc-key-stage-node': { + props: ccGraphShapeProps['cc-key-stage-node'], + migrations: ccGraphMigrations['cc-key-stage-node'], + }, + 'cc-key-stage-syllabus-node': { + props: ccGraphShapeProps['cc-key-stage-syllabus-node'], + migrations: ccGraphMigrations['cc-key-stage-syllabus-node'], + }, + 'cc-year-group-syllabus-node': { + props: ccGraphShapeProps['cc-year-group-syllabus-node'], + migrations: ccGraphMigrations['cc-year-group-syllabus-node'], + }, + 'cc-subject-node': { + props: ccGraphShapeProps['cc-subject-node'], + migrations: ccGraphMigrations['cc-subject-node'], + }, + 'cc-topic-node': { + props: ccGraphShapeProps['cc-topic-node'], + migrations: ccGraphMigrations['cc-topic-node'], + }, + 'cc-topic-lesson-node': { + props: ccGraphShapeProps['cc-topic-lesson-node'], + migrations: ccGraphMigrations['cc-topic-lesson-node'], + }, + 'cc-learning-statement-node': { + props: ccGraphShapeProps['cc-learning-statement-node'], + migrations: ccGraphMigrations['cc-learning-statement-node'], + }, + 'cc-science-lab-node': { + props: ccGraphShapeProps['cc-science-lab-node'], + migrations: ccGraphMigrations['cc-science-lab-node'], + }, + 'cc-teacher-timetable-node': { + props: ccGraphShapeProps['cc-teacher-timetable-node'], + migrations: ccGraphMigrations['cc-teacher-timetable-node'], + }, + 'cc-timetable-lesson-node': { + props: ccGraphShapeProps['cc-timetable-lesson-node'], + migrations: ccGraphMigrations['cc-timetable-lesson-node'], + }, + 'cc-planned-lesson-node': { + props: ccGraphShapeProps['cc-planned-lesson-node'], + migrations: ccGraphMigrations['cc-planned-lesson-node'], + }, + 'cc-school-timetable-node': { + props: ccGraphShapeProps['cc-school-timetable-node'], + migrations: ccGraphMigrations['cc-school-timetable-node'], + }, + 'cc-academic-year-node': { + props: ccGraphShapeProps['cc-academic-year-node'], + migrations: ccGraphMigrations['cc-academic-year-node'], + }, + 'cc-academic-term-node': { + props: ccGraphShapeProps['cc-academic-term-node'], + migrations: ccGraphMigrations['cc-academic-term-node'], + }, + 'cc-academic-week-node': { + props: ccGraphShapeProps['cc-academic-week-node'], + migrations: ccGraphMigrations['cc-academic-week-node'], + }, + 'cc-academic-day-node': { + props: ccGraphShapeProps['cc-academic-day-node'], + migrations: ccGraphMigrations['cc-academic-day-node'], + }, + 'cc-academic-period-node': { + props: ccGraphShapeProps['cc-academic-period-node'], + migrations: ccGraphMigrations['cc-academic-period-node'], + }, + 'cc-registration-period-node': { + props: ccGraphShapeProps['cc-registration-period-node'], + migrations: ccGraphMigrations['cc-registration-period-node'], + }, + 'cc-user-teacher-timetable-node': { + props: ccGraphShapeProps['cc-user-teacher-timetable-node'], + migrations: ccGraphMigrations['cc-user-teacher-timetable-node'], + }, + 'cc-user-timetable-lesson-node': { + props: ccGraphShapeProps['cc-user-timetable-lesson-node'], + migrations: ccGraphMigrations['cc-user-timetable-lesson-node'], + }, + }, + bindings: { + ...defaultBindingSchemas, + 'cc-slide-layout': { + props: ccBindingProps['cc-slide-layout'], + migrations: ccBindingMigrations['cc-slide-layout'], + }, + }, +}) diff --git a/src/server/server.bun.ts b/src/server/server.bun.ts new file mode 100644 index 0000000..4ad9952 --- /dev/null +++ b/src/server/server.bun.ts @@ -0,0 +1,199 @@ +// External imports +import { TLSocketRoom } from '@tldraw/sync-core' +import { IRequest, Router, RouterType, cors, json } from 'itty-router' +import { Readable } from 'stream' +import { + createTLStore, +} from 'tldraw' +// Internal imports +import { loadAsset, storeAsset } from './assets' +import { makeOrLoadRoom } from './rooms' +import { unfurl } from './unfurl' +import { server_schema_default } from './schema' +import { logger } from './../logger' + +// Add debug logging for environment variables +logger.info('Environment variables:', { + PORT: process.env.PORT, + PORT_TLDRAW_SYNC: process.env.PORT_TLDRAW_SYNC, + NODE_ENV: process.env.NODE_ENV +}); + +// Be explicit about port precedence +const PORT = process.env.PORT_TLDRAW_SYNC || 5002 + +// Log the port being used +logger.info(`Using port: ${PORT}`) + +const { corsify, preflight } = cors({ origin: '*' }) + +const router: RouterType = Router() + .all('*', preflight) + + .get(`/connect/:roomId`, async (req) => { + const {roomId} = req.params + const {sessionId} = req.query + logger.info(`Connecting to room: ${roomId}, session: ${sessionId}`) + server.upgrade(req, { data: { roomId, sessionId } }) + return new Response(null, { status: 101 }) + }) + + .put(`/uploads/:id`, async (req) => { + const {id} = req.params; + logger.info(`Received upload request for ID: ${id}`); + + try { + const buffer = await req.arrayBuffer(); // Directly convert the incoming request body to an ArrayBuffer + const stream = Readable.from(Buffer.from(buffer)); // Convert ArrayBuffer to Node.js Readable Stream + + await storeAsset(id, stream); + const response = new Response(JSON.stringify({ ok: true }), { + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': '*' + }, + status: 200 + }); // TODO: Unsafe, change + logger.info(`Upload successful for ID: ${id}`); + return response; + } catch (error) { + logger.error(`Error storing asset with ID: ${id}`, error); + return new Response('Internal Server Error', { status: 500 }); + } + }) + + .get(`/uploads/:id`, async (req) => { + const id = (req.params as any).id as string + logger.info(`Received request to load asset with ID: ${id}`) + try { + const asset = await loadAsset(id) + const response = new Response(asset) + response.headers.set('Access-Control-Allow-Origin', '*') // TODO: Unsafe, change + logger.info(`Asset loaded successfully for ID: ${id}`) + return response + } catch (error) { + logger.error(`Error loading asset with ID: ${id}`, error) + return new Response('Internal Server Error', { status: 500 }) + } + }) + + .get(`/unfurl`, async (req) => { + const url = (req.query as any).url as string + logger.info(`Received unfurl request for URL: ${url}`) + try { + const data = await unfurl(url) + const response = json(data) + response.headers.set('Access-Control-Allow-Origin', '*') // TODO: Unsafe, change + logger.info(`Unfurling successful for URL: ${url}`) + return response + } catch (error) { + logger.error(`Error unfurling URL: ${url}`, error) + return new Response('Internal Server Error', { status: 500 }) + } + }) + + .all('*', (req) => { + logger.info(`Received request for unknown route: ${req.url}`); + const response = new Response('Not found', { status: 404 }); + response.headers.set('Access-Control-Allow-Origin', '*'); // TODO: Unsafe, change + return response; + }) + +const server = Bun.serve<{ room?: TLSocketRoom; sessionId: string; roomId: string }>({ + port: parseInt(PORT as string), // Ensure it's parsed as a number + fetch(req) { + try { + logger.info(`Server started on port: ${PORT}`) // Add explicit port logging + logger.info('Received request: ', req.url) + return router.fetch(req).then(corsify) + } catch (e) { + logger.error('Error handling request: ', e) + return new Response('Something went wrong', { + status: 500, + }) + } + }, + websocket: { + async open(socket) { + logger.debug(`WebSocket connection attempt for room: ${socket.data.roomId}`, { + sessionId: socket.data.sessionId + }); + try { + const { sessionId, roomId } = socket.data; + if (!sessionId || !roomId) { + logger.error('Missing sessionId or roomId in WebSocket connection data', { + sessionId, + roomId + }); + socket.close(4000, 'Missing data'); + return; + } + logger.info(`WebSocket opened for room: ${roomId}, session: ${sessionId}`); + const room = await makeOrLoadRoom(roomId, server_schema_default); + if (!room) { + logger.error('Failed to create or load room', { + roomId, + sessionId + }); + socket.close(4001, 'Failed to load room'); + return; + } + room.handleSocketConnect({ sessionId, socket }); + socket.data.room = room; + logger.info(`Successfully connected to room: ${roomId}`, { + sessionId, + roomId + }); + } catch (error) { + logger.error('Error during WebSocket open:', error); + socket.close(1011, 'Internal error'); + } + }, + async message(ws, message) { + try { + logger.debug(`WebSocket message for session: ${ws.data.sessionId}`, { + message, + roomId: ws.data.roomId + }); + if (!ws.data.room) { + logger.error('No room found for WebSocket message', { + sessionId: ws.data.sessionId, + roomId: ws.data.roomId + }); + ws.close(4002, 'No room found'); + return; + } + ws.data.room.handleSocketMessage(ws.data.sessionId, message); + } catch (error) { + logger.error('Error handling WebSocket message:', error); + ws.close(1011, 'Message handling error'); + } + }, + drain(ws) { + logger.info(`WebSocket drain for session: ${ws.data.sessionId}`, { + roomId: ws.data.roomId + }); + ws.close(); + }, + close(ws) { + logger.info(`WebSocket closed for session: ${ws.data.sessionId}`, { + roomId: ws.data.roomId + }); + if (ws.data.room) { + ws.data.room.handleSocketClose(ws.data.sessionId); + } + }, + }, +}) + +// Add explicit logging of the server configuration +logger.info('Server configuration:', { + port: server.port, + hostname: server.hostname +}) + +logger.info(`Listening for connections on URL: ${server.url}`) + +logger.info(`Listening on localhost:${PORT}`) + +logger.info(`Server: ${server}`) \ No newline at end of file diff --git a/src/server/unfurl.ts b/src/server/unfurl.ts new file mode 100644 index 0000000..b26787d --- /dev/null +++ b/src/server/unfurl.ts @@ -0,0 +1,14 @@ +import _unfurl from 'unfurl.js' + +export async function unfurl(url: string) { + const { title, description, open_graph, twitter_card, favicon } = await _unfurl.unfurl(url) + + const image = open_graph?.images?.[0]?.url || twitter_card?.images?.[0]?.url + + return { + title, + description, + image, + favicon, + } +} diff --git a/src/types/graph_node_types.ts b/src/types/graph_node_types.ts new file mode 100644 index 0000000..ded3f28 --- /dev/null +++ b/src/types/graph_node_types.ts @@ -0,0 +1,310 @@ +export interface BaseNodeInterface { + w: number; + h: number; + color: string; + __primarylabel__: string; + unique_id: string; + path: string; + created: string; + merged: string; +} + +// Users +export interface UserNodeInterface extends BaseNodeInterface +{ + user_id: string; + user_type: string; + user_name: string; + user_email: string; + worker_node_data: string; +} + +export interface DeveloperNodeInterface extends BaseNodeInterface{ + user_id: string; + user_type: string; + user_name: string; + user_email: string; +} + +export interface TeacherNodeInterface extends BaseNodeInterface{ + teacher_code: string; + teacher_name_formal: string; + teacher_email: string; + worker_db_name: string; +} + +export interface StudentNodeInterface extends BaseNodeInterface{ + student_code: string; + student_name_formal: string; + student_email: string; + worker_db_name: string; +} + +export interface StandardUserNodeInterface extends BaseNodeInterface{ + user_id: string; + user_type: string; + user_name: string; + user_email: string; +} + +export interface SchoolAdminNodeInterface extends BaseNodeInterface { + user_id: string; + user_type: string; + user_name: string; + user_email: string; +} + +// Calendar +export interface CalendarNodeInterface extends BaseNodeInterface { + name: string; + start_date: string; + end_date: string; +} + +export interface CalendarYearNodeInterface extends BaseNodeInterface { + year: string; +} + +export interface CalendarMonthNodeInterface extends BaseNodeInterface { + year: string; + month: string; + month_name: string; +} + +export interface CalendarWeekNodeInterface extends BaseNodeInterface { + start_date: string; + week_number: string; + iso_week: string; +} + +export interface CalendarDayNodeInterface extends BaseNodeInterface { + date: string; + day_of_week: string; + iso_day: string; +} + +export interface CalendarTimeChunkNodeInterface extends BaseNodeInterface { + start_time: string; + end_time: string; +} + +// School +export interface SchoolNodeInterface extends BaseNodeInterface +{ + school_name: string; + school_website: string; + school_uuid: string; +} + +export interface DepartmentNodeInterface extends BaseNodeInterface +{ + department_name: string; +} + +export interface RoomNodeInterface extends BaseNodeInterface { + room_code: string; + room_name: string; +} + +export interface SubjectClassNodeInterface extends BaseNodeInterface +{ + subject_class_code: string; + year_group: string; + subject: string; + subject_code: string; +} + +// Curriculum +export interface PastoralStructureNodeInterface extends BaseNodeInterface { + // No additional properties +} + +export interface YearGroupNodeInterface extends BaseNodeInterface { + year_group: string; + year_group_name: string; +} + +export interface CurriculumStructureNodeInterface extends BaseNodeInterface { +} + +export interface KeyStageNodeInterface extends BaseNodeInterface { + key_stage_name: string; + key_stage: string; +} + +export interface KeyStageSyllabusNodeInterface extends BaseNodeInterface { + ks_syllabus_id: string; + ks_syllabus_name: string; + ks_syllabus_key_stage: string; + ks_syllabus_subject: string; + ks_syllabus_subject_code: string; +} + +export interface YearGroupSyllabusNodeInterface extends BaseNodeInterface { + yr_syllabus_id: string; + yr_syllabus_name: string; + yr_syllabus_year_group: string; + yr_syllabus_subject: string; + yr_syllabus_subject_code: string; +} + + +export interface SubjectNodeInterface extends BaseNodeInterface { + subject_code: string; + subject_name: string; +} + + +export interface TopicNodeInterface extends BaseNodeInterface { + topic_id: string; + topic_title: string; + total_number_of_lessons_for_topic: string; + topic_type: string; + topic_assessment_type: string; + +} + +export interface TopicLessonNodeInterface extends BaseNodeInterface { + topic_lesson_id: string; + topic_lesson_title: string; + topic_lesson_type: string; + topic_lesson_length: string; + topic_lesson_suggested_activities: string; + topic_lesson_skills_learned: string; + topic_lesson_weblinks: string; +} + + +export interface LearningStatementNodeInterface extends BaseNodeInterface { + lesson_learning_statement_id: string; + lesson_learning_statement: string; + lesson_learning_statement_type: string; +} + +export interface ScienceLabNodeInterface extends BaseNodeInterface { + science_lab_id: string; + science_lab_title: string; + science_lab_summary: string; + science_lab_requirements: string; + science_lab_procedure: string; + science_lab_safety: string; + science_lab_weblinks: string; +} + + +// School Timetable +export interface SchoolTimetableNodeInterface extends BaseNodeInterface { + start_date: string; + end_date: string; +} + +export interface AcademicYearNodeInterface extends BaseNodeInterface { + year: string; +} + +export interface AcademicTermNodeInterface extends BaseNodeInterface { + term_name: string; + term_number: string; + start_date: string; + end_date: string; +} + +export interface AcademicTermBreakNodeInterface extends BaseNodeInterface { + term_break_name: string; + start_date: string; + end_date: string; +} + +export interface AcademicWeekNodeInterface extends BaseNodeInterface { + academic_week_number: string; + start_date: string; + week_type: string; +} + +export interface HolidayWeekNodeInterface extends BaseNodeInterface { + start_date: string; +} + +export interface AcademicDayNodeInterface extends BaseNodeInterface { + academic_day: string; + date: string; + day_of_week: string; + day_type: string; +} + +export interface OffTimetableDayNodeInterface extends BaseNodeInterface { + date: string; + day_of_week: string; +} + +export interface StaffDayNodeInterface extends BaseNodeInterface { + date: string; + day_of_week: string; +} + +export interface HolidayDayNodeInterface extends BaseNodeInterface { + date: string; + day_of_week: string; +} + +export interface AcademicPeriodNodeInterface extends BaseNodeInterface { + name: string; + date: string; + start_time: string; + end_time: string; + period_code: string; +} + +export interface RegistrationPeriodNodeInterface extends BaseNodeInterface { + name: string; + date: string; + start_time: string; + end_time: string; + period_code: string; +} + +export interface BreakPeriodNodeInterface extends BaseNodeInterface { + name: string; + date: string; + start_time: string; + end_time: string; +} + +export interface OffTimetablePeriodNodeInterface extends BaseNodeInterface { + name: string; + date: string; + start_time: string; + end_time: string; +} + +// Teacher timetable +export interface TeacherTimetableNodeInterface extends BaseNodeInterface { +} + +export interface TimetableLessonNodeInterface extends BaseNodeInterface { + subject_class: string; + date: string; + start_time: string; + end_time: string; + period_code: string; +} + +export interface PlannedLessonNodeInterface extends BaseNodeInterface { + date: string; + start_time: string; + end_time: string; + period_code: string; + subject_class: string; + year_group: string; + subject: string; + teacher_code: string; + planning_status: string; + topic_code?: string | null | undefined; + topic_name?: string | null | undefined; + lesson_code?: string | null | undefined; + lesson_name?: string | null | undefined; + learning_statement_codes?: string | null | undefined; + learning_statements?: string | null | undefined; + learning_resource_codes?: string | null | undefined; + learning_resources?: string | null | undefined; +} diff --git a/src/types/graph_relationship_types.ts b/src/types/graph_relationship_types.ts new file mode 100644 index 0000000..b83553f --- /dev/null +++ b/src/types/graph_relationship_types.ts @@ -0,0 +1,12 @@ +export interface BaseRelationshipInterface { + __relationshiptype__: string; + source: string; + target: string; +} + +// General +export interface GeneralRelationshipInterface extends BaseRelationshipInterface { + __relationshiptype__: string; + source: string; + target: string; +} diff --git a/src/utils/tldraw/cc-base/cc-graph-migrations.ts b/src/utils/tldraw/cc-base/cc-graph-migrations.ts new file mode 100644 index 0000000..fd0fe5c --- /dev/null +++ b/src/utils/tldraw/cc-base/cc-graph-migrations.ts @@ -0,0 +1,32 @@ +import { ccGraphShapeProps } from './cc-graph-props' +import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from 'tldraw' +import { CCGraphShape, GraphShapeType } from './cc-graph-types' + +// Helper function to create version IDs for a shape type +const createVersions = (shapeType: GraphShapeType) => { + return createShapePropsMigrationIds(shapeType, { + Initial: 1 // All shapes start at version 1 as required by TLDraw + }) +} + +// Helper function to create a migration sequence for a shape +const createMigrationSequence = (shapeType: GraphShapeType) => { + const versions = createVersions(shapeType) + return createShapePropsMigrationSequence({ + sequence: [ + { + id: versions.Initial, + up: (props: CCGraphShape['props']) => { + // Initial version - no changes needed + return props + }, + }, + ], + }) +} + +// Create migrations for all graph shapes +export const ccGraphMigrations = Object.keys(ccGraphShapeProps).reduce((acc, shapeType) => ({ + ...acc, + [shapeType]: createMigrationSequence(shapeType as GraphShapeType) +}), {} as Record>) diff --git a/src/utils/tldraw/cc-base/cc-graph-props.ts b/src/utils/tldraw/cc-base/cc-graph-props.ts new file mode 100644 index 0000000..a1ad0a3 --- /dev/null +++ b/src/utils/tldraw/cc-base/cc-graph-props.ts @@ -0,0 +1,656 @@ +import { T, TLBinding, TLShapeId } from 'tldraw' +import { baseShapeProps } from './cc-props' +import { ShapeState } from './cc-graph-types' + +// State props validation +const stateProps = T.object({ + parentId: T.optional(T.string.nullable()), + isPageChild: T.optional(T.boolean.nullable()), + hasChildren: T.optional(T.boolean.nullable()), + bindings: T.optional(T.arrayOf(T.object({})).nullable()) +}) + +// Base props for all nodes +const graphBaseProps = { + ...baseShapeProps, + __primarylabel__: T.string, + unique_id: T.string, + path: T.string, + created: T.string, + merged: T.string, + state: T.optional(stateProps.nullable()), + defaultComponent: T.optional(T.boolean.nullable()) +} + +// Props for specific node types +export const ccGraphShapeProps = { + 'cc-user-node': { + ...graphBaseProps, + user_name: T.string, + user_email: T.string, + user_type: T.string, + user_id: T.string, + worker_node_data: T.string, + }, + 'cc-teacher-node': { + ...graphBaseProps, + teacher_code: T.string, + teacher_name_formal: T.string, + teacher_email: T.string, + user_db_name: T.string, + worker_db_name: T.string, + }, + 'cc-student-node': { + ...graphBaseProps, + student_code: T.string, + student_name_formal: T.string, + student_email: T.string, + worker_db_name: T.string, + }, + 'cc-calendar-node': { + ...graphBaseProps, + name: T.string, + calendar_type: T.string, + calendar_name: T.string, + start_date: T.string, + end_date: T.string, + }, + 'cc-calendar-year-node': { + ...graphBaseProps, + year: T.string, + }, + 'cc-calendar-month-node': { + ...graphBaseProps, + year: T.string, + month: T.string, + month_name: T.string, + }, + 'cc-calendar-week-node': { + ...graphBaseProps, + start_date: T.string, + week_number: T.string, + iso_week: T.string, + }, + 'cc-calendar-day-node': { + ...graphBaseProps, + date: T.string, + day_of_week: T.string, + iso_day: T.string, + }, + 'cc-calendar-time-chunk-node': { + ...graphBaseProps, + start_time: T.string, + end_time: T.string, + }, + 'cc-school-node': { + ...graphBaseProps, + school_uuid: T.string, + school_name: T.string, + school_website: T.string, + }, + 'cc-department-node': { + ...graphBaseProps, + department_name: T.string, + }, + 'cc-room-node': { + ...graphBaseProps, + room_code: T.string, + room_name: T.string, + }, + 'cc-subject-class-node': { + ...graphBaseProps, + subject_class_code: T.string, + year_group: T.string, + subject: T.string, + subject_code: T.string, + }, + 'cc-pastoral-structure-node': { + ...graphBaseProps, + }, + 'cc-year-group-node': { + ...graphBaseProps, + year_group: T.string, + year_group_name: T.string, + }, + 'cc-curriculum-structure-node': { + ...graphBaseProps, + }, + 'cc-key-stage-node': { + ...graphBaseProps, + key_stage_name: T.string, + key_stage: T.string, + }, + 'cc-key-stage-syllabus-node': { + ...graphBaseProps, + ks_syllabus_id: T.string, + ks_syllabus_name: T.string, + ks_syllabus_key_stage: T.string, + ks_syllabus_subject: T.string, + ks_syllabus_subject_code: T.string, + }, + 'cc-year-group-syllabus-node': { + ...graphBaseProps, + yr_syllabus_id: T.string, + yr_syllabus_name: T.string, + yr_syllabus_year_group: T.string, + yr_syllabus_subject: T.string, + yr_syllabus_subject_code: T.string, + }, + 'cc-subject-node': { + ...graphBaseProps, + subject_code: T.string, + subject_name: T.string, + }, + 'cc-topic-node': { + ...graphBaseProps, + topic_id: T.string, + topic_title: T.string, + total_number_of_lessons_for_topic: T.string, + topic_type: T.string, + topic_assessment_type: T.string, + }, + 'cc-topic-lesson-node': { + ...graphBaseProps, + topic_lesson_id: T.string, + topic_lesson_title: T.string, + topic_lesson_type: T.string, + topic_lesson_length: T.string, + topic_lesson_skills_learned: T.string, + topic_lesson_suggested_activities: T.string, + topic_lesson_weblinks: T.string, + }, + 'cc-learning-statement-node': { + ...graphBaseProps, + lesson_learning_statement_id: T.string, + lesson_learning_statement: T.string, + lesson_learning_statement_type: T.string, + }, + 'cc-science-lab-node': { + ...graphBaseProps, + science_lab_id: T.string, + science_lab_title: T.string, + science_lab_summary: T.string, + science_lab_requirements: T.string, + science_lab_procedure: T.string, + science_lab_safety: T.string, + science_lab_weblinks: T.string, + }, + 'cc-teacher-timetable-node': { + ...graphBaseProps, + teacher_id: T.string, + start_date: T.string, + end_date: T.string, + }, + 'cc-timetable-lesson-node': { + ...graphBaseProps, + subject_class: T.string, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, + }, + 'cc-planned-lesson-node': { + ...graphBaseProps, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, + subject_class: T.string, + year_group: T.string, + subject: T.string, + teacher_code: T.string, + planning_status: T.string, + topic_code: T.string, + topic_name: T.string, + lesson_code: T.string, + lesson_name: T.string, + learning_statement_codes: T.string, + learning_statements: T.string, + learning_resource_codes: T.string, + learning_resources: T.string, + }, + 'cc-school-timetable-node': { + ...graphBaseProps, + start_date: T.string, + end_date: T.string, + }, + 'cc-academic-year-node': { + ...graphBaseProps, + year: T.string, + }, + 'cc-academic-term-node': { + ...graphBaseProps, + term_name: T.string, + term_number: T.string, + start_date: T.string, + end_date: T.string, + }, + 'cc-academic-week-node': { + ...graphBaseProps, + academic_week_number: T.string, + start_date: T.string, + week_type: T.string, + }, + 'cc-academic-day-node': { + ...graphBaseProps, + academic_day: T.string, + date: T.string, + day_of_week: T.string, + day_type: T.string, + }, + 'cc-academic-period-node': { + ...graphBaseProps, + name: T.string, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, + }, + 'cc-registration-period-node': { + ...graphBaseProps, + name: T.string, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, + }, + 'cc-department-structure-node': { + ...graphBaseProps, + department_structure_type: T.string, + }, + 'cc-user-teacher-timetable-node': { + ...graphBaseProps, + school_db_name: T.string, + school_timetable_id: T.string, + }, + 'cc-user-timetable-lesson-node': { + ...graphBaseProps, + subject_class: T.string, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, + school_db_name: T.string, + school_period_id: T.string, + }, +} as const + +// Default props getters +export const getDefaultBaseProps = () => ({ + w: 200 as number, + h: 200 as number, + headerColor: '#3e6589' as string, + backgroundColor: '#f0f0f0' as string, + title: 'Untitled' as string, + isLocked: false as boolean, + unique_id: '' as string, + path: '' as string, + created: '' as string, + merged: '' as string, + state: { + parentId: null as TLShapeId | null, + isPageChild: true as boolean | null, + hasChildren: null as boolean | null, + bindings: null as TLBinding[] | null + } as ShapeState | null, + defaultComponent: true as boolean | null +}) + +export const getDefaultCCUserNodeProps = () => ({ + ...getDefaultBaseProps(), + __primarylabel__: 'User', + user_name: '', + user_email: '', + user_type: '', + user_id: '', + worker_node_data: '' +}) + +export const getDefaultCCTeacherNodeProps = () => ({ + ...getDefaultBaseProps(), + __primarylabel__: 'Teacher', + teacher_code: '', + teacher_name_formal: '', + teacher_email: '', + user_db_name: '', + worker_db_name: '', +}) + +export const getDefaultCCStudentNodeProps = () => ({ + ...getDefaultBaseProps(), + __primarylabel__: 'Student', + student_code: '', + student_name_formal: '', + student_email: '', + worker_db_name: '', +}) + +export const getDefaultCCCalendarNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Calendar', + __primarylabel__: 'Calendar', + name: '', + calendar_type: '', + calendar_name: '', + start_date: '', + end_date: '', +}) + +export const getDefaultCCCalendarYearNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Calendar Year', + __primarylabel__: 'Calendar Year', + year: '', +}) + +export const getDefaultCCCalendarMonthNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Calendar Month', + __primarylabel__: 'Calendar Month', + year: '', + month: '', + month_name: '', +}) + +export const getDefaultCCCalendarWeekNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Calendar Week', + __primarylabel__: 'Calendar Week', + start_date: '', + week_number: '', + iso_week: '', +}) + +export const getDefaultCCCalendarDayNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Calendar Day', + __primarylabel__: 'Calendar Day', + date: '', + day_of_week: '', + iso_day: '', +}) + +export const getDefaultCCCalendarTimeChunkNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Calendar Time Chunk', + __primarylabel__: 'Calendar Time Chunk', + start_time: '', + end_time: '', +}) + +export const getDefaultCCSchoolNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'School', + __primarylabel__: 'School', + school_uuid: '', + school_name: '', + school_website: '', +}) + +export const getDefaultCCDepartmentNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Department', + __primarylabel__: 'Department', + department_name: '', +}) + +export const getDefaultCCRoomNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Room', + __primarylabel__: 'Room', + room_code: '', + room_name: '', +}) + +export const getDefaultCCSubjectClassNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Subject Class', + __primarylabel__: 'Subject Class', + subject_class_code: '', + year_group: '', + subject: '', + subject_code: '', +}) + +export const getDefaultCCPastoralStructureNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Pastoral Structure', + __primarylabel__: 'Pastoral Structure', + pastoral_structure_type: '', +}) + +export const getDefaultCCYearGroupNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Year Group', + __primarylabel__: 'Year Group', + year_group: '', + year_group_name: '', +}) + +export const getDefaultCCCurriculumStructureNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Curriculum Structure', + __primarylabel__: 'Curriculum Structure', + curriculum_structure_type: '', +}) + +export const getDefaultCCKeyStageNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Key Stage', + __primarylabel__: 'Key Stage', + key_stage_name: '', + key_stage: '', +}) + +export const getDefaultCCKeyStageSyllabusNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Key Stage Syllabus', + __primarylabel__: 'Key Stage Syllabus', + ks_syllabus_id: '', + ks_syllabus_name: '', + ks_syllabus_key_stage: '', + ks_syllabus_subject: '', + ks_syllabus_subject_code: '', +}) + +export const getDefaultCCYearGroupSyllabusNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Year Group Syllabus', + __primarylabel__: 'Year Group Syllabus', + yr_syllabus_id: '', + yr_syllabus_name: '', + yr_syllabus_year_group: '', + yr_syllabus_subject: '', + yr_syllabus_subject_code: '', +}) + +export const getDefaultCCSubjectNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Subject', + __primarylabel__: 'Subject', + subject_code: '', + subject_name: '', +}) + +export const getDefaultCCTopicNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Topic', + __primarylabel__: 'Topic', + topic_id: '', + topic_title: '', + total_number_of_lessons_for_topic: '', + topic_type: '', + topic_assessment_type: '', +}) + +export const getDefaultCCTopicLessonNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Topic Lesson', + __primarylabel__: 'Topic Lesson', + topic_lesson_id: '', + topic_lesson_title: '', + topic_lesson_type: '', + topic_lesson_length: '', + topic_lesson_skills_learned: '', + topic_lesson_suggested_activities: '', + topic_lesson_weblinks: '', +}) + +export const getDefaultCCLearningStatementNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Learning Statement', + __primarylabel__: 'Learning Statement', + lesson_learning_statement_id: '', + lesson_learning_statement: '', + lesson_learning_statement_type: '', +}) + +export const getDefaultCCScienceLabNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Science Lab', + __primarylabel__: 'Science Lab', + science_lab_id: '', + science_lab_title: '', + science_lab_summary: '', + science_lab_requirements: '', + science_lab_procedure: '', + science_lab_safety: '', + science_lab_weblinks: '', +}) + +export const getDefaultCCTeacherTimetableNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Teacher Timetable', + __primarylabel__: 'Teacher Timetable', + teacher_id: '', + start_date: '', + end_date: '', +}) + +export const getDefaultCCTimetableLessonNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Timetable Lesson', + __primarylabel__: 'Timetable Lesson', + subject_class: '', + date: '', + start_time: '', + end_time: '', + period_code: '', +}) + +export const getDefaultCCPlannedLessonNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Planned Lesson', + __primarylabel__: 'Planned Lesson', + date: '', + start_time: '', + end_time: '', + period_code: '', + subject_class: '', + year_group: '', + subject: '', + teacher_code: '', + planning_status: '', + topic_code: '', + topic_name: '', + lesson_code: '', + lesson_name: '', + learning_statement_codes: '', + learning_statements: '', + learning_resource_codes: '', + learning_resources: '', +}) + +export const getDefaultCCSchoolTimetableNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'School Timetable', + __primarylabel__: 'School Timetable', + start_date: '', + end_date: '', +}) + +export const getDefaultCCAcademicYearNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Academic Year', + __primarylabel__: 'Academic Year', + year: '', +}) + +export const getDefaultCCAcademicTermNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Academic Term', + __primarylabel__: 'Academic Term', + term_name: '', + term_number: '', + start_date: '', + end_date: '', +}) + +export const getDefaultCCAcademicWeekNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Academic Week', + __primarylabel__: 'Academic Week', + academic_week_number: '', + start_date: '', + week_type: '', +}) + +export const getDefaultCCAcademicDayNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Academic Day', + __primarylabel__: 'Academic Day', + academic_day: '', + date: '', + day_of_week: '', + day_type: '', +}) + +export const getDefaultCCAcademicPeriodNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Academic Period', + __primarylabel__: 'Academic Period', + name: '', + date: '', + start_time: '', + end_time: '', + period_code: '', +}) + +export const getDefaultCCRegistrationPeriodNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Registration Period', + __primarylabel__: 'Registration Period', + name: '', + date: '', + start_time: '', + end_time: '', + period_code: '', +}) + +export const getDefaultCCDepartmentStructureNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'Department Structure', + __primarylabel__: 'DepartmentStructure', + department_structure_type: '', +}) + +export const getDefaultCCUserTeacherTimetableNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'User Teacher Timetable', + __primarylabel__: 'UserTeacherTimetable', + school_db_name: '', + school_timetable_id: '', +}) + +export const getDefaultCCUserTimetableLessonNodeProps = () => ({ + ...getDefaultBaseProps(), + title: 'User Timetable Lesson', + __primarylabel__: 'UserTimetableLesson', + subject_class: '', + date: '', + start_time: '', + end_time: '', + period_code: '', + school_db_name: '', + school_period_id: '', +}) diff --git a/src/utils/tldraw/cc-base/cc-graph-styles.ts b/src/utils/tldraw/cc-base/cc-graph-styles.ts new file mode 100644 index 0000000..2f2e6b7 --- /dev/null +++ b/src/utils/tldraw/cc-base/cc-graph-styles.ts @@ -0,0 +1,169 @@ +// Shared styles for all nodes +export const SHARED_NODE_STYLES = { + container: { + display: 'flex', + flexDirection: 'column' as const, + padding: '8px', + gap: '4px', + backgroundColor: 'var(--color-muted)', + color: 'var(--color-text)', + borderRadius: '4px', + minWidth: '150px', + }, + header: { + fontSize: '14px', + fontWeight: 'bold' as const, + marginBottom: '4px', + color: 'var(--color-text)', + }, + property: { + label: { + fontSize: '12px', + color: 'var(--color-text-2)', + marginRight: '4px', + fontWeight: '500' as const, + }, + value: { + fontSize: '12px', + color: 'var(--color-text)', + fontWeight: '200' as const, + }, + wrapper: { + display: 'flex', + alignItems: 'center', + gap: '4px', + }, + }, + error: { + container: { + padding: '8px', + backgroundColor: 'var(--color-error)', + color: 'white', + borderRadius: '4px', + fontSize: '12px', + }, + message: { + fontWeight: 'bold' as const, + }, + details: { + marginTop: '4px', + opacity: 0.8, + } + }, + defaultComponent: { + container: { + display: 'flex', + gap: '8px', + marginBottom: '8px', + }, + button: { + padding: '4px 8px', + fontSize: '12px', + borderRadius: '4px', + backgroundColor: 'var(--color-muted-2)', + color: 'var(--color-text)', + border: 'none', + cursor: 'pointer', + '&:hover': { + backgroundColor: 'var(--color-muted-3)', + } + } + } +} as const + +// Color themes for different node types +export const NODE_THEMES = { + calendar: { + headerColor: '#0066cc', + backgroundColor: '#e6f0ff', + }, + academic: { + headerColor: '#008000', + backgroundColor: '#e6ffe6', + }, + curriculum: { + headerColor: '#ff8c00', + backgroundColor: '#fff3e6', + }, + pastoral: { + headerColor: '#8a2be2', + backgroundColor: '#f5e6ff', + }, + people: { + headerColor: '#cc0000', + backgroundColor: '#ffe6e6', + }, + resource: { + headerColor: '#cccc00', + backgroundColor: '#fffff0', + }, +} as const + +// Node type to theme mapping +export const NODE_TYPE_THEMES: Record = { + // Calendar nodes + 'cc-calendar-node': 'calendar', + 'cc-calendar-year-node': 'calendar', + 'cc-calendar-month-node': 'calendar', + 'cc-calendar-week-node': 'calendar', + 'cc-calendar-day-node': 'calendar', + 'cc-calendar-time-chunk-node': 'calendar', + + // Academic nodes + 'cc-academic-year-node': 'academic', + 'cc-academic-term-node': 'academic', + 'cc-academic-week-node': 'academic', + 'cc-academic-day-node': 'academic', + 'cc-academic-period-node': 'academic', + 'cc-registration-period-node': 'academic', + 'cc-timetable-lesson-node': 'academic', + 'cc-planned-lesson-node': 'academic', + 'cc-school-timetable-node': 'academic', + 'cc-user-teacher-timetable-node': 'academic', + 'cc-user-timetable-lesson-node': 'academic', + + // Curriculum nodes + 'cc-curriculum-structure-node': 'curriculum', + 'cc-key-stage-node': 'curriculum', + 'cc-key-stage-syllabus-node': 'curriculum', + + 'cc-year-group-syllabus-node': 'curriculum', + 'cc-subject-node': 'curriculum', + 'cc-topic-node': 'curriculum', + 'cc-topic-lesson-node': 'curriculum', + 'cc-learning-statement-node': 'curriculum', + 'cc-science-lab-node': 'curriculum', + + // Pastoral nodes + 'cc-pastoral-structure-node': 'pastoral', + 'cc-year-group-node': 'pastoral', + + // People nodes + 'cc-user-node': 'people', + 'cc-teacher-node': 'people', + 'cc-student-node': 'people', + + // Resource nodes + 'cc-school-node': 'resource', + 'cc-department-node': 'resource', + 'cc-room-node': 'resource', + 'cc-subject-class-node': 'resource', +} as const + +// Helper function to get theme for a node type +export const getNodeTheme = (nodeType: string) => { + const themeKey = NODE_TYPE_THEMES[nodeType] + return themeKey ? NODE_THEMES[themeKey] : NODE_THEMES.resource // Default to resource theme +} + +// Helper function to get styles for a specific node type +export const getNodeStyles = (nodeType: string) => { + const theme = getNodeTheme(nodeType) + return { + ...SHARED_NODE_STYLES, + container: { + ...SHARED_NODE_STYLES.container, + backgroundColor: theme.backgroundColor, + }, + } +} \ No newline at end of file diff --git a/src/utils/tldraw/cc-base/cc-graph-types.ts b/src/utils/tldraw/cc-base/cc-graph-types.ts new file mode 100644 index 0000000..64a488d --- /dev/null +++ b/src/utils/tldraw/cc-base/cc-graph-types.ts @@ -0,0 +1,387 @@ +import { TLBinding, TLBaseShape, TLShapeId } from 'tldraw' +import { CCBaseShape } from './cc-types' +import { CCBaseProps } from './cc-props' +import { ccGraphShapeProps } from './cc-graph-props' + +// Export type for graph shape types +export type GraphShapeType = keyof typeof ccGraphShapeProps + +export interface ShapeState { + parentId: TLShapeId | null + isPageChild: boolean | null + hasChildren: boolean | null + bindings: TLBinding[] | null +} + +export type CCGraphShapeProps = CCBaseProps & { + __primarylabel__: string + unique_id: string + path: string + created: string + merged: string + state: ShapeState | null | undefined + defaultComponent: boolean | null +} + +// Define the base shape type for graph shapes +export type CCGraphShape = CCBaseShape & TLBaseShape + +export type CCUserNodeProps = CCGraphShapeProps & { + user_name: string + user_email: string + user_type: string + user_id: string + worker_node_data: string +} + +export type CCTeacherNodeProps = CCGraphShapeProps & { + teacher_code: string + teacher_name_formal: string + teacher_email: string + user_db_name: string + worker_db_name: string +} + +export type CCStudentNodeProps = CCGraphShapeProps & { + student_name_formal: string + student_code: string + student_email: string +} + +export type CCCalendarNodeProps = CCGraphShapeProps & { + title: string + name: string + calendar_type: string + calendar_name: string + start_date: string + end_date: string +} + +export type CCCalendarYearNodeProps = CCGraphShapeProps & { + year: string +} + +export type CCCalendarMonthNodeProps = CCGraphShapeProps & { + year: string + month: string + month_name: string +} + +export type CCCalendarWeekNodeProps = CCGraphShapeProps & { + start_date: string + week_number: string + iso_week: string +} + +export type CCCalendarDayNodeProps = CCGraphShapeProps & { + date: string + day_of_week: string + iso_day: string +} + +export type CCCalendarTimeChunkNodeProps = CCGraphShapeProps & { + start_time: string + end_time: string +} + +export type CCSchoolNodeProps = CCGraphShapeProps & { + school_uuid: string + school_name: string + school_website: string +} + +export type CCDepartmentNodeProps = CCGraphShapeProps & { + department_name: string +} + +export type CCRoomNodeProps = CCGraphShapeProps & { + room_code: string + room_name: string +} + +export type CCSubjectClassNodeProps = CCGraphShapeProps & { + subject_class_code: string + year_group: string + subject: string + subject_code: string +} + +export type CCPastoralStructureNodeProps = CCGraphShapeProps & { + pastoral_structure_type: string +} + +export type CCYearGroupNodeProps = CCGraphShapeProps & { + year_group: string + year_group_name: string +} + +export type CCCurriculumStructureNodeProps = CCGraphShapeProps & { + curriculum_structure_type: string +} + +export type CCKeyStageNodeProps = CCGraphShapeProps & { + key_stage_name: string + key_stage: string +} + +export type CCKeyStageSyllabusNodeProps = CCGraphShapeProps & { + ks_syllabus_id: string + ks_syllabus_name: string + ks_syllabus_key_stage: string + ks_syllabus_subject: string + ks_syllabus_subject_code: string +} + +export type CCYearGroupSyllabusNodeProps = CCGraphShapeProps & { + yr_syllabus_id: string + yr_syllabus_name: string + yr_syllabus_year_group: string + yr_syllabus_subject: string + yr_syllabus_subject_code: string +} + +export type CCSubjectNodeProps = CCGraphShapeProps & { + subject_code: string + subject_name: string +} + +export type CCTopicNodeProps = CCGraphShapeProps & { + topic_id: string + topic_title: string + total_number_of_lessons_for_topic: string + topic_type: string + topic_assessment_type: string +} + +export type CCTopicLessonNodeProps = CCGraphShapeProps & { + topic_lesson_id: string + topic_lesson_title: string + topic_lesson_type: string + topic_lesson_length: string + topic_lesson_skills_learned: string + topic_lesson_suggested_activities: string + topic_lesson_weblinks: string +} + +export type CCLearningStatementNodeProps = CCGraphShapeProps & { + lesson_learning_statement_id: string + lesson_learning_statement: string + lesson_learning_statement_type: string +} + +export type CCScienceLabNodeProps = CCGraphShapeProps & { + science_lab_id: string + science_lab_title: string + science_lab_summary: string + science_lab_requirements: string + science_lab_procedure: string + science_lab_safety: string + science_lab_weblinks: string +} + +export type CCTeacherTimetableNodeProps = CCGraphShapeProps & { + teacher_id: string + start_date: string + end_date: string +} + +export type CCTimetableLessonNodeProps = CCGraphShapeProps & { + subject_class: string + date: string + start_time: string + end_time: string + period_code: string +} + +export type CCPlannedLessonNodeProps = CCGraphShapeProps & { + date: string + start_time: string + end_time: string + period_code: string + subject_class: string + year_group: string + subject: string + teacher_code: string + planning_status: string + topic_code: string + topic_name: string + lesson_code: string + lesson_name: string + learning_statement_codes: string + learning_statements: string + learning_resource_codes: string + learning_resources: string +} + +export type CCSchoolTimetableNodeProps = CCGraphShapeProps & { + start_date: string + end_date: string +} + +export type CCAcademicYearNodeProps = CCGraphShapeProps & { + year: string +} + +export type CCAcademicTermNodeProps = CCGraphShapeProps & { + term_name: string + term_number: string + start_date: string + end_date: string +} + +export type CCAcademicWeekNodeProps = CCGraphShapeProps & { + academic_week_number: string + start_date: string + week_type: string +} + +export type CCAcademicDayNodeProps = CCGraphShapeProps & { + academic_day: string + date: string + day_of_week: string + day_type: string +} + +export type CCAcademicPeriodNodeProps = CCGraphShapeProps & { + name: string + date: string + start_time: string + end_time: string + period_code: string +} + +export type CCRegistrationPeriodNodeProps = CCGraphShapeProps & { + name: string + date: string + start_time: string + end_time: string + period_code: string +} + +export type CCDepartmentStructureNodeProps = CCGraphShapeProps & { + department_structure_type: string +} + +export type CCUserTeacherTimetableNodeProps = CCGraphShapeProps & { + school_db_name: string + school_timetable_id: string +} + +export type CCUserTimetableLessonNodeProps = CCGraphShapeProps & { + subject_class: string + date: string + start_time: string + end_time: string + period_code: string + school_db_name: string + school_period_id: string +} + +// Define a type-safe mapping of node types to their configurations +export type CCNodeTypes = { + User: { props: CCUserNodeProps } + Developer: { props: CCUserNodeProps } + Teacher: { props: CCTeacherNodeProps } + Student: { props: CCStudentNodeProps } + Calendar: { props: CCCalendarNodeProps } + TeacherTimetable: { props: CCTeacherTimetableNodeProps } + TimetableLesson: { props: CCTimetableLessonNodeProps } + PlannedLesson: { props: CCPlannedLessonNodeProps } + School: { props: CCSchoolNodeProps } + CalendarYear: { props: CCCalendarYearNodeProps } + CalendarMonth: { props: CCCalendarMonthNodeProps } + CalendarWeek: { props: CCCalendarWeekNodeProps } + CalendarDay: { props: CCCalendarDayNodeProps } + CalendarTimeChunk: { props: CCCalendarTimeChunkNodeProps } + ScienceLab: { props: CCScienceLabNodeProps } + KeyStageSyllabus: { props: CCKeyStageSyllabusNodeProps } + YearGroupSyllabus: { props: CCYearGroupSyllabusNodeProps } + CurriculumStructure: { props: CCCurriculumStructureNodeProps } + Topic: { props: CCTopicNodeProps } + TopicLesson: { props: CCTopicLessonNodeProps } + LearningStatement: { props: CCLearningStatementNodeProps } + SchoolTimetable: { props: CCSchoolTimetableNodeProps } + AcademicYear: { props: CCAcademicYearNodeProps } + AcademicTerm: { props: CCAcademicTermNodeProps } + AcademicWeek: { props: CCAcademicWeekNodeProps } + AcademicDay: { props: CCAcademicDayNodeProps } + AcademicPeriod: { props: CCAcademicPeriodNodeProps } + RegistrationPeriod: { props: CCRegistrationPeriodNodeProps } + PastoralStructure: { props: CCPastoralStructureNodeProps } + KeyStage: { props: CCKeyStageNodeProps } + Department: { props: CCDepartmentNodeProps } + Room: { props: CCRoomNodeProps } + SubjectClass: { props: CCSubjectClassNodeProps } + DepartmentStructure: { props: CCDepartmentStructureNodeProps } + UserTeacherTimetable: { props: CCUserTeacherTimetableNodeProps } + UserTimetableLesson: { props: CCUserTimetableLessonNodeProps } +} + +// Helper function to get shape type from node type +export const getShapeType = (nodeType: keyof CCNodeTypes): string => { + return `cc-${nodeType.replace(/([A-Z])/g, '-$1').toLowerCase().substring(1)}-node`; +} + +// Helper function to get allowed props from node type +export const getAllowedProps = (): string[] => { + return ['__primarylabel__', 'unique_id']; +} + +// Helper function to get node configuration +export const getNodeConfig = (nodeType: T) => { + const shapeType = getShapeType(nodeType); + return { + shapeType, + allowedProps: getAllowedProps() + }; +} + +// Helper function to check if a string is a valid node type +export const isValidNodeType = (type: string): type is keyof CCNodeTypes => { + return type in { + User: true, + Developer: true, + Teacher: true, + Student: true, + Calendar: true, + TeacherTimetable: true, + TimetableLesson: true, + PlannedLesson: true, + School: true, + CalendarYear: true, + CalendarMonth: true, + CalendarWeek: true, + CalendarDay: true, + CalendarTimeChunk: true, + ScienceLab: true, + KeyStageSyllabus: true, + YearGroupSyllabus: true, + CurriculumStructure: true, + Topic: true, + TopicLesson: true, + LearningStatement: true, + SchoolTimetable: true, + AcademicYear: true, + AcademicTerm: true, + AcademicWeek: true, + AcademicDay: true, + AcademicPeriod: true, + RegistrationPeriod: true, + PastoralStructure: true, + KeyStage: true, + Department: true, + Room: true, + SubjectClass: true, + DepartmentStructure: true, + UserTeacherTimetable: true, + UserTimetableLesson: true, + }; +} \ No newline at end of file diff --git a/src/utils/tldraw/cc-base/cc-migrations.ts b/src/utils/tldraw/cc-base/cc-migrations.ts new file mode 100644 index 0000000..06d7aab --- /dev/null +++ b/src/utils/tldraw/cc-base/cc-migrations.ts @@ -0,0 +1,246 @@ +import { TLRecord, TLShape } from 'tldraw' +import { getDefaultCCBaseProps, getDefaultCCCalendarProps, getDefaultCCLiveTranscriptionProps, getDefaultCCSettingsProps, getDefaultCCSlideProps, getDefaultCCSlideShowProps, getDefaultCCSlideLayoutBindingProps, getDefaultCCYoutubeEmbedProps, getDefaultCCSearchProps, getDefaultCCWebBrowserProps } from './cc-props' + +// Export both shape and binding migrations +export const ccBindingMigrations = { + 'cc-slide-layout': { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'binding') return record + if (record.type !== 'cc-slide-layout') return record + return { + ...record, + props: { + ...getDefaultCCSlideLayoutBindingProps(), + ...record.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, +} + +export const ccShapeMigrations = { + base: { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-base') return record + return { + ...shape, + props: { + ...getDefaultCCBaseProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, + + calendar: { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-calendar') return record + return { + ...shape, + props: { + ...getDefaultCCCalendarProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, + + liveTranscription: { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-live-transcription') return record + return { + ...shape, + props: { + ...getDefaultCCLiveTranscriptionProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, + + settings: { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-settings') return record + return { + ...shape, + props: { + ...getDefaultCCSettingsProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, + + slideshow: { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-slideshow') return record + return { + ...shape, + props: { + ...getDefaultCCSlideShowProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, + + slide: { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-slide') return record + return { + ...shape, + props: { + ...getDefaultCCSlideProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, + + 'cc-youtube-embed': { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-youtube-embed') return record + return { + ...shape, + props: { + ...getDefaultCCYoutubeEmbedProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, + + search: { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-search') return record + return { + ...shape, + props: { + ...getDefaultCCSearchProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, + + webBrowser: { + firstVersion: 1, + currentVersion: 1, + migrators: { + 1: { + up: (record: TLRecord) => { + if (record.typeName !== 'shape') return record + const shape = record as TLShape + if (shape.type !== 'cc-web-browser') return record + return { + ...shape, + props: { + ...getDefaultCCWebBrowserProps(), + ...shape.props, + }, + } + }, + down: (record: TLRecord) => { + return record + }, + }, + }, + }, +} \ No newline at end of file diff --git a/src/utils/tldraw/cc-base/cc-props.ts b/src/utils/tldraw/cc-base/cc-props.ts new file mode 100644 index 0000000..0168427 --- /dev/null +++ b/src/utils/tldraw/cc-base/cc-props.ts @@ -0,0 +1,262 @@ +import { T } from 'tldraw' +import { CC_BASE_STYLE_CONSTANTS, CC_SLIDESHOW_STYLE_CONSTANTS } from './cc-styles' + +export interface CCBaseProps { + title: string + w: number + h: number + headerColor: string + backgroundColor: string + isLocked: boolean +} + +// Create a constant for the base props validation +export const baseShapeProps = { + title: T.string, + w: T.number, + h: T.number, + headerColor: T.string, + backgroundColor: T.string, + isLocked: T.boolean, +} + +export const ccShapeProps = { + base: baseShapeProps, + + calendar: { + ...baseShapeProps, + date: T.string, + selectedDate: T.string, + view: T.string, + events: T.arrayOf(T.object({ + id: T.string, + title: T.string, + start: T.string, + end: T.string, + groupId: T.string.optional(), + extendedProps: T.object({ + subjectClass: T.string, + color: T.string, + periodCode: T.string, + path: T.string.optional() + }) + })), + }, + + liveTranscription: { + ...baseShapeProps, + isRecording: T.boolean, + segments: T.arrayOf(T.object({ + id: T.string, + text: T.string, + completed: T.boolean, + start: T.string, + end: T.string, + })), + currentSegment: T.object({ + id: T.string, + text: T.string, + completed: T.boolean, + start: T.string, + end: T.string, + }).optional(), + lastProcessedSegment: T.string.optional(), + }, + + settings: { + ...baseShapeProps, + userEmail: T.string, + userRole: T.string, + isTeacher: T.boolean, + }, + + slideshow: { + ...baseShapeProps, + currentSlideIndex: T.number, + slidePattern: T.string, + numSlides: T.number, + slides: T.arrayOf(T.object({ + imageData: T.string, + meta: T.object({ + text: T.string, + format: T.string, + }), + })).optional(), + }, + + slide: { + ...baseShapeProps, + imageData: T.string, + meta: T.object({ + text: T.string, + format: T.string, + }), + }, + + 'cc-youtube-embed': { + ...baseShapeProps, + video_url: T.string, + transcript: T.arrayOf(T.object({ + start: T.number, + duration: T.number, + text: T.string, + })), + transcriptVisible: T.boolean, + }, + + search: { + ...baseShapeProps, + query: T.string, + results: T.arrayOf(T.object({ + title: T.string, + url: T.string, + content: T.string, + })), + isSearching: T.boolean, + }, + + webBrowser: { + ...baseShapeProps, + url: T.string, + history: T.arrayOf(T.string), + currentHistoryIndex: T.number, + isLoading: T.boolean, + }, +} + +export const ccBindingProps = { + 'cc-slide-layout': { + isMovingWithParent: T.boolean.optional(), + placeholder: T.boolean.optional(), + index: T.string + }, +} + +export const getDefaultCCBaseProps = () => ({ + title: 'Base Shape', + w: 100, + h: 100, + headerColor: '#3e6589', + backgroundColor: '#ffffff', + isLocked: false, +}) + +export const getDefaultCCCalendarProps = () => ({ + ...getDefaultCCBaseProps(), + date: new Date().toISOString(), + selectedDate: new Date().toISOString(), + view: 'timeGridWeek', + events: [], +}) + +export const getDefaultCCLiveTranscriptionProps = () => ({ + ...getDefaultCCBaseProps(), + isRecording: false, + segments: [], + currentSegment: undefined, + lastProcessedSegment: undefined, +}) + +export const getDefaultCCSettingsProps = () => ({ + ...getDefaultCCBaseProps(), + userEmail: '', + userRole: '', + isTeacher: false, +}) + +export function getDefaultCCSlideShowProps() { + // Base 16:9 ratio dimensions + const baseWidth = 1280 + const baseHeight = 720 + // Add header height and spacing + const totalHeight = baseHeight + + CC_SLIDESHOW_STYLE_CONSTANTS.SLIDE_HEADER_HEIGHT + // Slideshow's own header + CC_SLIDESHOW_STYLE_CONSTANTS.SLIDE_SPACING * 2 + // Top and bottom spacing + CC_SLIDESHOW_STYLE_CONSTANTS.SLIDE_CONTENT_PADDING // Extra padding for content + + return { + title: 'Slideshow', + w: baseWidth, + h: totalHeight, + headerColor: '#3e6589', + backgroundColor: '#0f0f0f', + isLocked: false, + currentSlideIndex: 0, + slidePattern: 'horizontal', + numSlides: 3, + slides: [], + } +} + +export function getDefaultCCSlideProps() { + // Base 16:9 ratio dimensions + const baseWidth = 1280 + const baseHeight = 720 + // Add header height + const totalHeight = baseHeight + CC_BASE_STYLE_CONSTANTS.HEADER.height + + return { + title: 'Slide', + w: baseWidth, + h: totalHeight, + headerColor: '#3e6589', + backgroundColor: '#0f0f0f', + isLocked: false, + imageData: '', + meta: { + text: '', + format: 'markdown' + } + } +} + +export function getDefaultCCSlideLayoutBindingProps() { + return { + isMovingWithParent: false, + placeholder: false, + index: '0', + } +} + +export function getDefaultCCYoutubeEmbedProps() { + const videoHeight = 450 + const totalHeight = videoHeight + CC_BASE_STYLE_CONSTANTS.HEADER.height + (CC_BASE_STYLE_CONSTANTS.CONTENT.padding * 2) + + return { + ...getDefaultCCBaseProps(), + title: 'YouTube Video', + w: 800, + h: totalHeight, + headerColor: '#ff0000', + backgroundColor: '#0f0f0f', + isLocked: false, + video_url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + transcript: [], + transcriptVisible: false, + } +} + +export const getDefaultCCSearchProps = () => ({ + ...getDefaultCCBaseProps(), + w: 400, + h: 500, + title: 'Search', + headerColor: '#1a73e8', + backgroundColor: '#ffffff', + query: '', + results: [], + isSearching: false, +}) + +export const getDefaultCCWebBrowserProps = () => ({ + ...getDefaultCCBaseProps(), + title: 'Web Browser', + w: 800, + h: 600, + headerColor: '#1a73e8', + backgroundColor: '#ffffff', + url: '', + history: [], + currentHistoryIndex: -1, + isLoading: false, +}) diff --git a/src/utils/tldraw/cc-base/cc-styles.ts b/src/utils/tldraw/cc-base/cc-styles.ts new file mode 100644 index 0000000..c117dc2 --- /dev/null +++ b/src/utils/tldraw/cc-base/cc-styles.ts @@ -0,0 +1,118 @@ +// Style constants used by all CC shapes +export const CC_BASE_STYLE_CONSTANTS = { + FONT_FAMILY: 'Inter, sans-serif', + FONT_SIZES: { + small: 12, + medium: 14, + large: 16, + }, + // Container styles + CONTAINER: { + borderRadius: '4px', + borderWidth: '2px', + borderColor: '#e2e8f0', + boxShadow: '0 2px 4px var(--color-muted-1)', + }, + HEADER: { + height: 32, + padding: 8, + borderRadius: 4, + }, + CONTENT: { + padding: 16, + borderRadius: 8, + borderWidth: 2, + backgroundColor: 'white', + }, + HANDLE: { + width: 8, + }, + COLORS: { + primary: '#3e6589', + primary_dark: '#2e4a69', + secondary: '#718096', + secondary_dark: '#5a687a', + background: '#ffffff', + border: '#e2e8f0', + text: '#1a202c', + textLight: '#718096', + }, + // Minimum dimensions + MIN_DIMENSIONS: { + width: 100, + height: 100, + }, +} as const + +// Calendar specific styles +export const CC_CALENDAR_STYLE_CONSTANTS = { + // Common button styles + COMMON_BUTTON: { + border: 'none', + borderRadius: '5px', + padding: '0.4em 1em', + fontSize: '0.95em', + textTransform: 'uppercase', + letterSpacing: '0.05em', + cursor: 'pointer', + transition: 'background-color 0.3s ease', + boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)', + }, + + // Application button styles + APPLICATION_BUTTON: { + backgroundColor: '#4f80ff', + color: '#fff', + }, + + // Option button styles + OPTION_BUTTON: { + backgroundColor: '#f0f4f9', + color: '#2c3e50', + border: '1px solid #ddd', + }, + + // Calendar event styles + EVENT: { + mainFrame: { + backgroundColor: 'transparent', + padding: '0px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + minHeight: '100%', + borderRadius: '4px', + }, + title: { + fontSize: '1.1em', + fontWeight: 'normal', + textAlign: 'center', + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + opacity: 1, + padding: '0px 0px', + width: '100%', + letterSpacing: '0.02em', + margin: '0px 0px', + } + } +} as const + +// Slideshow specific styles +export const CC_SLIDESHOW_STYLE_CONSTANTS = { + DEFAULT_SLIDE_WIDTH: 800, + DEFAULT_SLIDE_HEIGHT: 600, + SLIDE_HEADER_HEIGHT: 40, + SLIDE_HEADER_PADDING: 8, + SLIDE_CONTENT_PADDING: 16, + SLIDE_BORDER_RADIUS: 4, + SLIDE_BORDER_WIDTH: 1, + SLIDE_SPACING: 16, + SLIDE_COLORS: { + background: '#ffffff', + border: '#e2e8f0', + text: '#ffffff', + secondary: '#718096', + }, +} as const \ No newline at end of file diff --git a/src/utils/tldraw/cc-base/cc-types.ts b/src/utils/tldraw/cc-base/cc-types.ts new file mode 100644 index 0000000..59d135e --- /dev/null +++ b/src/utils/tldraw/cc-base/cc-types.ts @@ -0,0 +1,4 @@ +import { TLBaseShape } from 'tldraw' +import { CCBaseProps } from './cc-props' + +export interface CCBaseShape extends TLBaseShape {} \ No newline at end of file diff --git a/src/utils/tldraw/graph/baseNodeShapeUtil.tsx b/src/utils/tldraw/graph/baseNodeShapeUtil.tsx new file mode 100644 index 0000000..9bb8e87 --- /dev/null +++ b/src/utils/tldraw/graph/baseNodeShapeUtil.tsx @@ -0,0 +1,411 @@ +import { + Editor, + HTMLContainer, + Rectangle2d, + ShapeUtil, + TLDefaultColorTheme, + getDefaultColorTheme, + createShapeId +} from 'tldraw' +import { + AllNodeShapes +} from './graph-shape-types' +import { + AllRelationshipShapes +} from './graph-relationship-types' +import { getNodeComponent } from './nodeComponents'; +import axios from '../../../axiosConfig'; +import graphState from './graphStateUtil'; + +export const nodeTypeConfig = { + Developer: { shapeType: 'developer_node', color: 'light-blue' }, + Teacher: { shapeType: 'teacher_node', color: 'light-green' }, + + User: { shapeType: 'user_node', color: 'light-green' }, + TeacherTimetable: { shapeType: 'teacher_timetable_node', color: 'blue' }, + TimetableLesson: { shapeType: 'timetable_lesson_node', color: 'light-blue' }, + PlannedLesson: { shapeType: 'planned_lesson_node', color: 'light-green' }, + School: { shapeType: 'school_node', color: 'grey' }, + Calendar: { shapeType: 'calendar_node', color: 'violet' }, + CalendarYear: { shapeType: 'calendar_year_node', color: 'red' }, + CalendarMonth: { shapeType: 'calendar_month_node', color: 'light-violet' }, + CalendarWeek: { shapeType: 'calendar_week_node', color: 'light-red' }, + CalendarDay: { shapeType: 'calendar_day_node', color: 'light-blue' }, + CalendarTimeChunk: { shapeType: 'calendar_time_chunk_node', color: 'blue' }, + ScienceLab: { shapeType: 'science_lab_node', color: 'yellow' }, + KeyStageSyllabus: { shapeType: 'key_stage_syllabus_node', color: 'grey' }, + YearGroupSyllabus: { shapeType: 'year_group_syllabus_node', color: 'light-blue' }, + CurriculumStructure: { shapeType: 'curriculum_structure_node', color: 'grey' }, + Topic: { shapeType: 'topic_node', color: 'green' }, + TopicLesson: { shapeType: 'topic_lesson_node', color: 'light-green' }, + LearningStatement: { shapeType: 'learning_statement_node', color: 'light-blue' }, + SchoolTimetable: { shapeType: 'school_timetable_node', color: 'grey' }, + AcademicYear: { shapeType: 'academic_year_node', color: 'light-violet' }, + AcademicTerm: { shapeType: 'academic_term_node', color: 'yellow' }, + AcademicWeek: { shapeType: 'academic_week_node', color: 'orange' }, + AcademicDay: { shapeType: 'academic_day_node', color: 'light-red' }, + AcademicPeriod: { shapeType: 'academic_period_node', color: 'light-green' }, + RegistrationPeriod: { shapeType: 'registration_period_node', color: 'light-green' }, + PastoralStructure: { shapeType: 'pastoral_structure_node', color: 'grey' }, + KeyStage: { shapeType: 'key_stage_node', color: 'blue' }, + Department: { shapeType: 'department_node', color: 'light-blue' }, + Room: { shapeType: 'room_node', color: 'violet' }, + SubjectClass: { shapeType: 'subject_class_node', color: 'light-blue' }, +}; + +const createNodeComponent = (shape: AllNodeShapes, theme: TLDefaultColorTheme, editor: Editor) => { + let isDragging = false; + let startX = 0; + let startY = 0; + + const borderColor = theme.id === 'dark' ? 'white' : 'black' + + const handlePointerDown = (e: React.PointerEvent) => { + e.preventDefault() + e.stopPropagation() + + const rect = e.currentTarget.getBoundingClientRect() + const x = e.clientX - rect.left + const y = e.clientY - rect.top + + // Define button areas + const openFileButtonArea = { x: 10, y: shape.props.h - 60, width: shape.props.w - 20, height: 25 } + const getConnectedNodesButtonArea = { x: 10, y: shape.props.h - 30, width: shape.props.w - 20, height: 25 } + + if (isPointInRect(x, y, openFileButtonArea)) { + console.log('Clicked on Open File button') + loadTldrawFile(shape.props.path, editor) + } else if (isPointInRect(x, y, getConnectedNodesButtonArea)) { + console.log('Clicked on Get Connected Nodes button') + handleGetConnectedNodes() + } else if (isPointInShape(x, y, shape) && !isPointInRect(x, y, openFileButtonArea) && !isPointInRect(x, y, getConnectedNodesButtonArea)) { + console.log('Clicked on shape') + isDragging = true; + startX = e.clientX - shape.x; + startY = e.clientY - shape.y; + } + } + + const handlePointerMove = (e: React.PointerEvent) => { + if (isDragging) { + const newX = e.clientX - startX; + const newY = e.clientY - startY; + editor.updateShape({ + id: shape.id, + type: shape.type, + x: newX, + y: newY, + }); + } + } + + const handlePointerUp = (e: React.PointerEvent) => { + isDragging = false; + } + + const isPointInShape = (x: number, y: number, shape: AllNodeShapes) => { + const bounds = editor.getShapeGeometry(shape).bounds + return x >= bounds.x && x <= bounds.x + bounds.width && y >= bounds.y && y <= bounds.y + bounds.height + } + + const isPointInRect = (x: number, y: number, rect: { x: number, y: number, width: number, height: number }) => { + return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height + } + + let isFetchingConnectedNodes = false; + + const handleGetConnectedNodes = async () => { + if (isFetchingConnectedNodes) { + console.log("WARNING! Already fetching connected nodes. Skipping..."); + return; + } + isFetchingConnectedNodes = true; + + console.log("Getting connected nodes for:", shape.props.unique_id); + try { + const response = await axios.get(`/api/database/tools/get-connected-nodes-and-edges?unique_id=${shape.props.unique_id}`); + console.log("Connected nodes response:", response.data); + if (response.data.status === "success") { + const mainNode = response.data.main_node; + const connectedNodes = response.data.connected_nodes; + const relationships = response.data.relationships; + + // Add nodes to the graph + [mainNode, ...connectedNodes].forEach((node: any) => { + console.log("Node:", node); + const newShapeId = createShapeId(node.node_data.unique_id); + const doesShapeExist = editor.getShape(newShapeId); + if (!doesShapeExist) { + console.log("Creating new shape with ID:", newShapeId); + const nodeConfig = nodeTypeConfig[node.node_type as keyof typeof nodeTypeConfig]; + if (nodeConfig) { + const newShape = { + id: newShapeId, + type: nodeConfig.shapeType, + x: 0, + y: 0, + props: { + color: nodeConfig.color, + ...node.node_data + } + }; + console.log("New shape:", newShape); + console.log("Creating shape:", newShape); + editor.createShape(newShape); + console.log("New shape created:", newShape); + const bounds = editor.getShapeGeometry(newShapeId).bounds; + console.log("Shape bounds:", bounds); + console.log("Updating shape with width:", bounds.w, "and height:", bounds.h); + newShape.props.w = bounds.w; + newShape.props.h = bounds.h; + console.log("Adding node to graphState:", newShape); + const shapeWithWidthAndHeight = { + ...newShape, + w: bounds.w, + h: bounds.h + } + graphState.addNode(shapeWithWidthAndHeight); + console.log("Node added to graphState:", newShape); + } else { + console.log("WARNING! Node type not found:", node.node_type); + } + } + }); + console.log("Updating shapes with dagre..."); + graphState.setEditor(editor); + graphState.updateShapesWithDagre(); + + // Add edges to the graph + relationships.forEach((relationship: any) => { + graphState.addEdge(relationship.start_node.unique_id, relationship.end_node.unique_id); + }); + + // Create edge shapes + graphState.getEdges().forEach((edge: any) => { + console.log("WARNING! Cancelling createEdgeComponent()..."); + // console.log("handleGetConnectedNodes(): Creating edge component for:", edge.v, edge.w); + // createEdgeComponent(edge.v, edge.w, editor); + }); + + console.log("Done!"); + } else { + console.error('Error in response:', response.data.message); + } + } catch (error) { + console.error('Error fetching connected nodes:', error); + } finally { + isFetchingConnectedNodes = false; + } + }; + + const loadTldrawFile = async (path: string, editor: any) => { + console.log("Loading tldraw_file...") + try { + const response = await axios.get(`/api/database/tldraw_fs/get_tldraw_user_file${path}/tldraw_file.json`); + const fileContent = response.data; + + console.log("File content:", fileContent); + + if (fileContent && fileContent.document && fileContent.document.store) { + + // Ensure the schema version is set + if (!fileContent.document.schema) { + console.log("!fileContent.document.schema") + fileContent.document.schema = { schemaVersion: 1 }; + } else if (!fileContent.document.schema.schemaVersion) { + console.log("!fileContent.document.schema.schemaVersion") + fileContent.document.schema.schemaVersion = 1; + } + + // Load the new content + console.log("Loading snapshot: ", fileContent) + editor.loadSnapshot(fileContent); + } else { + console.error('Invalid file content structure:', fileContent); + throw new Error('Invalid file content structure'); + } + } catch (error) { + console.error('Error loading tldraw file:', error); + } + }; + + return ( + + {getNodeComponent(shape, theme)} +
+
loadTldrawFile(shape.props.path, editor)} + > + Open File +
+
+ Get Connected Nodes +
+
+
+ ) +} + +const createNodeIndicator = (shape: AllNodeShapes, editor: any) => { + const bounds = editor.getShapeGeometry(shape).bounds + const theme = getDefaultColorTheme({ isDarkMode: editor.user.getIsDarkMode() }) + return ( + + ) +} + +const createEdgeComponent = (sourceId: string, targetId: string, editor: any) => { + console.log("Creating edge component for:", sourceId, targetId) + const edge = { + type: 'general_relationship', + props: { + w: 200, + h: 300, + color: 'black', + __relationshiptype__: '', + source: sourceId, + target: targetId, + } + }; + editor.createShape(edge); + graphState.addNode(edge); +}; + +export abstract class BaseNodeShapeUtil extends ShapeUtil { + static override type: string + + static override props: any + static override migrations: any + + override isAspectRatioLocked = (_shape: T) => true + override canResize = (_shape: T) => true + + abstract override getDefaultProps(): T['props'] + + getGeometry(shape: T) { + return new Rectangle2d({ + width: shape.props.w, + height: shape.props.h, + x: 0, + y: 0, + isFilled: true, + }) + } + + component(shape: T) { + const theme = getDefaultColorTheme({ isDarkMode: this.editor.user.getIsDarkMode() }) + return createNodeComponent(shape, theme, this.editor) + } + + indicator(shape: T) { + return createNodeIndicator(shape, this.editor) + } + + onDrag = (shape: T, dx: number, dy: number) => { + return { + x: shape.x + dx, + y: shape.y + dy, + } + } +} + +export abstract class BaseRelationshipShapeUtil extends ShapeUtil { + static override type: string + + static override props: any + static override migrations: any + + override isAspectRatioLocked = (_shape: T) => true + override canResize = (_shape: T) => true + + abstract override getDefaultProps(): T['props'] + + getGeometry(shape: T) { + return new Rectangle2d({ + width: shape.props.w, + height: shape.props.h, + x: 0, + y: 0, + isFilled: true, + }); + } + + component(shape: T) { + // Define how the edge is rendered + return ( + + ); + } + + indicator(shape: T) { + // Define the indicator for the edge + return ( + + ); + } +} \ No newline at end of file diff --git a/src/utils/tldraw/graph/graph-relationship-migrations.ts b/src/utils/tldraw/graph/graph-relationship-migrations.ts new file mode 100644 index 0000000..1c6dcc6 --- /dev/null +++ b/src/utils/tldraw/graph/graph-relationship-migrations.ts @@ -0,0 +1,23 @@ +import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from 'tldraw' + +// Ensure each node type and its migrations are added separately +const generalRelationshipVersions = createShapePropsMigrationIds( + 'general_relationship', + { + AddSomeProperty: 1, + } +); + +export const generalRelationshipShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: generalRelationshipVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) diff --git a/src/utils/tldraw/graph/graph-relationship-props.ts b/src/utils/tldraw/graph/graph-relationship-props.ts new file mode 100644 index 0000000..87b15d3 --- /dev/null +++ b/src/utils/tldraw/graph/graph-relationship-props.ts @@ -0,0 +1,20 @@ +import { DefaultColorStyle, T, RecordProps } from 'tldraw' +import { + GeneralRelationshipShape +} from './graph-relationship-types' + +// Base node shape props +export const baseRelationshipShapeProps = { + w: T.number, + h: T.number, + color: DefaultColorStyle, + __relationshiptype__: T.string, + source: T.string, + target: T.string, +} + +// General relationship shape props +export const generalRelationshipShapeProps: RecordProps = { + ...baseRelationshipShapeProps, +} + diff --git a/src/utils/tldraw/graph/graph-relationship-types.ts b/src/utils/tldraw/graph/graph-relationship-types.ts new file mode 100644 index 0000000..1fcca67 --- /dev/null +++ b/src/utils/tldraw/graph/graph-relationship-types.ts @@ -0,0 +1,14 @@ +import { TLBaseShape, TLDefaultColorStyle } from 'tldraw' +import { + GeneralRelationshipInterface +} from '../../../types/graph_relationship_types' + +export type BaseRelationshipShape = TLBaseShape; + +export type AllRelationshipShapes = GeneralRelationshipShape; + +export type GeneralRelationshipShape = BaseRelationshipShape<"general_relationship", GeneralRelationshipInterface>; \ No newline at end of file diff --git a/src/utils/tldraw/graph/graph-shape-migrations.ts b/src/utils/tldraw/graph/graph-shape-migrations.ts new file mode 100644 index 0000000..787b544 --- /dev/null +++ b/src/utils/tldraw/graph/graph-shape-migrations.ts @@ -0,0 +1,749 @@ +import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from 'tldraw' + +// Ensure each node type and its migrations are added separately +const userNodeVersions = createShapePropsMigrationIds( + 'user_node', + { + AddSomeProperty: 1, + } +) + +const developerNodeVersions = createShapePropsMigrationIds( + 'developer_node', + { + AddSomeProperty: 1, + } +); + +const teacherNodeVersions = createShapePropsMigrationIds( + 'teacher_node', + { + AddSomeProperty: 1, + } +); + +const studentNodeVersions = createShapePropsMigrationIds( + 'student_node', + { + AddSomeProperty: 1, + } +); + +export const userNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: userNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const developerNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: developerNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const teacherNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: teacherNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const studentNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: studentNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +// Calendar node shape migrations +const calendarNodeVersions = createShapePropsMigrationIds( + 'calendar_node', + { + AddSomeProperty: 1, + } +) + +const yearNodeVersions = createShapePropsMigrationIds( + 'calendar_year_node', + { + AddSomeProperty: 1, + } +); + +const monthNodeVersions = createShapePropsMigrationIds( + 'calendar_month_node', + { + AddSomeProperty: 1, + } +); + +const weekNodeVersions = createShapePropsMigrationIds( + 'calendar_week_node', + { + AddSomeProperty: 1, + } +); + +const dayNodeVersions = createShapePropsMigrationIds( + 'calendar_day_node', + { + AddSomeProperty: 1, + } +); + +const timeChunkNodeVersions = createShapePropsMigrationIds( + 'calendar_time_chunk_node', + { + AddSomeProperty: 1, + } +); + + +export const calendarNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: calendarNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const yearNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: yearNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const monthNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: monthNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const weekNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: weekNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const dayNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: dayNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const timeChunkNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: timeChunkNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + + +const schoolNodeVersions = createShapePropsMigrationIds( + 'school_node', + { + AddSomeProperty: 1, + } +) + +const departmentNodeVersions = createShapePropsMigrationIds( + 'department_node', + { + AddSomeProperty: 1, + } +); + +const roomNodeVersions = createShapePropsMigrationIds( + 'room_node', + { + AddSomeProperty: 1, + } +); + +const subjectClassNodeVersions = createShapePropsMigrationIds( + 'subject_class_node', + { + AddSomeProperty: 1, + } +); + +export const schoolNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: schoolNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const departmentNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: departmentNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const roomNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: roomNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const subjectClassNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: subjectClassNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + + +const pastoralStructureNodeVersions = createShapePropsMigrationIds( + 'pastoral_structure_node', + { + AddSomeProperty: 1, + } +) + +const yearGroupNodeVersions = createShapePropsMigrationIds( + 'year_group_node', + { + AddSomeProperty: 1, + } +); + +const curriculumStructureNodeVersions = createShapePropsMigrationIds( + 'curriculum_structure_node', + { + AddSomeProperty: 1, + } +); + +const keyStageNodeVersions = createShapePropsMigrationIds( + 'key_stage_node', + { + AddSomeProperty: 1, + } +); + +const keyStageSyllabusNodeVersions = createShapePropsMigrationIds( + 'key_stage_syllabus_node', + { + AddSomeProperty: 1, + } +); + +const yearGroupSyllabusNodeVersions = createShapePropsMigrationIds( + 'year_group_syllabus_node', + { + AddSomeProperty: 1, + } +); + +const subjectNodeVersions = createShapePropsMigrationIds( + 'subject_node', + { + AddSomeProperty: 1, + } +); + +const topicNodeVersions = createShapePropsMigrationIds( + 'topic_node', + { + AddSomeProperty: 1, + } +); + +const topicLessonNodeVersions = createShapePropsMigrationIds( + 'topic_lesson_node', + { + AddSomeProperty: 1, + } +); + +const learningStatementNodeVersions = createShapePropsMigrationIds( + 'learning_statement_node', + { + AddSomeProperty: 1, + } +); + +const scienceLabNodeVersions = createShapePropsMigrationIds( + 'science_lab_node', + { + AddSomeProperty: 1, + } +); + +export const pastoralStructureNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: pastoralStructureNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const yearGroupNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: yearGroupNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const curriculumStructureNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: curriculumStructureNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const keyStageNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: keyStageNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const keyStageSyllabusNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: keyStageSyllabusNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const yearGroupSyllabusNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: yearGroupSyllabusNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const subjectNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: subjectNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const topicNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: topicNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const topicLessonNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: topicLessonNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + + +export const learningStatementNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: learningStatementNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const scienceLabNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: scienceLabNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + + + + +const schoolTimetableNodeVersions = createShapePropsMigrationIds( + 'school_timetable_node', + { + AddSomeProperty: 1, + } +) + +const academicYearNodeVersions = createShapePropsMigrationIds( + 'academic_year_node', + { + AddSomeProperty: 1, + } +); + +const academicTermNodeVersions = createShapePropsMigrationIds( + 'academic_term_node', + { + AddSomeProperty: 1, + } +); + +const academicWeekNodeVersions = createShapePropsMigrationIds( + 'academic_week_node', + { + AddSomeProperty: 1, + } +); + +const academicDayNodeVersions = createShapePropsMigrationIds( + 'academic_day_node', + { + AddSomeProperty: 1, + } +); + +const academicPeriodNodeVersions = createShapePropsMigrationIds( + 'academic_period_node', + { + AddSomeProperty: 1, + } +); + +const registrationPeriodNodeVersions = createShapePropsMigrationIds( + 'registration_period_node', + { + AddSomeProperty: 1, + } +); + +export const schoolTimetableNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: schoolTimetableNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const academicYearNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: academicYearNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const academicTermNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: academicTermNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const academicWeekNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: academicWeekNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const academicDayNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: academicDayNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const academicPeriodNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: academicPeriodNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const registrationPeriodNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: registrationPeriodNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + + + + + +const teacherTimetableNodeVersions = createShapePropsMigrationIds( + 'teacher_timetable_node', + { + AddSomeProperty: 1, + } +) + +const timetableLessonNodeVersions = createShapePropsMigrationIds( + 'timetable_lesson_node', + { + AddSomeProperty: 1, + } +); + +const plannedLessonNodeVersions = createShapePropsMigrationIds( + 'planned_lesson_node', + { + AddSomeProperty: 1, + } +); + +export const teacherTimetableNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: teacherTimetableNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const timetableLessonNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: timetableLessonNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) + +export const plannedLessonNodeShapeMigrations = createShapePropsMigrationSequence({ + sequence: [ + { + id: plannedLessonNodeVersions.AddSomeProperty, + up(props) { + props.someProperty = 'some value' + }, + down(props) { + delete props.someProperty + }, + } + ], +}) \ No newline at end of file diff --git a/src/utils/tldraw/graph/graph-shape-props.ts b/src/utils/tldraw/graph/graph-shape-props.ts new file mode 100644 index 0000000..d8ed81a --- /dev/null +++ b/src/utils/tldraw/graph/graph-shape-props.ts @@ -0,0 +1,332 @@ +import { DefaultColorStyle, RecordProps, T } from 'tldraw' +import { + UserNodeShape, + DeveloperNodeShape, + TeacherNodeShape, + StudentNodeShape, + CalendarNodeShape, + CalendarYearNodeShape, + CalendarMonthNodeShape, + CalendarWeekNodeShape, + CalendarDayNodeShape, + CalendarTimeChunkNodeShape, + SchoolNodeShape, + DepartmentNodeShape, + RoomNodeShape, + SubjectClassNodeShape, + PastoralStructureNodeShape, + YearGroupNodeShape, + CurriculumStructureNodeShape, + KeyStageNodeShape, + KeyStageSyllabusNodeShape, + YearGroupSyllabusNodeShape, + SubjectNodeShape, + TopicNodeShape, + TopicLessonNodeShape, + LearningStatementNodeShape, + ScienceLabNodeShape, + SchoolTimetableNodeShape, + AcademicYearNodeShape, + AcademicTermNodeShape, + AcademicWeekNodeShape, + AcademicDayNodeShape, + AcademicPeriodNodeShape, + RegistrationPeriodNodeShape, + TeacherTimetableNodeShape, + TimetableLessonNodeShape, + PlannedLessonNodeShape, +} from './graph-shape-types' + +// Base node shape props +const baseNodeShapeProps = { + w: T.number, + h: T.number, + color: DefaultColorStyle, + __primarylabel__: T.string, + unique_id: T.string, + path: T.string, + created: T.string, + merged: T.string, +} + +export const userNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + user_id: T.string, + user_name: T.string, + user_email: T.string, + worker_node_data: T.string, + user_type: T.string, +} + +export const developerNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + user_id: T.string, + user_name: T.string, + user_email: T.string, + user_type: T.string, +} + +export const teacherNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + teacher_code: T.string, + teacher_name_formal: T.string, + teacher_email: T.string, + worker_db_name: T.string, +} + +export const studentNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + student_code: T.string, + student_name_formal: T.string, + student_email: T.string, + worker_db_name: T.string, +} + +// Calendar node shape props +export const calendarNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + name: T.string, + start_date: T.string, + end_date: T.string, +} + +export const calendarYearNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + year: T.string, +} + +export const calendarMonthNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + year: T.string, + month: T.string, + month_name: T.string, +} + +export const calendarWeekNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + start_date: T.string, + week_number: T.string, + iso_week: T.string, +} + +export const calendarDayNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + date: T.string, + day_of_week: T.string, + iso_day: T.string, +} + +export const calendarTimeChunkNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + start_time: T.string, + end_time: T.string, +} + + +// School +export const schoolNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + school_name: T.string, + school_website: T.string, + school_uuid: T.string, +} + +export const departmentNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + department_name: T.string, +} + +export const roomNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + room_code: T.string, + room_name: T.string, +} + +export const subjectClassNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + subject_class_code: T.string, + year_group: T.string, + subject: T.string, + subject_code: T.string, +} + +// Curriculum +export const pastoralStructureNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, +} + +export const yearGroupNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + year_group: T.string, + year_group_name: T.string, +} + + +export const curriculumStructureNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, +} + +export const keyStageNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + key_stage_name: T.string, + key_stage: T.string, +} + + +export const keyStageSyllabusNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + ks_syllabus_id: T.string, + ks_syllabus_name: T.string, + ks_syllabus_key_stage: T.string, + ks_syllabus_subject: T.string, + ks_syllabus_subject_code: T.string, +} + + +export const yearGroupSyllabusNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + yr_syllabus_id: T.string, + yr_syllabus_name: T.string, + yr_syllabus_year_group: T.string, + yr_syllabus_subject: T.string, + yr_syllabus_subject_code: T.string, +} + + +export const subjectNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + subject_code: T.string, + subject_name: T.string, +} + +export const topicNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + topic_id: T.string, + topic_title: T.string, + total_number_of_lessons_for_topic: T.string, + topic_type: T.string, + topic_assessment_type: T.string, +} + +export const topicLessonNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + topic_lesson_id: T.string, + topic_lesson_title: T.string, + topic_lesson_type: T.string, + topic_lesson_length: T.string, + topic_lesson_suggested_activities: T.string, + topic_lesson_skills_learned: T.string, + topic_lesson_weblinks: T.string, + +} + +export const learningStatementNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + lesson_learning_statement_id: T.string, + lesson_learning_statement: T.string, + lesson_learning_statement_type: T.string, +} + + +export const scienceLabNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + science_lab_id: T.string, + science_lab_title: T.string, + science_lab_summary: T.string, + science_lab_requirements: T.string, + science_lab_procedure: T.string, + science_lab_safety: T.string, + science_lab_weblinks: T.string, +} + +// School Timetable +export const schoolTimetableNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + start_date: T.string, + end_date: T.string, +} + + +export const academicYearNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + year: T.string, +} + + +export const academicTermNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + term_name: T.string, + term_number: T.string, + start_date: T.string, + end_date: T.string, +} + +export const academicWeekNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + academic_week_number: T.string, + start_date: T.string, + week_type: T.string, +} + +export const academicDayNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + academic_day: T.string, + date: T.string, + day_of_week: T.string, + day_type: T.string, +} + +export const academicPeriodNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + name: T.string, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, +} + +export const registrationPeriodNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + name: T.string, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, +} + + + +// Teacher Timetable +export const teacherTimetableNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, +} + +export const timetableLessonNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + subject_class: T.string, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, +} + +export const plannedLessonNodeShapeProps: RecordProps = { + ...baseNodeShapeProps, + date: T.string, + start_time: T.string, + end_time: T.string, + period_code: T.string, + subject_class: T.string, + year_group: T.string, + subject: T.string, + teacher_code: T.string, + planning_status: T.string, + topic_code: T.string.optional().nullable(), + topic_name: T.string.optional().nullable(), + lesson_code: T.string.optional().nullable(), + lesson_name: T.string.optional().nullable(), + learning_statement_codes: T.string.optional().nullable(), + learning_statements: T.string.optional().nullable(), + learning_resource_codes: T.string.optional().nullable(), + learning_resources: T.string.optional().nullable(), +} diff --git a/src/utils/tldraw/graph/graph-shape-types.ts b/src/utils/tldraw/graph/graph-shape-types.ts new file mode 100644 index 0000000..369b3c5 --- /dev/null +++ b/src/utils/tldraw/graph/graph-shape-types.ts @@ -0,0 +1,94 @@ +import { TLBaseShape, TLDefaultColorStyle } from 'tldraw' +import { + UserNodeInterface, + DeveloperNodeInterface, + TeacherNodeInterface, + StudentNodeInterface, + CalendarNodeInterface, + CalendarYearNodeInterface, + CalendarMonthNodeInterface, + CalendarWeekNodeInterface, + CalendarDayNodeInterface, + CalendarTimeChunkNodeInterface, + SchoolNodeInterface, + DepartmentNodeInterface, + RoomNodeInterface, + SubjectClassNodeInterface, + PastoralStructureNodeInterface, + YearGroupNodeInterface, + CurriculumStructureNodeInterface, + KeyStageNodeInterface, + KeyStageSyllabusNodeInterface, + YearGroupSyllabusNodeInterface, + SubjectNodeInterface, + TopicNodeInterface, + TopicLessonNodeInterface, + LearningStatementNodeInterface, + ScienceLabNodeInterface, + SchoolTimetableNodeInterface, + AcademicYearNodeInterface, + AcademicTermNodeInterface, + AcademicWeekNodeInterface, + AcademicDayNodeInterface, + AcademicPeriodNodeInterface, + RegistrationPeriodNodeInterface, + TeacherTimetableNodeInterface, + TimetableLessonNodeInterface, + PlannedLessonNodeInterface +} from '../../../types/graph_node_types'; + +export type BaseNodeShape = TLBaseShape; + +export type AllNodeShapes = UserNodeShape | DeveloperNodeShape | TeacherNodeShape | StudentNodeShape | CalendarNodeShape | CalendarYearNodeShape | CalendarMonthNodeShape | CalendarWeekNodeShape | CalendarDayNodeShape | CalendarTimeChunkNodeShape | ScienceLabNodeShape | KeyStageSyllabusNodeShape | YearGroupNodeShape | YearGroupSyllabusNodeShape | CurriculumStructureNodeShape | TopicNodeShape | TopicLessonNodeShape | LearningStatementNodeShape | SchoolNodeShape | TeacherTimetableNodeShape | TimetableLessonNodeShape | PlannedLessonNodeShape | SchoolTimetableNodeShape | SubjectClassNodeShape | SubjectNodeShape | AcademicDayNodeShape | AcademicWeekNodeShape | AcademicYearNodeShape | AcademicTermNodeShape | AcademicPeriodNodeShape | RegistrationPeriodNodeShape | PastoralStructureNodeShape | KeyStageNodeShape | RoomNodeShape | DepartmentNodeShape; + +// User entity node shapes +export type UserNodeShape = BaseNodeShape<"user_node", UserNodeInterface>; +export type DeveloperNodeShape = BaseNodeShape<"developer_node", DeveloperNodeInterface>; +export type TeacherNodeShape = BaseNodeShape<"teacher_node", TeacherNodeInterface>; +export type StudentNodeShape = BaseNodeShape<"student_node", StudentNodeInterface>; + +// Calendar node shapes +export type CalendarNodeShape = BaseNodeShape<"calendar_node", CalendarNodeInterface>; +export type CalendarYearNodeShape = BaseNodeShape<"calendar_year_node", CalendarYearNodeInterface>; +export type CalendarMonthNodeShape = BaseNodeShape<"calendar_month_node", CalendarMonthNodeInterface>; +export type CalendarWeekNodeShape = BaseNodeShape<"calendar_week_node", CalendarWeekNodeInterface>; +export type CalendarDayNodeShape = BaseNodeShape<"calendar_day_node", CalendarDayNodeInterface>; +export type CalendarTimeChunkNodeShape = BaseNodeShape<"calendar_time_chunk_node", CalendarTimeChunkNodeInterface>; + +// School entity node shapes +export type SchoolNodeShape = BaseNodeShape<"school_node", SchoolNodeInterface>; +export type DepartmentNodeShape = BaseNodeShape<"department_node", DepartmentNodeInterface>; +export type RoomNodeShape = BaseNodeShape<"room_node", RoomNodeInterface>; +export type SubjectClassNodeShape = BaseNodeShape<"subject_class_node", SubjectClassNodeInterface>; + +// Curriculum entity node shapes +export type PastoralStructureNodeShape = BaseNodeShape<"pastoral_structure_node", PastoralStructureNodeInterface>; +export type YearGroupNodeShape = BaseNodeShape<"year_group_node", YearGroupNodeInterface>; +export type CurriculumStructureNodeShape = BaseNodeShape<"curriculum_structure_node", CurriculumStructureNodeInterface>; +export type KeyStageNodeShape = BaseNodeShape<"key_stage_node", KeyStageNodeInterface>; +export type KeyStageSyllabusNodeShape = BaseNodeShape<"key_stage_syllabus_node", KeyStageSyllabusNodeInterface>; +export type YearGroupSyllabusNodeShape = BaseNodeShape<"year_group_syllabus_node", YearGroupSyllabusNodeInterface>; +export type SubjectNodeShape = BaseNodeShape<"subject_node", SubjectNodeInterface>; +export type TopicNodeShape = BaseNodeShape<"topic_node", TopicNodeInterface>; +export type TopicLessonNodeShape = BaseNodeShape<"topic_lesson_node", TopicLessonNodeInterface>; +export type LearningStatementNodeShape = BaseNodeShape<"learning_statement_node", LearningStatementNodeInterface>; +export type ScienceLabNodeShape = BaseNodeShape<"science_lab_node", ScienceLabNodeInterface>; + +// School timetable entity node shapes +export type SchoolTimetableNodeShape = BaseNodeShape<"school_timetable_node", SchoolTimetableNodeInterface>; +export type AcademicYearNodeShape = BaseNodeShape<"academic_year_node", AcademicYearNodeInterface>; +export type AcademicTermNodeShape = BaseNodeShape<"academic_term_node", AcademicTermNodeInterface>; +export type AcademicWeekNodeShape = BaseNodeShape<"academic_week_node", AcademicWeekNodeInterface>; +export type AcademicDayNodeShape = BaseNodeShape<"academic_day_node", AcademicDayNodeInterface>; +export type AcademicPeriodNodeShape = BaseNodeShape<"academic_period_node", AcademicPeriodNodeInterface>; +export type RegistrationPeriodNodeShape = BaseNodeShape<"registration_period_node", RegistrationPeriodNodeInterface>; + +// Teacher timetable entity node shapes +export type TeacherTimetableNodeShape = BaseNodeShape<"teacher_timetable_node", TeacherTimetableNodeInterface>; +export type TimetableLessonNodeShape = BaseNodeShape<"timetable_lesson_node", TimetableLessonNodeInterface>; +export type PlannedLessonNodeShape = BaseNodeShape<"planned_lesson_node", PlannedLessonNodeInterface>; + diff --git a/src/utils/tldraw/graph/graphShapeUtil.tsx b/src/utils/tldraw/graph/graphShapeUtil.tsx new file mode 100644 index 0000000..0d7b14e --- /dev/null +++ b/src/utils/tldraw/graph/graphShapeUtil.tsx @@ -0,0 +1,971 @@ +import { BaseNodeShapeUtil, BaseRelationshipShapeUtil } from './baseNodeShapeUtil' +import { + UserNodeShape, + DeveloperNodeShape, + TeacherNodeShape, + StudentNodeShape, + CalendarNodeShape, + CalendarYearNodeShape, + CalendarMonthNodeShape, + CalendarWeekNodeShape, + CalendarDayNodeShape, + CalendarTimeChunkNodeShape, + ScienceLabNodeShape, + KeyStageSyllabusNodeShape, + YearGroupNodeShape, + YearGroupSyllabusNodeShape, + CurriculumStructureNodeShape, + TopicNodeShape, + TopicLessonNodeShape, + LearningStatementNodeShape, + SchoolNodeShape, + TeacherTimetableNodeShape, + TimetableLessonNodeShape, + PlannedLessonNodeShape, + SchoolTimetableNodeShape, + SubjectClassNodeShape, + SubjectNodeShape, + AcademicDayNodeShape, + AcademicWeekNodeShape, + AcademicYearNodeShape, + AcademicTermNodeShape, + AcademicPeriodNodeShape, + RegistrationPeriodNodeShape, + PastoralStructureNodeShape, + KeyStageNodeShape, + RoomNodeShape, + DepartmentNodeShape, +} from './graph-shape-types' +import { + userNodeShapeProps, + developerNodeShapeProps, + teacherNodeShapeProps, + studentNodeShapeProps, + calendarNodeShapeProps, + calendarYearNodeShapeProps, + calendarMonthNodeShapeProps, + calendarWeekNodeShapeProps, + calendarDayNodeShapeProps, + calendarTimeChunkNodeShapeProps, + scienceLabNodeShapeProps, + keyStageSyllabusNodeShapeProps, + yearGroupNodeShapeProps, + yearGroupSyllabusNodeShapeProps, + curriculumStructureNodeShapeProps, + topicNodeShapeProps, + topicLessonNodeShapeProps, + learningStatementNodeShapeProps, + schoolNodeShapeProps, + teacherTimetableNodeShapeProps, + timetableLessonNodeShapeProps, + plannedLessonNodeShapeProps, + schoolTimetableNodeShapeProps, + subjectClassNodeShapeProps, + subjectNodeShapeProps, + academicDayNodeShapeProps, + academicWeekNodeShapeProps, + academicYearNodeShapeProps, + academicTermNodeShapeProps, + academicPeriodNodeShapeProps, + registrationPeriodNodeShapeProps, + pastoralStructureNodeShapeProps, + keyStageNodeShapeProps, + departmentNodeShapeProps, + roomNodeShapeProps +} from './graph-shape-props' +import { + userNodeShapeMigrations, + developerNodeShapeMigrations, + teacherNodeShapeMigrations, + studentNodeShapeMigrations, + calendarNodeShapeMigrations, + yearNodeShapeMigrations, + monthNodeShapeMigrations, + weekNodeShapeMigrations, + dayNodeShapeMigrations, + timeChunkNodeShapeMigrations, + keyStageSyllabusNodeShapeMigrations, + yearGroupNodeShapeMigrations, + yearGroupSyllabusNodeShapeMigrations, + curriculumStructureNodeShapeMigrations, + topicNodeShapeMigrations, + topicLessonNodeShapeMigrations, + learningStatementNodeShapeMigrations, + scienceLabNodeShapeMigrations, + schoolNodeShapeMigrations, + teacherTimetableNodeShapeMigrations, + timetableLessonNodeShapeMigrations, + plannedLessonNodeShapeMigrations, + schoolTimetableNodeShapeMigrations, + subjectClassNodeShapeMigrations, + subjectNodeShapeMigrations, + academicDayNodeShapeMigrations, + academicWeekNodeShapeMigrations, + academicYearNodeShapeMigrations, + academicTermNodeShapeMigrations, + academicPeriodNodeShapeMigrations, + registrationPeriodNodeShapeMigrations, + pastoralStructureNodeShapeMigrations, + roomNodeShapeMigrations, + departmentNodeShapeMigrations, + keyStageNodeShapeMigrations, +} from './graph-shape-migrations' +import { GeneralRelationshipShape } from './graph-relationship-types' +import { generalRelationshipShapeProps } from './graph-relationship-props' +import { generalRelationshipShapeMigrations } from './graph-relationship-migrations' + +// User Nodes +export class UserNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'user_node' as const + static override props = userNodeShapeProps + static override migrations = userNodeShapeMigrations + + getDefaultProps(): UserNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'blue', + __primarylabel__: 'User', + unique_id: '', + user_name: '', + user_email: '', + user_type: '', + user_id: '', + worker_node_data: '', + path: '', + created: '', + merged: '', + } + } +} + +export class DeveloperNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'developer_node' as const + static override props = developerNodeShapeProps + static override migrations = developerNodeShapeMigrations + + getDefaultProps(): DeveloperNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Developer', + unique_id: '', + user_name: '', + user_email: '', + user_type: '', + user_id: '', + path: '', + created: '', + merged: '', + } + } +} + +export class TeacherNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'teacher_node' as const + static override props = teacherNodeShapeProps + static override migrations = teacherNodeShapeMigrations + + getDefaultProps(): TeacherNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Teacher', + unique_id: '', + teacher_code: '', + teacher_name_formal: '', + teacher_email: '', + worker_db_name: '', + path: '', + created: '', + merged: '', + } + } +} + +export class StudentNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'student_node' as const + static override props = studentNodeShapeProps + static override migrations = studentNodeShapeMigrations + + getDefaultProps(): StudentNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Student', + unique_id: '', + student_code: '', + student_name_formal: '', + student_email: '', + worker_db_name: '', + path: '', + created: '', + merged: '', + } + } +} + +// Calendar Nodes +export class CalendarNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'calendar_node' as const + static override props = calendarNodeShapeProps + static override migrations = calendarNodeShapeMigrations + + getDefaultProps(): CalendarNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Calendar', + unique_id: '', + name: '', + start_date: '', + end_date: '', + path: '', + created: '', + merged: '', + } + } +} + +export class CalendarYearNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'calendar_year_node' as const + static override props = calendarYearNodeShapeProps + static override migrations = yearNodeShapeMigrations + + getDefaultProps(): CalendarYearNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Calendar Year', + unique_id: '', + year: '', + path: '', + created: '', + merged: '' + } + } +} + +export class CalendarMonthNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'calendar_month_node' as const + static override props = calendarMonthNodeShapeProps + static override migrations = monthNodeShapeMigrations + + getDefaultProps(): CalendarMonthNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Calendar Month', + unique_id: '', + year: '', + month: '', + month_name: '', + path: '', + created: '', + merged: '', + } + } +} + +export class CalendarWeekNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'calendar_week_node' as const + static override props = calendarWeekNodeShapeProps + static override migrations = weekNodeShapeMigrations + + getDefaultProps(): CalendarWeekNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Calendar Week', + unique_id: '', + start_date: '', + week_number: '', + iso_week: '', + path: '', + created: '', + merged: '', + } + } +} + +export class CalendarDayNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'calendar_day_node' as const + static override props = calendarDayNodeShapeProps + static override migrations = dayNodeShapeMigrations + + getDefaultProps(): CalendarDayNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Calendar Day', + unique_id: '', + date: '', + day_of_week: '', + iso_day: '', + path: '', + created: '', + merged: '', + } + } +} + +export class CalendarTimeChunkNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'calendar_time_chunk_node' as const + static override props = calendarTimeChunkNodeShapeProps + static override migrations = timeChunkNodeShapeMigrations + + getDefaultProps(): CalendarTimeChunkNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Calendar Time Chunk', + unique_id: '', + start_time: '', + end_time: '', + path: '', + created: '', + merged: '', + } + } +} + +// School Nodes +export class SubjectClassNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'subject_class_node' as const + static override props = subjectClassNodeShapeProps + static override migrations = subjectClassNodeShapeMigrations + + getDefaultProps(): SubjectClassNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Subject Class', + unique_id: '', + subject_class_code: '', + year_group: '', + subject: '', + subject_code: '', + path: '', + created: '', + merged: '', + } + } +} + +export class SchoolNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'school_node' as const + static override props = schoolNodeShapeProps + static override migrations = schoolNodeShapeMigrations + + getDefaultProps(): SchoolNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'School', + unique_id: '', + school_uuid: '', + school_name: '', + school_website: '', + path: '', + created: '', + merged: '', + } + } +} + +export class DepartmentNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'department_node' as const + static override props = departmentNodeShapeProps + static override migrations = departmentNodeShapeMigrations + + getDefaultProps(): DepartmentNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Department', + unique_id: '', + department_name: '', + path: '', + created: '', + merged: '', + } + } +} + +export class RoomNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'room_node' as const + static override props = roomNodeShapeProps + static override migrations = roomNodeShapeMigrations + + getDefaultProps(): RoomNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Room', + unique_id: '', + room_name: '', + room_code: '', + path: '', + created: '', + merged: '', + } + } +} + + +// Curriculum Nodes +export class PastoralStructureNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'pastoral_structure_node' as const + static override props = pastoralStructureNodeShapeProps + static override migrations = pastoralStructureNodeShapeMigrations + + getDefaultProps(): PastoralStructureNodeShape['props'] { + return { + w: 200, + h: 130, + color: 'white', + __primarylabel__: 'Pastoral Structure', + unique_id: '', + path: '', + created: '', + merged: '', + } + } +} + +export class YearGroupNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'year_group_node' as const + static override props = yearGroupNodeShapeProps + static override migrations = yearGroupNodeShapeMigrations + + getDefaultProps(): YearGroupNodeShape['props'] { + return { + w: 200, + h: 150, + color: 'white', + __primarylabel__: 'Year Group', + unique_id: '', + year_group: '', + year_group_name: '', + path: '', + created: '', + merged: '', + } + } +} + +export class CurriculumStructureNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'curriculum_structure_node' as const + static override props = curriculumStructureNodeShapeProps + static override migrations = curriculumStructureNodeShapeMigrations + + getDefaultProps(): CurriculumStructureNodeShape['props'] { + return { + w: 200, + h: 130, + color: 'white', + __primarylabel__: 'Curriculum Structure', + unique_id: '', + path: '', + created: '', + merged: '', + } + } +} + +export class KeyStageNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'key_stage_node' as const + static override props = keyStageNodeShapeProps + static override migrations = keyStageNodeShapeMigrations + + getDefaultProps(): KeyStageNodeShape['props'] { + return { + w: 200, + h: 150, + color: 'white', + __primarylabel__: 'Key Stage', + unique_id: '', + key_stage_name: '', + key_stage: '', + path: '', + created: '', + merged: '', + } + } +} + +export class KeyStageSyllabusNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'key_stage_syllabus_node' as const + static override props = keyStageSyllabusNodeShapeProps + static override migrations = keyStageSyllabusNodeShapeMigrations + + getDefaultProps(): KeyStageSyllabusNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Key Stage Syllabus', + unique_id: '', + ks_syllabus_id: '', + ks_syllabus_name: '', + ks_syllabus_key_stage: '', + ks_syllabus_subject: '', + ks_syllabus_subject_code: '', + path: '', + created: '', + merged: '', + } + } +} + +export class YearGroupSyllabusNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'year_group_syllabus_node' as const + static override props = yearGroupSyllabusNodeShapeProps + static override migrations = yearGroupSyllabusNodeShapeMigrations + + getDefaultProps(): YearGroupSyllabusNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Year Group Syllabus', + unique_id: '', + yr_syllabus_id: '', + yr_syllabus_name: '', + yr_syllabus_year_group: '', + yr_syllabus_subject: '', + yr_syllabus_subject_code: '', + path: '', + created: '', + merged: '', + } + } +} + +export class SubjectNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'subject_node' as const + static override props = subjectNodeShapeProps + static override migrations = subjectNodeShapeMigrations + + getDefaultProps(): SubjectNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Subject', + unique_id: '', + subject_code: '', + subject_name: '', + path: '', + created: '', + merged: '', + } + } +} + +export class TopicNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'topic_node' as const + static override props = topicNodeShapeProps + static override migrations = topicNodeShapeMigrations + + getDefaultProps(): TopicNodeShape['props'] { + return { + w: 300, + h: 400, + color: 'white', + __primarylabel__: 'Topic', + unique_id: '', + topic_id: '', + topic_title: '', + total_number_of_lessons_for_topic: '', + topic_type: '', + topic_assessment_type: '', + path: '', + created: '', + merged: '', + } + } +} + +export class TopicLessonNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'topic_lesson_node' as const + static override props = topicLessonNodeShapeProps + static override migrations = topicLessonNodeShapeMigrations + + getDefaultProps(): TopicLessonNodeShape['props'] { + return { + w: 300, + h: 500, + color: 'white', + __primarylabel__: 'Topic Lesson', + unique_id: '', + topic_lesson_id: '', + topic_lesson_title: '', + topic_lesson_type: '', + topic_lesson_length: '', + topic_lesson_skills_learned: '', + topic_lesson_suggested_activities: '', + topic_lesson_weblinks: '', + path: '', + created: '', + merged: '', + } + } +} + +export class LearningStatementNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'learning_statement_node' as const + static override props = learningStatementNodeShapeProps + static override migrations = learningStatementNodeShapeMigrations + + getDefaultProps(): LearningStatementNodeShape['props'] { + return { + w: 180, + h: 300, + color: 'light-blue', + __primarylabel__: 'Learning Statement', + unique_id: '', + lesson_learning_statement_id: '', + lesson_learning_statement: '', + lesson_learning_statement_type: '', + path: '', + created: '', + merged: '', + } + } +} + +export class ScienceLabNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'science_lab_node' as const + static override props = scienceLabNodeShapeProps + static override migrations = scienceLabNodeShapeMigrations + + getDefaultProps(): ScienceLabNodeShape['props'] { + return { + w: 300, + h: 400, + color: 'white', + __primarylabel__: 'Science Lab', + unique_id: '', + science_lab_id: '', + science_lab_title: '', + science_lab_summary: '', + science_lab_requirements: '', + science_lab_procedure: '', + science_lab_safety: '', + science_lab_weblinks: '', + path: '', + created: '', + merged: '', + } + } +} + +// School Timetable Nodes +export class SchoolTimetableNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'school_timetable_node' as const + + static override props = schoolTimetableNodeShapeProps + static override migrations = schoolTimetableNodeShapeMigrations + + getDefaultProps(): SchoolTimetableNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'School Timetable', + unique_id: '', + start_date: '', + end_date: '', + path: '', + created: '', + merged: '', + } + } +} + +export class AcademicYearNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'academic_year_node' as const + static override props = academicYearNodeShapeProps + static override migrations = academicYearNodeShapeMigrations + + getDefaultProps(): AcademicYearNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Academic Year', + unique_id: '', + year: '', + path: '', + created: '', + merged: '', + } + } +} + +export class AcademicTermNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'academic_term_node' as const + static override props = academicTermNodeShapeProps + static override migrations = academicTermNodeShapeMigrations + + getDefaultProps(): AcademicTermNodeShape['props'] { + return { + w: 300, + h: 200, + color: 'white', + __primarylabel__: 'Academic Term', + unique_id: '', + term_name: '', + term_number: '', + start_date: '', + end_date: '', + path: '', + created: '', + merged: '', + } + } +} + +export class AcademicWeekNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'academic_week_node' as const + static override props = academicWeekNodeShapeProps + static override migrations = academicWeekNodeShapeMigrations + + getDefaultProps(): AcademicWeekNodeShape['props'] { + return { + w: 300, + h: 200, + color: 'white', + __primarylabel__: 'Academic Week', + unique_id: '', + start_date: '', + week_type: '', + academic_week_number: '', + path: '', + created: '', + merged: '', + } + } +} + +export class AcademicDayNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'academic_day_node' as const + static override props = academicDayNodeShapeProps + static override migrations = academicDayNodeShapeMigrations + + getDefaultProps(): AcademicDayNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Academic Day', + unique_id: '', + academic_day: '', + date: '', + day_of_week: '', + day_type: '', + path: '', + created: '', + merged: '', + } + } +} + +export class AcademicPeriodNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'academic_period_node' as const + static override props = academicPeriodNodeShapeProps + static override migrations = academicPeriodNodeShapeMigrations + + getDefaultProps(): AcademicPeriodNodeShape['props'] { + return { + w: 200, + h: 300, + color: 'white', + __primarylabel__: 'Academic Period', + unique_id: '', + name: '', + date: '', + start_time: '', + end_time: '', + period_code: '', + path: '', + created: '', + merged: '', + } + } +} + +export class RegistrationPeriodNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'registration_period_node' as const + static override props = registrationPeriodNodeShapeProps + static override migrations = registrationPeriodNodeShapeMigrations + + getDefaultProps(): RegistrationPeriodNodeShape['props'] { + return { + w: 200, + h: 200, + color: 'white', + __primarylabel__: 'Registration Period', + unique_id: '', + name: '', + date: '', + start_time: '', + end_time: '', + period_code: '', + path: '', + created: '', + merged: '', + } + } +} + +// Teacher Timetable Nodes +export class TeacherTimetableNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'teacher_timetable_node' as const + static override props = teacherTimetableNodeShapeProps + static override migrations = teacherTimetableNodeShapeMigrations + + getDefaultProps(): TeacherTimetableNodeShape['props'] { + return { + w: 200, + h: 130, + color: 'white', + __primarylabel__: 'Teacher Timetable', + unique_id: '', + path: '', + created: '', + merged: '', + } + } +} + +export class TimetableLessonNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'timetable_lesson_node' as const + static override props = timetableLessonNodeShapeProps + static override migrations = timetableLessonNodeShapeMigrations + + override isAspectRatioLocked = (_shape: TimetableLessonNodeShape) => true + override canResize = (_shape: TimetableLessonNodeShape) => true + + getDefaultProps(): TimetableLessonNodeShape['props'] { + return { + w: 200, + h: 250, + color: 'white', + __primarylabel__: 'Timetable Lesson', + unique_id: '', + subject_class: '', + date: '', + start_time: '', + end_time: '', + period_code: '', + path: '', + created: '', + merged: '', + } + } +} + +export class PlannedLessonNodeShapeUtil extends BaseNodeShapeUtil { + static override type = 'planned_lesson_node' as const + static override props = plannedLessonNodeShapeProps + static override migrations = plannedLessonNodeShapeMigrations + + getDefaultProps(): PlannedLessonNodeShape['props'] { + return { + w: 200, + h: 250, + color: 'white', + __primarylabel__: 'Planned Lesson', + unique_id: '', + date: '', + start_time: '', + end_time: '', + period_code: '', + subject_class: '', + year_group: '', + subject: '', + teacher_code: '', + planning_status: '', + topic_code: '', + topic_name: '', + lesson_code: '', + lesson_name: '', + learning_statement_codes: '', + learning_statements: '', + learning_resource_codes: '', + learning_resources: '', + path: '', + created: '', + merged: '', + } + } +} + +// Relationships +export class GeneralRelationshipShapeUtil extends BaseRelationshipShapeUtil { + static override type = 'general_relationship' as const + static override props = generalRelationshipShapeProps + static override migrations = generalRelationshipShapeMigrations + + getDefaultProps(): GeneralRelationshipShape['props'] { + return { + w: 200, + h: 250, + color: 'black', + __relationshiptype__: '', + source: '', + target: '', + } + } +} + +export const allShapeUtils = [ + DeveloperNodeShapeUtil, + TeacherNodeShapeUtil, + StudentNodeShapeUtil, + UserNodeShapeUtil, + TeacherTimetableNodeShapeUtil, + TimetableLessonNodeShapeUtil, + PlannedLessonNodeShapeUtil, + SchoolNodeShapeUtil, + CalendarNodeShapeUtil, + CalendarYearNodeShapeUtil, + CalendarMonthNodeShapeUtil, + CalendarWeekNodeShapeUtil, + CalendarDayNodeShapeUtil, + CalendarTimeChunkNodeShapeUtil, + ScienceLabNodeShapeUtil, + KeyStageSyllabusNodeShapeUtil, + YearGroupSyllabusNodeShapeUtil, + CurriculumStructureNodeShapeUtil, + TopicNodeShapeUtil, + TopicLessonNodeShapeUtil, + LearningStatementNodeShapeUtil, + SchoolTimetableNodeShapeUtil, + AcademicYearNodeShapeUtil, + AcademicTermNodeShapeUtil, + AcademicWeekNodeShapeUtil, + AcademicDayNodeShapeUtil, + AcademicPeriodNodeShapeUtil, + RegistrationPeriodNodeShapeUtil, + DepartmentNodeShapeUtil, + RoomNodeShapeUtil, + PastoralStructureNodeShapeUtil, + YearGroupNodeShapeUtil, + KeyStageNodeShapeUtil +]; \ No newline at end of file diff --git a/src/utils/tldraw/graph/graphStateUtil.tsx b/src/utils/tldraw/graph/graphStateUtil.tsx new file mode 100644 index 0000000..5b38ff1 --- /dev/null +++ b/src/utils/tldraw/graph/graphStateUtil.tsx @@ -0,0 +1,102 @@ +import dagre from '@dagrejs/dagre'; +import { createShapeId, Editor } from 'tldraw'; + +const graphState = { + g: new dagre.graphlib.Graph(), + nodeData: new Map(), + editor: null as Editor | null, + + initGraph: () => { + graphState.g.setGraph({}); + graphState.g.setDefaultEdgeLabel(() => ({})); + }, + + updateNodesWithDagre: () => { + dagre.layout(graphState.g); + // Update positions in nodeData after layout + graphState.g.nodes().forEach((id) => { + const node = graphState.g.node(id); + if (graphState.nodeData.has(id)) { + const fullNode = graphState.nodeData.get(id); + fullNode.x = node.x; + fullNode.y = node.y; + graphState.nodeData.set(id, fullNode); + } + }); + }, + + updateShapesWithDagre: () => { + console.log("Updating shapes with dagre..."); + if (!graphState.editor) { + console.error("Editor is not set. Call setEditor before updating shapes."); + return; + } + + console.log("Updating nodes with dagre..."); + graphState.updateNodesWithDagre(); + console.log("Nodes updated with dagre..."); + + console.log("Updating set of shapes with dagre..."); + graphState.nodeData.forEach((shape, id) => { + console.log("Updating shape with dagre:", shape, id); + const node = graphState.g.node(id); + console.log("Node without w and h:", node); + const nodeWithWidthAndHeight = { + ...node, + width: shape.w, + height: shape.h + } + console.log("Node with w and h:", nodeWithWidthAndHeight); + + if (nodeWithWidthAndHeight) { + console.log("Updating shape:", shape); + + graphState.editor!.updateShape({ + id: createShapeId(node.label), + type: shape.type, + x: nodeWithWidthAndHeight.x - nodeWithWidthAndHeight.width / 2, + y: nodeWithWidthAndHeight.y - nodeWithWidthAndHeight.height / 2, + }); + } + }); + }, + + addNode: (shape: any) => { + console.log("Adding shape to graphState:", shape); + const id = shape.props.unique_id; + console.log("Adding node to graphState:", id); + graphState.g.setNode(id, { + label: id, + width: shape.props.w, + height: shape.props.h + }); + graphState.nodeData.set(id, shape); + }, + + addEdge: (source: string, target: string) => { + graphState.g.setEdge(source, target); + }, + + getNode: (id: string) => { + return graphState.nodeData.get(id); + }, + + getAllNodes: () => { + return Array.from(graphState.nodeData.values()).filter(item => { + // Check if the item has a type property and it's not an edge type + return item.type && !item.type.includes('relationship'); + }); + }, + + getEdges: () => { + return graphState.g.edges(); + }, + + setEditor: (editor: Editor) => { + graphState.editor = editor; + } +}; + +graphState.initGraph(); + +export default graphState; \ No newline at end of file diff --git a/src/utils/tldraw/graph/nodeComponents.tsx b/src/utils/tldraw/graph/nodeComponents.tsx new file mode 100644 index 0000000..cc63c1b --- /dev/null +++ b/src/utils/tldraw/graph/nodeComponents.tsx @@ -0,0 +1,689 @@ +import React from 'react'; +import { AllNodeShapes } from './graph-shape-types'; + +interface NodeComponentProps { + shape: T; + theme: any; +} + +interface BaseNodeProps { + __primarylabel__: string; + unique_id: string; +} + +interface TeacherNodeProps extends BaseNodeProps { + teacher_name_formal: string; + teacher_code: string; + teacher_email: string; + worker_db_name: string; +} + +interface StudentNodeProps extends BaseNodeProps { + student_name_formal: string; + student_code: string; + student_email: string; + worker_db_name: string; +} + +interface UserNodeProps extends BaseNodeProps { + user_name: string; + user_email: string; + user_type: string; +} + +interface CalendarNodeProps extends BaseNodeProps { + name: string; + start_date: string; + end_date: string; +} + +interface CalendarNodeProps extends BaseNodeProps { + name: string; + start_date: string; + end_date: string; +} + +interface CalendarYearNodeProps extends BaseNodeProps { + year: string; +} + +interface CalendarMonthNodeProps extends BaseNodeProps { + month_name: string; + year: string; +} + +interface CalendarWeekNodeProps extends BaseNodeProps { + start_date: string; + iso_week: string; +} + +interface CalendarDayNodeProps extends BaseNodeProps { + day_of_week: string; + date: string; +} + +interface CalendarTimeChunkNodeProps extends BaseNodeProps { + start_time: string; + end_time: string; +} + +interface CalendarTimeChunkNodeProps extends BaseNodeProps { + start_time: string; + end_time: string; +} + +interface SchoolNodeProps extends BaseNodeProps { + school_name: string; + school_website: string; +} + +interface DepartmentNodeProps extends BaseNodeProps { + department_name: string; +} + +interface RoomNodeProps extends BaseNodeProps { + room_name: string; + room_code: string; +} + +interface SubjectClassNodeProps extends BaseNodeProps { + subject_class_code: string; + year_group: string; + subject: string; +} + +interface PastoralStructureNodeProps extends BaseNodeProps { +} + +interface YearGroupNodeProps extends BaseNodeProps { + year_group: string; +} + +interface CurriculumStructureNodeProps extends BaseNodeProps { +} + +interface KeyStageNodeProps extends BaseNodeProps { + key_stage: string; +} + +interface KeyStageSyllabusNodeProps extends BaseNodeProps { + ks_syllabus_id: string; + ks_syllabus_subject: string; +} + +interface YearGroupSyllabusNodeProps extends BaseNodeProps { + yr_syllabus_id: string; + yr_syllabus_subject: string; +} + +interface SubjectNodeProps extends BaseNodeProps { + subject_name: string; + subject_code: string; +} + +interface TopicNodeProps extends BaseNodeProps { + topic_title: string; + topic_id: string; + total_number_of_lessons_for_topic: string; + topic_type: string; + topic_assessment_type: string; +} + +interface TopicLessonNodeProps extends BaseNodeProps { + topic_lesson_title: string; + topic_lesson_id: string; + topic_lesson_type: string; + topic_lesson_length: string; + topic_lesson_suggested_activities: string; + topic_lesson_skills_learned: string; + topic_lesson_weblinks: string; +} + +interface LearningStatementNodeProps extends BaseNodeProps { + lesson_learning_statement: string; + lesson_learning_statement_id: string; + lesson_learning_statement_type: string; +} + +interface ScienceLabNodeProps extends BaseNodeProps { + science_lab_title: string; + science_lab_id: string; + science_lab_summary: string; + science_lab_requirements: string; + science_lab_procedure: string; + science_lab_safety: string; + science_lab_weblinks: string; +} + +interface SchoolTimetableNodeProps extends BaseNodeProps { + start_date: string; + end_date: string; +} + +interface AcademicYearNodeProps extends BaseNodeProps { + year: string; +} + +interface AcademicTermNodeProps extends BaseNodeProps { + term_name: string; + term_number: string; + start_date: string; + end_date: string; +} + +interface AcademicWeekNodeProps extends BaseNodeProps { + start_date: string; + week_type: string; + academic_week_number: string; +} + +interface AcademicDayNodeProps extends BaseNodeProps { + day_of_week: string; + day_type: string; + date: string; +} + +interface AcademicPeriodNodeProps extends BaseNodeProps { + name: string; + date: string; + start_time: string; + end_time: string; + period_code: string; +} + +interface RegistrationPeriodNodeProps extends BaseNodeProps { + name: string; + date: string; + start_time: string; + end_time: string; + period_code: string; +} + +interface TeacherTimetableNodeProps extends BaseNodeProps { +} + +interface TimetableLessonNodeProps extends BaseNodeProps { + subject_class: string; + date: string; + period_code: string; +} + +interface PlannedLessonNodeProps extends BaseNodeProps { + subject_class: string; + date: string; + period_code: string; + planning_status: string; + teacher_code: string; + year_group: string; + subject: string; +} + +const DefaultNodeComponent: React.FC = ({ shape, theme }) => ( + <> +
+
+ {(shape.props.__primarylabel__).toUpperCase()} +
+
+ +); + +// Users +const UserNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as UserNodeProps; + return ( + <> + +
User Name: {props.user_name}
+
User Email: {props.user_email}
+ + ); +}; + +const DeveloperNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as UserNodeProps; + return ( + <> + +
User Name: {props.user_name}
+
Use Email: {props.user_email}
+ + ); +}; + +const TeacherNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as TeacherNodeProps; + return ( + <> + +
Teacher Name: {props.teacher_name_formal}
+
Teacher Code: {props.teacher_code}
+
Email: {props.teacher_email}
+ + ); +}; + +const StudentNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as StudentNodeProps; + return ( + <> + +
Student Name: {props.student_name_formal}
+
Student Code: {props.student_code}
+
Email: {props.student_email}
+ + ); +}; + +// Calendar +const CalendarNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as CalendarNodeProps; + return ( + <> + +
Calendar Name: {props.name}
+
Start Date: {props.start_date}
+
End Date: {props.end_date}
+ + ); +}; + +const CalendarYearNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as CalendarYearNodeProps; + return ( + <> + +
Year: {props.year}
+ + ); +}; + +const CalendarMonthNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as CalendarMonthNodeProps; + return ( + <> + +
Month: {props.month_name}
+
Year: {props.year}
+ + ); +}; + +const CalendarWeekNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as CalendarWeekNodeProps; + return ( + <> + +
Week Start Date: {props.start_date}
+
ISO Week: {props.iso_week}
+ + ); +}; + +const CalendarDayNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as CalendarDayNodeProps; + return ( + <> + +
Day of Week: {props.day_of_week}
+
Date: {props.date}
+ + ); +}; + +const CalendarTimeChunkNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as CalendarTimeChunkNodeProps; + return ( + <> + +
Start Time: {props.start_time}
+
End Time: {props.end_time}
+ + ); +}; + +// Schools +const SchoolNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as SchoolNodeProps; + return ( + <> + +
School Name: {props.school_name}
+
School Website: {props.school_website}
+ + ); +}; + +const DepartmentNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as DepartmentNodeProps; + return ( + <> + +
Department Name: {props.department_name}
+ + ); +}; + +const RoomNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as RoomNodeProps; + return ( + <> + +
Room Name: {props.room_name}
+
Room Code: {props.room_code}
+ + ); +}; + +const SubjectClassNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as SubjectClassNodeProps; + return ( + <> + +
Subject Class: {props.subject_class_code}
+
Year Group: {props.year_group}
+
Subject: {props.subject}
+ + ); +}; + +// Curriculum +const PastoralStructureNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as PastoralStructureNodeProps; + return ( + <> + + + ); +}; + +const YearGroupNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as YearGroupNodeProps; + return ( + <> + +
Year Group: {props.year_group}
+ + ); +}; + +const CurriculumStructureNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as CurriculumStructureNodeProps; + return ( + <> + + + ); +}; + +const KeyStageNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as KeyStageNodeProps; + return ( + <> + +
Key Stage: {props.key_stage}
+ + ); +}; + +const KeyStageSyllabusNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as KeyStageSyllabusNodeProps; + return ( + <> + +
Syllabus ID: {props.ks_syllabus_id}
+
Subject: {props.ks_syllabus_subject}
+ + ); +}; + +const YearGroupSyllabusNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as YearGroupSyllabusNodeProps; + return ( + <> + +
Syllabus ID: {props.yr_syllabus_id}
+
Subject: {props.yr_syllabus_subject}
+ + ); +}; + +const SubjectNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as SubjectNodeProps; + return ( + <> + +
Subject: {props.subject_name}
+
Code: {props.subject_code}
+ + ); +}; + +const TopicNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as TopicNodeProps; + return ( + <> + +
Title: {props.topic_title}
+
ID: {props.topic_id}
+
Lessons: {props.total_number_of_lessons_for_topic}
+
Type: {props.topic_type}
+
Assessment Type: {props.topic_assessment_type}
+ + ); +}; + +const TopicLessonNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as TopicLessonNodeProps; + return ( + <> + +
Title: {props.topic_lesson_title}
+
ID: {props.topic_lesson_id}
+
Type: {props.topic_lesson_type}
+
Length: {props.topic_lesson_length}
+
Suggested Activities: {props.topic_lesson_suggested_activities}
+
Skills Learned: {props.topic_lesson_skills_learned}
+
Web Links: {props.topic_lesson_weblinks}
+ + ); +}; + +const LearningStatementNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as LearningStatementNodeProps; + return ( + <> + +
Learning Statement: {props.lesson_learning_statement}
+
ID: {props.lesson_learning_statement_id}
+
Type: {props.lesson_learning_statement_type}
+ + ); +}; + + +const ScienceLabNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as ScienceLabNodeProps; + return ( + <> + +
Title: {props.science_lab_title}
+
ID: {props.science_lab_id}
+
Summary: {props.science_lab_summary}
+
Requirements: {props.science_lab_requirements}
+
Procedure: {props.science_lab_procedure}
+
Safety: {props.science_lab_safety}
+
Web Links: {props.science_lab_weblinks}
+ + ); +}; + +// School Timetable +const SchoolTimetableNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as SchoolTimetableNodeProps; + return ( + <> + +
Start Date: {props.start_date}
+
End Date: {props.end_date}
+ + ); +}; + +const AcademicYearNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as AcademicYearNodeProps; + return ( + <> + +
Year: {props.year}
+ + ); +}; + +const AcademicTermNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as AcademicTermNodeProps; + return ( + <> + +
Term Name: {props.term_name}
+
Term Number: {props.term_number}
+
Start Date: {props.start_date}
+
End Date: {props.end_date}
+ + ); +}; + +const AcademicWeekNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as AcademicWeekNodeProps; + return ( + <> + +
Start Date: {props.start_date}
+
Week Type: {props.week_type}
+
Academic Week Number: {props.academic_week_number}
+ + ); +}; + +const AcademicDayNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as AcademicDayNodeProps; + return ( + <> + +
Day of Week: {props.day_of_week}
+
Day Type: {props.day_type}
+
Date: {props.date}
+ + ); +}; + +const AcademicPeriodNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as AcademicPeriodNodeProps; + return ( + <> + +
Name: {props.name}
+
Date: {props.date}
+
Start Time: {props.start_time}
+
End Time: {props.end_time}
+
Period Code: {props.period_code}
+ + ); +}; + + +const RegistrationPeriodNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as RegistrationPeriodNodeProps; + return ( + <> + +
Name: {props.name}
+
Date: {props.date}
+
Start Time: {props.start_time}
+
End Time: {props.end_time}
+
Period Code: {props.period_code}
+ + ); +}; + +// Teacher Timetable +const TeacherTimetableNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as TeacherTimetableNodeProps; + return ( + <> + + + ); +}; + +const TimetableLessonNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as TimetableLessonNodeProps; + return ( + <> + +
Subject Class: {props.subject_class}
+
Date: {props.date}
+
Period Code: {props.period_code}
+ + ); +}; + +const PlannedLessonNodeComponent: React.FC = ({ shape, theme }) => { + const props = shape.props as PlannedLessonNodeProps; + return ( + <> + +
Subject Class: {props.subject_class}
+
Year Group: {props.year_group}
+
Subject: {props.subject}
+
Teacher Code: {props.teacher_code}
+
Planning Status: {props.planning_status}
+ + ); +}; + +const nodeComponents: { [key: string]: React.FC } = { + user_node: UserNodeComponent, + teacher_node: TeacherNodeComponent, + student_node: StudentNodeComponent, + timetable_lesson_node: TimetableLessonNodeComponent, + developer_node: DeveloperNodeComponent, + school_node: SchoolNodeComponent, + department_node: DepartmentNodeComponent, + planned_lesson_node: PlannedLessonNodeComponent, + registration_period_node: RegistrationPeriodNodeComponent, + teacher_timetable_node: TeacherTimetableNodeComponent, + academic_year_node: AcademicYearNodeComponent, + academic_term_node: AcademicTermNodeComponent, + academic_week_node: AcademicWeekNodeComponent, + academic_day_node: AcademicDayNodeComponent, + academic_period_node: AcademicPeriodNodeComponent, + key_stage_node: KeyStageNodeComponent, + key_stage_syllabus_node: KeyStageSyllabusNodeComponent, + year_group_syllabus_node: YearGroupSyllabusNodeComponent, + subject_node: SubjectNodeComponent, + topic_node: TopicNodeComponent, + topic_lesson_node: TopicLessonNodeComponent, + learning_statement_node: LearningStatementNodeComponent, + science_lab_node: ScienceLabNodeComponent, + school_timetable_node: SchoolTimetableNodeComponent, + calendar_node: CalendarNodeComponent, + calendar_year_node: CalendarYearNodeComponent, + calendar_month_node: CalendarMonthNodeComponent, + calendar_week_node: CalendarWeekNodeComponent, + calendar_day_node: CalendarDayNodeComponent, + calendar_time_chunk_node: CalendarTimeChunkNodeComponent, + year_group_node: YearGroupNodeComponent, + pastoral_structure_node: PastoralStructureNodeComponent, + curriculum_structure_node: CurriculumStructureNodeComponent, + room_node: RoomNodeComponent, + subject_class_node: SubjectClassNodeComponent, +}; + +export const getNodeComponent = (shape: AllNodeShapes, theme: any) => { + const Component = nodeComponents[shape.type] || DefaultNodeComponent; + return ; +}; \ No newline at end of file diff --git a/src/utils/userContext.tsx b/src/utils/userContext.tsx new file mode 100644 index 0000000..87ae4c0 --- /dev/null +++ b/src/utils/userContext.tsx @@ -0,0 +1,225 @@ +import { ReactNode, createContext, useContext, useState, useEffect } from 'react'; +import { UserNodeInterface } from '../types/graph_node_types'; +import { TLUser } from 'tldraw'; + +export const getFromLocalStorage = (key: string) => { + const item = localStorage.getItem(key); + if (item === null || item === 'undefined') return null; + try { + return JSON.parse(item); + } catch (error) { + console.error(`Error parsing JSON for key ${key}:`, error); + return null; + } +}; + +export const setToLocalStorage = (key: string, value: any) => { + localStorage.setItem(key, JSON.stringify(value)); +}; + +export const removeFromLocalStorage = (key: string) => { + localStorage.removeItem(key); +}; + +export const setStateAndStorage = (setter: React.Dispatch>, key: string, value: any) => { + setter(value); + setToLocalStorage(key, value); +}; + +const AuthContext = createContext({ + userRole: null as string | null, + firebaseIdToken: null as string | null, + msAccessToken: null as string | null, + neo4jDbName: null as string | null, + userNode: null as UserNodeInterface | null, + tldrawUserFilePath: null as string | null, + oneNoteNotebook: null as any, + isLoading: false, + error: null as string | null, + logout: async () => {}, + getIdToken: async () => Promise.resolve('') as Promise, +}); + +export const AuthProvider = ({ children }: { children: ReactNode }) => { + const [user, setUser] = useState(getFromLocalStorage('user')); + const [isLoading, setIsLoading] = useState(true); + const [userRole, setUserRole] = useState(getFromLocalStorage('userRole')); + const [firebaseIdToken, setToken] = useState(getFromLocalStorage('firebaseIdToken')); + const [msAccessToken, setMsToken] = useState(getFromLocalStorage('msAccessToken')); + const [neo4jDbName, setNeo4jDbName] = useState(getFromLocalStorage('neo4jDbName')); + const [userNode, setUserNode] = useState(getFromLocalStorage('userNode')); + const [tldrawUserFilePath, setTldrawUserFilePath] = useState(getFromLocalStorage('tldrawUserFilePath')); + const [oneNoteNotebook, setOneNoteNotebook] = useState(getFromLocalStorage('oneNoteNotebook')); + const [error, setError] = useState(null); + + + useEffect(() => { + const unsubscribe = auth.onAuthStateChanged(async (user) => { + setIsLoading(true); + try { + if (user) { + console.log("AuthProvider - useEffect - User state changed:", user); + const storedUserRole = getFromLocalStorage('userRole'); + const storedFirebaseIdToken = await user.getIdToken(); + const storedMsAccessToken = getFromLocalStorage('msAccessToken'); + const storedNeo4jDbName = getFromLocalStorage('neo4jDbName'); + const storedUserNode = getFromLocalStorage('userNode'); + const storedOneNoteNotebook = getFromLocalStorage('oneNoteNotebook'); + + setStateAndStorage(setUser, 'user', user); + setStateAndStorage(setUserRole, 'userRole', storedUserRole); + setStateAndStorage(setToken, 'firebaseIdToken', storedFirebaseIdToken); + setStateAndStorage(setMsToken, 'msAccessToken', storedMsAccessToken); + setStateAndStorage(setNeo4jDbName, 'neo4jDbName', storedNeo4jDbName); + setStateAndStorage(setUserNode, 'userNode', storedUserNode); + setStateAndStorage(setTldrawUserFilePath, 'tldrawUserFilePath', storedUserNode?.path); + setStateAndStorage(setOneNoteNotebook, 'oneNoteNotebook', storedOneNoteNotebook); + + console.log("AuthProvider - useEffect - Updated state:", { user, userRole: storedUserRole }); + } else { + setStateAndStorage(setUser, 'user', null); + setStateAndStorage(setUserRole, 'userRole', null); + setStateAndStorage(setToken, 'firebaseIdToken', null); + setStateAndStorage(setMsToken, 'msAccessToken', null); + setStateAndStorage(setNeo4jDbName, 'neo4jDbName', null); + setStateAndStorage(setUserNode, 'userNode', null); + setStateAndStorage(setTldrawUserFilePath, 'tldrawUserFilePath', null); + setStateAndStorage(setOneNoteNotebook, 'oneNoteNotebook', null); + + removeFromLocalStorage('userRole'); + removeFromLocalStorage('msAccessToken'); + removeFromLocalStorage('neo4jDbName'); + removeFromLocalStorage('userNode'); + removeFromLocalStorage('oneNoteNotebook'); + } + } catch (error) { + setError(error instanceof Error ? error.message : 'An unknown error occurred'); + } finally { + setIsLoading(false); + } + }); + + return () => unsubscribe(); + }, []); + + const login = async (email: string, password: string, role: string) => { + try { + const { user, firebaseIdToken, firestoreUserDoc } = await emailLogin(email, password); + const userRole = role || firestoreUserDoc?.userRole || null; + const userNode = await fetchUserNode(user.uid); + + setStateAndStorage(setUser, 'user', user); + setStateAndStorage(setUserRole, 'userRole', userRole); + setStateAndStorage(setToken, 'firebaseIdToken', firebaseIdToken); + setStateAndStorage(setUserNode, 'userNode', userNode); + setStateAndStorage(setTldrawUserFilePath, 'tldrawUserFilePath', userNode.path); + return { user, firebaseIdToken, userNode, userRole, message: 'Login successful' }; + } catch (error) { + setError(error instanceof Error ? error.message : 'An unknown error occurred'); + return { user: null, firebaseIdToken: null, userNode: null, userRole: null, message: 'Login failed' }; + } + }; + + const logout = async () => { + console.log("Logging out..."); + setIsLoading(true); + setError(null); + try { + await logoutUser(); + setStateAndStorage(setUser, 'user', null); + setStateAndStorage(setUserRole, 'userRole', null); + setStateAndStorage(setToken, 'firebaseIdToken', null); + setStateAndStorage(setMsToken, 'msAccessToken', null); + setStateAndStorage(setNeo4jDbName, 'neo4jDbName', null); + setStateAndStorage(setUserNode, 'userNode', null); + setStateAndStorage(setTldrawUserFilePath, 'tldrawUserFilePath', null); + setStateAndStorage(setOneNoteNotebook, 'oneNoteNotebook', null); + removeFromLocalStorage('user'); + removeFromLocalStorage('firebaseIdToken'); + removeFromLocalStorage('msAccessToken'); + removeFromLocalStorage('neo4jDbName'); + removeFromLocalStorage('userNode'); + removeFromLocalStorage('tldrawUserFilePath'); + removeFromLocalStorage('oneNoteNotebook'); + } catch (error) { + setError(error instanceof Error ? error.message : 'An unknown error occurred'); + } finally { + console.log("Finished logging out"); + setIsLoading(false); + } + }; + + const registerUser = async (email: string, password: string, username: string, userRole: string): Promise<{ user: User | null; firebaseIdToken: string | null; userNode: UserNodeInterface | null; userRole: string | null; message: string | null }> => { + try { + const { user, firebaseIdToken, neo4jDbName, userNode, tldrawUserFilePath } = await registerUserWithEmailAndPassword(email, password, username, userRole); + setStateAndStorage(setUser, 'user', user); + setStateAndStorage(setUserRole, 'userRole', userRole); + setStateAndStorage(setToken, 'firebaseIdToken', firebaseIdToken); + setStateAndStorage(setNeo4jDbName, 'neo4jDbName', neo4jDbName); + setStateAndStorage(setUserNode, 'userNode', userNode); + setStateAndStorage(setTldrawUserFilePath, 'tldrawUserFilePath', userNode.path); + return { user, firebaseIdToken, userNode, userRole, message: 'Email user registered successfully' }; + } catch (error) { + return { user: null, firebaseIdToken: null, userNode: null, userRole: null, message: error instanceof Error ? error.message : 'An unknown error occurred' }; + } + }; + + const registerOrLoginWithMicrosoft = async (role: string): Promise<{ user: User | null; firebaseIdToken: string | null; msAccessToken: string | null; userNode: UserNodeInterface | null; userRole: string | null; message: string | null; oneNoteNotebook: any }> => { + try { + console.log("registerOrLoginWithMicrosoft - Starting"); + console.log(`Ready to sign in with Microsoft as ${role}`); + const { user, firebaseIdToken, msAccessToken, neo4jDbName, userNode, oneNoteNotebook, isNewUser } = await signInWithMicrosoft(role); + setStateAndStorage(setUser, 'user', user || null); + setStateAndStorage(setUserRole, 'userRole', role); + setStateAndStorage(setToken, 'firebaseIdToken', firebaseIdToken || null); + setStateAndStorage(setMsToken, 'msAccessToken', msAccessToken || null); + setStateAndStorage(setNeo4jDbName, 'neo4jDbName', neo4jDbName || null); + setStateAndStorage(setUserNode, 'userNode', userNode || null); + setStateAndStorage(setTldrawUserFilePath, 'tldrawUserFilePath', userNode?.path || null); + setStateAndStorage(setOneNoteNotebook, 'oneNoteNotebook', oneNoteNotebook || null); + + console.log(`Signed in with Microsoft as ${role}`); + console.log("OneNote Notebook:", oneNoteNotebook); + setIsLoading(false); + return { user, userRole: role, firebaseIdToken, msAccessToken, userNode, oneNoteNotebook, message: isNewUser ? 'User registered successfully with Microsoft' : 'User logged in successfully with Microsoft' }; + } catch (error) { + setError(error instanceof Error ? error.message : 'An unknown error occurred'); + setIsLoading(false); + return { user: null, userRole: null, firebaseIdToken: null, msAccessToken: null, userNode: null, oneNoteNotebook: null, message: 'Failed to sign in with Microsoft' }; + } + }; + + const getIdToken = async () => { + if (user) { + return await user.getIdToken(true); + } + throw new Error('User not authenticated'); + }; + + return ( + setError(null), + getIdToken, + }} + > + {children} + + ); +}; + +export const useAuth = () => useContext(AuthContext); diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..d3c47cd --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Default", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "importHelpers": true, + "resolveJsonModule": true, + "incremental": true, + "jsx": "react-jsx", + "lib": ["dom", "DOM.Iterable", "esnext"], + "experimentalDecorators": true, + "module": "esnext", + "target": "esnext", + "moduleResolution": "node", + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "skipLibCheck": true, + "strict": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "useDefineForClassFields": true, + "noImplicitOverride": true, + "types": ["node", "@types/jest"] + }, + "exclude": ["node_modules"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..6cddda1 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.base.json", + "include": ["src", "scripts", "vite.config.mts"], + "exclude": ["node_modules", "dist", ".tsbuild*"], + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "types": ["bun-types", "node"], + "strict": true, + "skipLibCheck": true + } +} diff --git a/vite.config.mts b/vite.config.mts new file mode 100644 index 0000000..4a4d7e2 --- /dev/null +++ b/vite.config.mts @@ -0,0 +1,16 @@ +import react from '@vitejs/plugin-react-swc' +import path from 'path' +import { defineConfig } from 'vite' + +export default defineConfig(() => ({ + plugins: [react({ tsDecorators: true })], + root: path.join(__dirname, 'src/client'), + publicDir: path.join(__dirname, 'public'), + server: { + port: 5000, + host: '0.0.0.0', // Expose the server to the network + }, + optimizeDeps: { + exclude: ['assets'], + }, +})) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..6dae779 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,3321 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.26.2": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/compat-data@^7.26.5": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" + integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== + +"@babel/core@^7.23.3": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" + integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.9" + "@babel/helper-compilation-targets" "^7.26.5" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/traverse" "^7.26.9" + "@babel/types" "^7.26.9" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" + integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== + dependencies: + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + +"@babel/helper-annotate-as-pure@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" + integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== + dependencies: + "@babel/types" "^7.25.9" + +"@babel/helper-compilation-targets@^7.26.5": + version "7.26.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8" + integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== + dependencies: + "@babel/compat-data" "^7.26.5" + "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-module-imports@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-plugin-utils@^7.25.9": + version "7.26.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" + integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== + +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/helper-validator-option@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" + integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== + +"@babel/helpers@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" + integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== + dependencies: + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" + +"@babel/parser@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" + integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== + dependencies: + "@babel/types" "^7.26.9" + +"@babel/plugin-syntax-jsx@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" + integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-react-display-name@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz#4b79746b59efa1f38c8695065a92a9f5afb24f7d" + integrity sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-react-jsx-development@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz#8fd220a77dd139c07e25225a903b8be8c829e0d7" + integrity sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.25.9" + +"@babel/plugin-transform-react-jsx@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz#06367940d8325b36edff5e2b9cbe782947ca4166" + integrity sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-syntax-jsx" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/plugin-transform-react-pure-annotations@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz#ea1c11b2f9dbb8e2d97025f43a3b5bc47e18ae62" + integrity sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/preset-react@^7.23.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.26.3.tgz#7c5e028d623b4683c1f83a0bd4713b9100560caa" + integrity sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-transform-react-display-name" "^7.25.9" + "@babel/plugin-transform-react-jsx" "^7.25.9" + "@babel/plugin-transform-react-jsx-development" "^7.25.9" + "@babel/plugin-transform-react-pure-annotations" "^7.25.9" + +"@babel/runtime@^7.21.0": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433" + integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" + integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" + +"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" + integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.25.9", "@babel/types@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" + integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + +"@dagrejs/dagre@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@dagrejs/dagre/-/dagre-1.1.4.tgz#66f9c0e2b558308f2c268f60e2c28f22ee17e339" + integrity sha512-QUTc54Cg/wvmlEUxB+uvoPVKFazM1H18kVHBQNmK2NbrDR5ihOCR6CXLnDSZzMcSQKJtabPUWridBOlJM3WkDg== + dependencies: + "@dagrejs/graphlib" "2.2.4" + +"@dagrejs/graphlib@2.2.4": + version "2.2.4" + resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.4.tgz#d77bfa9ff49e2307c0c6e6b8b26b5dd3c05816c4" + integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== + +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/android-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd" + integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d" + integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1" + integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/darwin-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276" + integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb" + integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/freebsd-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2" + integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4" + integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/linux-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb" + integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a" + integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-ia32@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a" + integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-loong64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72" + integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-mips64el@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289" + integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-ppc64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7" + integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-riscv64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09" + integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-s390x@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829" + integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4" + integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/netbsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462" + integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/openbsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691" + integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/sunos-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273" + integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/win32-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f" + integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-ia32@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03" + integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061" + integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + +"@fastify/ajv-compiler@^3.5.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-3.6.0.tgz#907497a0e62a42b106ce16e279cf5788848e8e79" + integrity sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ== + dependencies: + ajv "^8.11.0" + ajv-formats "^2.1.1" + fast-uri "^2.0.0" + +"@fastify/cors@^9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@fastify/cors/-/cors-9.0.1.tgz#9ddb61b4a61e02749c5c54ca29f1c646794145be" + integrity sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q== + dependencies: + fastify-plugin "^4.0.0" + mnemonist "0.39.6" + +"@fastify/error@^3.3.0", "@fastify/error@^3.4.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@fastify/error/-/error-3.4.1.tgz#b14bb4cac3dd4ec614becbc643d1511331a6425c" + integrity sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ== + +"@fastify/fast-json-stringify-compiler@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz#5df89fa4d1592cbb8780f78998355feb471646d5" + integrity sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA== + dependencies: + fast-json-stringify "^5.7.0" + +"@fastify/merge-json-schemas@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz#3551857b8a17a24e8c799e9f51795edb07baa0bc" + integrity sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA== + dependencies: + fast-deep-equal "^3.1.3" + +"@fastify/websocket@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@fastify/websocket/-/websocket-10.0.1.tgz#ece72340870dfccc0d5abdbe7242c632a5f3340a" + integrity sha512-8/pQIxTPRD8U94aILTeJ+2O3el/r19+Ej5z1O1mXlqplsUH7KzCjAI0sgd5DM/NoPjAi5qLFNIjgM5+9/rGSNw== + dependencies: + duplexify "^4.1.2" + fastify-plugin "^4.0.0" + ws "^8.0.0" + +"@floating-ui/core@^1.6.0": + version "1.6.9" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" + integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw== + dependencies: + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/dom@^1.0.0": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34" + integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== + dependencies: + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/react-dom@^2.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31" + integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" + integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@radix-ui/number@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46" + integrity sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ== + +"@radix-ui/primitive@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" + integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== + +"@radix-ui/react-alert-dialog@^1.0.5": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.6.tgz#52187fdaa5110ed6749e75974e90c3505f788c5d" + integrity sha512-p4XnPqgej8sZAAReCAKgz1REYZEBLR8hU9Pg27wFnCWIMc8g1ccCs0FjBcy05V15VTu8pAePw/VDYeOm/uZ6yQ== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dialog" "1.1.6" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" + +"@radix-ui/react-arrow@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz#30c0d574d7bb10eed55cd7007b92d38b03c6b2ab" + integrity sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg== + dependencies: + "@radix-ui/react-primitive" "2.0.2" + +"@radix-ui/react-collection@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.2.tgz#b45eccca1cb902fd078b237316bd9fa81e621e15" + integrity sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" + +"@radix-ui/react-compose-refs@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec" + integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw== + +"@radix-ui/react-context-menu@^2.1.5": + version "2.2.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.2.6.tgz#752fd1d91f92bba287ef2b558770f4ca7d74523e" + integrity sha512-aUP99QZ3VU84NPsHeaFt4cQUNgJqFsLLOt/RbbWXszZ6MP0DpDyjkFZORr4RpAEx3sUBk+Kc8h13yGtC5Qw8dg== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-menu" "2.1.6" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-context@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" + integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== + +"@radix-ui/react-dialog@1.1.6", "@radix-ui/react-dialog@^1.0.5": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz#65b4465e99ad900f28a98eed9a94bb21ec644bf7" + integrity sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-presence" "1.1.2" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" + +"@radix-ui/react-direction@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" + integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== + +"@radix-ui/react-dismissable-layer@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz#96dde2be078c694a621e55e047406c58cd5fe774" + integrity sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" + +"@radix-ui/react-dropdown-menu@^2.0.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.6.tgz#b66b62648b378370aa3c38e5727fd3bc5b8792a3" + integrity sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-menu" "2.1.6" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-focus-guards@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" + integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== + +"@radix-ui/react-focus-scope@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz#c0a4519cd95c772606a82fc5b96226cd7fdd2602" + integrity sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-id@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-menu@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.6.tgz#05fb1ef3fd7545c8abe61178372902970cdec3ce" + integrity sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.2" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-presence" "1.1.2" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-roving-focus" "1.1.2" + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" + +"@radix-ui/react-popover@^1.0.7": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.6.tgz#699634dbc7899429f657bb590d71fb3ca0904087" + integrity sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.2" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-presence" "1.1.2" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" + +"@radix-ui/react-popper@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.2.tgz#d2e1ee5a9b24419c5936a1b7f6f472b7b412b029" + integrity sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-portal@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8" + integrity sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA== + dependencies: + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-presence@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc" + integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-primitive@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz#ac8b7854d87b0d7af388d058268d9a7eb64ca8ef" + integrity sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w== + dependencies: + "@radix-ui/react-slot" "1.1.2" + +"@radix-ui/react-roving-focus@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz#815d051a54299114a68db6eb8d34c41a3c0a646f" + integrity sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-slider@^1.1.0": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slider/-/react-slider-1.2.3.tgz#f40072e88891d756493f27bb53285e32d0e6af37" + integrity sha512-nNrLAWLjGESnhqBqcCNW4w2nn7LxudyMzeB6VgdyAnFLC6kfQgnAjSL2v6UkQTnDctJBlxrmxfplWS4iYjdUTw== + dependencies: + "@radix-ui/number" "1.1.0" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-previous" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + +"@radix-ui/react-slot@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.2.tgz#daffff7b2bfe99ade63b5168407680b93c00e1c6" + integrity sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + +"@radix-ui/react-toast@^1.1.1": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-toast/-/react-toast-1.2.6.tgz#f8d4bb2217851d221d700ac48fbe866b35023361" + integrity sha512-gN4dpuIVKEgpLn1z5FhzT9mYRUitbfZq9XqN/7kkBMUgFTzTG8x/KszWJugJXHcwxckY8xcKDZPz7kG3o6DsUA== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-presence" "1.1.2" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.2" + +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-use-escape-keydown@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== + +"@radix-ui/react-use-previous@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz#d4dd37b05520f1d996a384eb469320c2ada8377c" + integrity sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og== + +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== + dependencies: + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-visually-hidden@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz#8f6025507eb5d8b4b3215ebfd2c71a6632323a62" + integrity sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q== + dependencies: + "@radix-ui/react-primitive" "2.0.2" + +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== + +"@remix-run/router@1.22.0": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.22.0.tgz#dd8096cb055c475a4de6b35322b8d3b118c17b43" + integrity sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw== + +"@rollup/rollup-android-arm-eabi@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz#731df27dfdb77189547bcef96ada7bf166bbb2fb" + integrity sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw== + +"@rollup/rollup-android-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz#4bea6db78e1f6927405df7fe0faf2f5095e01343" + integrity sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q== + +"@rollup/rollup-darwin-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz#a7aab77d44be3c44a20f946e10160f84e5450e7f" + integrity sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q== + +"@rollup/rollup-darwin-x64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz#c572c024b57ee8ddd1b0851703ace9eb6cc0dd82" + integrity sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw== + +"@rollup/rollup-freebsd-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz#cf74f8113b5a83098a5c026c165742277cbfb88b" + integrity sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA== + +"@rollup/rollup-freebsd-x64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz#39561f3a2f201a4ad6a01425b1ff5928154ecd7c" + integrity sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz#980d6061e373bfdaeb67925c46d2f8f9b3de537f" + integrity sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g== + +"@rollup/rollup-linux-arm-musleabihf@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz#f91a90f30dc00d5a64ac2d9bbedc829cd3cfaa78" + integrity sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA== + +"@rollup/rollup-linux-arm64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz#fac700fa5c38bc13a0d5d34463133093da4c92a0" + integrity sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A== + +"@rollup/rollup-linux-arm64-musl@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz#f50ecccf8c78841ff6df1706bc4782d7f62bf9c3" + integrity sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q== + +"@rollup/rollup-linux-loongarch64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz#5869dc0b28242da6553e2b52af41374f4038cd6e" + integrity sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ== + +"@rollup/rollup-linux-powerpc64le-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz#5cdd9f851ce1bea33d6844a69f9574de335f20b1" + integrity sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw== + +"@rollup/rollup-linux-riscv64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz#ef5dc37f4388f5253f0def43e1440ec012af204d" + integrity sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw== + +"@rollup/rollup-linux-s390x-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz#7dbc3ccbcbcfb3e65be74538dfb6e8dd16178fde" + integrity sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA== + +"@rollup/rollup-linux-x64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz#5783fc0adcab7dc069692056e8ca8d83709855ce" + integrity sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA== + +"@rollup/rollup-linux-x64-musl@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz#00b6c29b298197a384e3c659910b47943003a678" + integrity sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ== + +"@rollup/rollup-win32-arm64-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz#cbfee01f1fe73791c35191a05397838520ca3cdd" + integrity sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ== + +"@rollup/rollup-win32-ia32-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz#95cdbdff48fe6c948abcf6a1d500b2bd5ce33f62" + integrity sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w== + +"@rollup/rollup-win32-x64-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz#4cdb2cfae69cdb7b1a3cc58778e820408075e928" + integrity sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g== + +"@sindresorhus/slugify@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@sindresorhus/slugify/-/slugify-2.2.1.tgz#fa2e2e25d6e1e74a2eeb5e2c37f5ccc516ed2c4b" + integrity sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw== + dependencies: + "@sindresorhus/transliterate" "^1.0.0" + escape-string-regexp "^5.0.0" + +"@sindresorhus/transliterate@^1.0.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz#2309fff65a868047e6d2dd70dec747c5b36a8327" + integrity sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ== + dependencies: + escape-string-regexp "^5.0.0" + +"@socket.io/component-emitter@~3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" + integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== + +"@swc/core-darwin-arm64@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.18.tgz#21415e0b08edbefbc2fc2d4a710a0978f220239d" + integrity sha512-FdGqzAIKVQJu8ROlnHElP59XAUsUzCFSNsou+tY/9ba+lhu8R9v0OI5wXiPErrKGZpQFMmx/BPqqhx3X4SuGNg== + +"@swc/core-darwin-x64@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.10.18.tgz#b50426e95da0fd50895c5ce2eac69fb4aab030f5" + integrity sha512-RZ73gZRituL/ZVLgrW6BYnQ5g8tuStG4cLUiPGJsUZpUm0ullSH6lHFvZTCBNFTfpQChG6eEhi2IdG6DwFp1lw== + +"@swc/core-linux-arm-gnueabihf@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.18.tgz#28fb68d206dbe0d1ab45a422219fe852b804d8c6" + integrity sha512-8iJqI3EkxJuuq21UHoen1VS+QlS23RvynRuk95K+Q2HBjygetztCGGEc+Xelx9a0uPkDaaAtFvds4JMDqb9SAA== + +"@swc/core-linux-arm64-gnu@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.18.tgz#8d8d07590370434f0306a7a8931eb89e47402272" + integrity sha512-8f1kSktWzMB6PG+r8lOlCfXz5E8Qhsmfwonn77T/OfjvGwQaWrcoASh2cdjpk3dydbf8jsKGPQE1lSc7GyjXRQ== + +"@swc/core-linux-arm64-musl@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.18.tgz#2bba59b2d5f2893256993c2f2e88a0fa4abfa9d8" + integrity sha512-4rv+E4VLdgQw6zjbTAauCAEExxChvxMpBUMCiZweTNPKbJJ2dY6BX2WGJ1ea8+RcgqR/Xysj3AFbOz1LBz6dGA== + +"@swc/core-linux-x64-gnu@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.18.tgz#9a89a7c08f0eaa1cf26d8a0a37ca01f765a2a465" + integrity sha512-vTNmyRBVP+sZca+vtwygYPGTNudTU6Gl6XhaZZ7cEUTBr8xvSTgEmYXoK/2uzyXpaTUI4Bmtp1x81cGN0mMoLQ== + +"@swc/core-linux-x64-musl@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.18.tgz#3c0f28e920404be6ee3359fe6ed76051dc742619" + integrity sha512-1TZPReKhFCeX776XaT6wegknfg+g3zODve+r4oslFHI+g7cInfWlxoGNDS3niPKyuafgCdOjme2g3OF+zzxfsQ== + +"@swc/core-win32-arm64-msvc@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.18.tgz#d64c6d990843a63ab57711744a49f2e2f5e72c1c" + integrity sha512-o/2CsaWSN3bkzVQ6DA+BiFKSVEYvhWGA1h+wnL2zWmIDs2Knag54sOEXZkCaf8YQyZesGeXJtPEy9hh/vjJgkA== + +"@swc/core-win32-ia32-msvc@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.18.tgz#5e4c40e406e6b2e073f15bc00c11f7dbca7a7a5c" + integrity sha512-eTPASeJtk4mJDfWiYEiOC6OYUi/N7meHbNHcU8e+aKABonhXrIo/FmnTE8vsUtC6+jakT1TQBdiQ8fzJ1kJVwA== + +"@swc/core-win32-x64-msvc@1.10.18": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.18.tgz#de40a245f947d104658458e370554ca4693f8cdf" + integrity sha512-1Dud8CDBnc34wkBOboFBQud9YlV1bcIQtKSg7zC8LtwR3h+XAaCayZPkpGmmAlCv1DLQPvkF+s0JcaVC9mfffQ== + +"@swc/core@^1.10.15": + version "1.10.18" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.10.18.tgz#4a6b5e10c5f3b059145c4c144cbc10c8bcd45f4f" + integrity sha512-IUWKD6uQYGRy8w2X9EZrtYg1O3SCijlHbCXzMaHQYc1X7yjijQh4H3IVL9ssZZyVp2ZDfQZu4bD5DWxxvpyjvg== + dependencies: + "@swc/counter" "^0.1.3" + "@swc/types" "^0.1.17" + optionalDependencies: + "@swc/core-darwin-arm64" "1.10.18" + "@swc/core-darwin-x64" "1.10.18" + "@swc/core-linux-arm-gnueabihf" "1.10.18" + "@swc/core-linux-arm64-gnu" "1.10.18" + "@swc/core-linux-arm64-musl" "1.10.18" + "@swc/core-linux-x64-gnu" "1.10.18" + "@swc/core-linux-x64-musl" "1.10.18" + "@swc/core-win32-arm64-msvc" "1.10.18" + "@swc/core-win32-ia32-msvc" "1.10.18" + "@swc/core-win32-x64-msvc" "1.10.18" + +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/types@^0.1.17": + version "0.1.17" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.17.tgz#bd1d94e73497f27341bf141abdf4c85230d41e7c" + integrity sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ== + dependencies: + "@swc/counter" "^0.1.3" + +"@tldraw/editor@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/editor/-/editor-3.6.1.tgz#709312c7f68e5edbae0239f7076393c879f429ee" + integrity sha512-ErgdYwyGCWfFE+DCasLBxy7QPSrMcaRaPM4TYj4PugiSeLxcTn80CPH52dyWpwQWyfKHIR/1cE4d+Pce/lIqHQ== + dependencies: + "@tldraw/state" "3.6.1" + "@tldraw/state-react" "3.6.1" + "@tldraw/store" "3.6.1" + "@tldraw/tlschema" "3.6.1" + "@tldraw/utils" "3.6.1" + "@tldraw/validate" "3.6.1" + "@types/core-js" "^2.5.5" + "@use-gesture/react" "^10.2.27" + classnames "^2.3.2" + core-js "^3.31.1" + eventemitter3 "^4.0.7" + idb "^7.1.1" + is-plain-object "^5.0.0" + lodash.isequal "^4.5.0" + +"@tldraw/state-react@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/state-react/-/state-react-3.6.1.tgz#3284c70c624492ff989c15402b61ea607be3cc03" + integrity sha512-UvHXRD709QIaU2ZuQQWK12SMNO8d1hgNyctPb9yC93IkaLfZ3/pFgd+OhIEhJuoeWjVMtseDyTDQ/uSu0wLZwg== + dependencies: + "@tldraw/state" "3.6.1" + "@tldraw/utils" "3.6.1" + +"@tldraw/state@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/state/-/state-3.6.1.tgz#79547bb1a0907a6ff82418adf1ba5ad27f84e487" + integrity sha512-5iScpRQoiGdfKuWZuYLw3jevC0R2rtPhmibk+BOW/HDzSw8AIwjgOpPE3WyexKvvdYt84HPWolDuzUkhQ8lBBA== + dependencies: + "@tldraw/utils" "3.6.1" + +"@tldraw/store@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/store/-/store-3.6.1.tgz#ab9268665bf6fa0dc7dba74ba950afada67ee037" + integrity sha512-FjkK+nPx9RzzJf0YfUZ2Cvc0+d9D4KZjuPmJ4+Xeapmx9ovfrGJT3FCo7JZFpapMYMGl/cKcqIrUD5OrjE0ybg== + dependencies: + "@tldraw/state" "3.6.1" + "@tldraw/utils" "3.6.1" + lodash.isequal "^4.5.0" + +"@tldraw/sync-core@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/sync-core/-/sync-core-3.6.1.tgz#a872df972d0eb1ecefcfda97c1e2b82dfc3660e0" + integrity sha512-DYmKq1jqM3BRhZLVwAmC6kGDwTWyyK5YqgeFemcRNLdp6Sd0XBUCvXgefemsKMirPfaZLOPfo7A8tNxw+3XgDg== + dependencies: + "@tldraw/state" "3.6.1" + "@tldraw/store" "3.6.1" + "@tldraw/tlschema" "3.6.1" + "@tldraw/utils" "3.6.1" + lodash.isequal "^4.5.0" + nanoevents "^7.0.1" + ws "^8.16.0" + +"@tldraw/sync@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/sync/-/sync-3.6.1.tgz#f1d89d327504b8900cf53c3c4b6be0ffd0233ad3" + integrity sha512-gfT7nf8nAVQYrYx477aj9mpfjRH3GryICzvD4WzmV0W5DeGGFTrpjPP0XbQQ0r0HHYKyY7fOByEpp/+RvnK46g== + dependencies: + "@tldraw/state" "3.6.1" + "@tldraw/state-react" "3.6.1" + "@tldraw/sync-core" "3.6.1" + "@tldraw/utils" "3.6.1" + lodash.isequal "^4.5.0" + nanoevents "^7.0.1" + tldraw "3.6.1" + ws "^8.16.0" + +"@tldraw/tlschema@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/tlschema/-/tlschema-3.6.1.tgz#b273de9ce1650f9c181bb45d17a723f67cf26e12" + integrity sha512-frIvPletM7N4yh7cNsXwr2VHuD+dsXmYatxvLO+HuS91/XadJv/fSFXerBqQ/y4lU+7UjqKMRi6ey9nL28oM6Q== + dependencies: + "@tldraw/state" "3.6.1" + "@tldraw/store" "3.6.1" + "@tldraw/utils" "3.6.1" + "@tldraw/validate" "3.6.1" + +"@tldraw/utils@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/utils/-/utils-3.6.1.tgz#f4f3379e9ec3ff9a57b3612db9657c8ebd91fddc" + integrity sha512-LBEwG8bj5xl/+JOQJQsqZy3v5xGMVxdKzRSHIDx1Wcho67ijzUGztLikR8Rk8jSTtLp+YWK81/wSpJKi6gczJA== + dependencies: + fractional-indexing-jittered "^0.9.1" + lodash.throttle "^4.1.1" + lodash.uniq "^4.5.0" + +"@tldraw/validate@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@tldraw/validate/-/validate-3.6.1.tgz#233f685c6196edcec9530e0d5b4615189c4c70e9" + integrity sha512-oFEfVcrFWnVO+DcW+ys8NfgiWVctL7uDCf6g13iax4aN0gTu1HiJYkNIsTUcIe7Uji3LZ9BZlm9fthGg6yvQ4Q== + dependencies: + "@tldraw/utils" "3.6.1" + +"@types/body-parser@*": + version "1.19.5" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bun@^1.1.6": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/bun/-/bun-1.2.2.tgz#ebcc7a5f925166a4e9df3d7c93b0b1b4bca75446" + integrity sha512-tr74gdku+AEDN5ergNiBnplr7hpDp3V1h7fqI2GcR/rsUaM39jpSeKH0TFibRvU0KwniRx5POgaYnaXbk0hU+w== + dependencies: + bun-types "1.2.2" + +"@types/connect@*": + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + +"@types/core-js@^2.5.5": + version "2.5.8" + resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.8.tgz#d5c6ec44f2f3328653dce385ae586bd8261f8e85" + integrity sha512-VgnAj6tIAhJhZdJ8/IpxdatM8G4OD3VWGlp6xIxUGENZlpbob9Ty4VVdC1FIEp0aK6DBscDDjyzy5FB60TuNqg== + +"@types/estree@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/express-serve-static-core@^4.17.33": + version "4.19.6" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" + integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + +"@types/express@^4.17.21": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + +"@types/node@*": + version "22.13.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.5.tgz#23add1d71acddab2c6a4d31db89c0f98d330b511" + integrity sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg== + dependencies: + undici-types "~6.20.0" + +"@types/node@^20.11.0": + version "20.17.19" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.19.tgz#0f2869555719bef266ca6e1827fcdca903c1a697" + integrity sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A== + dependencies: + undici-types "~6.19.2" + +"@types/prop-types@*": + version "15.7.14" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2" + integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== + +"@types/qs@*": + version "6.9.18" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.18.tgz#877292caa91f7c1b213032b34626505b746624c2" + integrity sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA== + +"@types/range-parser@*": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== + +"@types/react-dom@^18.2.0": + version "18.3.5" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.5.tgz#45f9f87398c5dcea085b715c58ddcf1faf65f716" + integrity sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q== + +"@types/react@^18.2.0": + version "18.3.18" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.18.tgz#9b382c4cd32e13e463f97df07c2ee3bbcd26904b" + integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-static@*": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + +"@types/ws@^8.5.10", "@types/ws@~8.5.10": + version "8.5.14" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.14.tgz#93d44b268c9127d96026cf44353725dd9b6c3c21" + integrity sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw== + dependencies: + "@types/node" "*" + +"@use-gesture/core@10.3.1": + version "10.3.1" + resolved "https://registry.yarnpkg.com/@use-gesture/core/-/core-10.3.1.tgz#976c9421e905f0079d49822cfd5c2e56b808fc56" + integrity sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw== + +"@use-gesture/react@^10.2.27": + version "10.3.1" + resolved "https://registry.yarnpkg.com/@use-gesture/react/-/react-10.3.1.tgz#17a743a894d9bd9a0d1980c618f37f0164469867" + integrity sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g== + dependencies: + "@use-gesture/core" "10.3.1" + +"@vitejs/plugin-react-swc@^3.7.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-swc/-/plugin-react-swc-3.8.0.tgz#3af56d6dbfe3734e2970d8b9345f261353e2d676" + integrity sha512-T4sHPvS+DIqDP51ifPqa9XIRAz/kIvIi8oXcnOZZgHmMotgmmdxe/DD5tMFlt5nuIRzT0/QuiwmKlH0503Aapw== + dependencies: + "@swc/core" "^1.10.15" + +abstract-logging@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" + integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + +ajv@^8.0.0, ajv@^8.10.0, ajv@^8.11.0: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +aria-hidden@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" + integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== + dependencies: + tslib "^2.0.0" + +asn1.js@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + +avvio@^8.3.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/avvio/-/avvio-8.4.0.tgz#7cbd5bca74f0c9effa944ced601f94ffd8afc5ed" + integrity sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA== + dependencies: + "@fastify/error" "^3.3.0" + fastq "^1.17.1" + +axios@^1.7.2: + version "1.7.9" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" + integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.1.tgz#215741fe3c9dba2d7e12c001d0cfdbae43975ba7" + integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browserify-aes@^1.0.4, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.1.tgz#06e530907fe2949dc21fc3c2e2302e10b1437238" + integrity sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ== + dependencies: + bn.js "^5.2.1" + randombytes "^2.1.0" + safe-buffer "^5.2.1" + +browserify-sign@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" + integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== + dependencies: + bn.js "^5.2.1" + browserify-rsa "^4.1.0" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.5" + hash-base "~3.0" + inherits "^2.0.4" + parse-asn1 "^5.1.7" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" + +browserslist@^4.24.0: + version "4.24.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" + integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== + dependencies: + caniuse-lite "^1.0.30001688" + electron-to-chromium "^1.5.73" + node-releases "^2.0.19" + update-browserslist-db "^1.1.1" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +bun-types@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bun-types/-/bun-types-1.2.2.tgz#06db618bb0b58939094fa22f2cb1b80df6666fae" + integrity sha512-RCbMH5elr9gjgDGDhkTTugA21XtJAy/9jkKe/G3WR2q17VPGhcquf9Sir6uay9iW+7P/BV0CAHA1XlHXMAVKHg== + dependencies: + "@types/node" "*" + "@types/ws" "~8.5.10" + +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + +call-bind-apply-helpers@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +caniuse-lite@^1.0.30001688: + version "1.0.30001700" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6" + integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ== + +canvas-size@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/canvas-size/-/canvas-size-1.2.6.tgz#1eaa6b56167cf2a70fa4021680829d2073b45706" + integrity sha512-x2iVHOrZ5x9V0Hwx6kBz+Yxf/VCAII+jrD6WLjJbytJLozHq/oDJjEva432Os0eHxWMFR0vYlLJwTr6QxyxQqw== + +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== + dependencies: + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@^1.0.0-rc.12: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0.tgz#1ede4895a82f26e8af71009f961a9b8cb60d6a81" + integrity sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.1.0" + encoding-sniffer "^0.2.0" + htmlparser2 "^9.1.0" + parse5 "^7.1.2" + parse5-htmlparser2-tree-adapter "^7.0.0" + parse5-parser-stream "^7.1.2" + undici "^6.19.5" + whatwg-mimetype "^4.0.0" + +ci-info@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.6.tgz#8fe672437d01cd6c4561af5334e0cc50ff1955f7" + integrity sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw== + dependencies: + inherits "^2.0.4" + safe-buffer "^5.2.1" + +classnames@^2.3.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concurrently@^8.2.2: + version "8.2.2" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-8.2.2.tgz#353141985c198cfa5e4a3ef90082c336b5851784" + integrity sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg== + dependencies: + chalk "^4.1.2" + date-fns "^2.30.0" + lodash "^4.17.21" + rxjs "^7.8.1" + shell-quote "^1.8.1" + spawn-command "0.0.2" + supports-color "^8.1.1" + tree-kill "^1.2.2" + yargs "^17.7.2" + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cookie@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== + +core-js@^3.31.1: + version "3.40.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.40.0.tgz#2773f6b06877d8eda102fc42f828176437062476" + integrity sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +create-ecdh@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^7.0.3: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-browserify@^3.12.0: + version "3.12.1" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.1.tgz#bb8921bec9acc81633379aa8f52d69b0b69e0dac" + integrity sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ== + dependencies: + browserify-cipher "^1.0.1" + browserify-sign "^4.2.3" + create-ecdh "^4.0.4" + create-hash "^1.2.0" + create-hmac "^1.1.7" + diffie-hellman "^5.0.3" + hash-base "~3.0.4" + inherits "^2.0.4" + pbkdf2 "^3.1.2" + public-encrypt "^4.0.3" + randombytes "^2.1.0" + randomfill "^1.0.4" + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +csstype@^3.0.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +date-fns@^2.30.0: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.3.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + +debug@~4.3.1, debug@~4.3.2: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +des.js@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + +diffie-hellman@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^3.0.1, domutils@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" + integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +duplexify@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" + integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.2" + +electron-to-chromium@^1.5.73: + version "1.5.103" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.103.tgz#3d02025bc16e96e5edb3ed3ffa2538a11ae682dc" + integrity sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA== + +elliptic@^6.5.3, elliptic@^6.5.5: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encoding-sniffer@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz#799569d66d443babe82af18c9f403498365ef1d5" + integrity sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg== + dependencies: + iconv-lite "^0.6.3" + whatwg-encoding "^3.1.1" + +end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +engine.io-client@~6.6.1: + version "6.6.3" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.6.3.tgz#815393fa24f30b8e6afa8f77ccca2f28146be6de" + integrity sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + engine.io-parser "~5.2.1" + ws "~8.17.1" + xmlhttprequest-ssl "~2.1.1" + +engine.io-parser@~5.2.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== + +entities@^4.2.0, entities@^4.4.0, entities@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +esbuild@^0.17.15: + version "0.17.19" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955" + integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw== + optionalDependencies: + "@esbuild/android-arm" "0.17.19" + "@esbuild/android-arm64" "0.17.19" + "@esbuild/android-x64" "0.17.19" + "@esbuild/darwin-arm64" "0.17.19" + "@esbuild/darwin-x64" "0.17.19" + "@esbuild/freebsd-arm64" "0.17.19" + "@esbuild/freebsd-x64" "0.17.19" + "@esbuild/linux-arm" "0.17.19" + "@esbuild/linux-arm64" "0.17.19" + "@esbuild/linux-ia32" "0.17.19" + "@esbuild/linux-loong64" "0.17.19" + "@esbuild/linux-mips64el" "0.17.19" + "@esbuild/linux-ppc64" "0.17.19" + "@esbuild/linux-riscv64" "0.17.19" + "@esbuild/linux-s390x" "0.17.19" + "@esbuild/linux-x64" "0.17.19" + "@esbuild/netbsd-x64" "0.17.19" + "@esbuild/openbsd-x64" "0.17.19" + "@esbuild/sunos-x64" "0.17.19" + "@esbuild/win32-arm64" "0.17.19" + "@esbuild/win32-ia32" "0.17.19" + "@esbuild/win32-x64" "0.17.19" + +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + +eventemitter3@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +fast-content-type-parse@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz#4087162bf5af3294d4726ff29b334f72e3a1092c" + integrity sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ== + +fast-decode-uri-component@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" + integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== + +fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-json-stringify@^5.7.0, fast-json-stringify@^5.8.0: + version "5.16.1" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.16.1.tgz#a6d0c575231a3a08c376a00171d757372f2ca46e" + integrity sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g== + dependencies: + "@fastify/merge-json-schemas" "^0.1.0" + ajv "^8.10.0" + ajv-formats "^3.0.1" + fast-deep-equal "^3.1.3" + fast-uri "^2.1.0" + json-schema-ref-resolver "^1.0.1" + rfdc "^1.2.0" + +fast-querystring@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53" + integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg== + dependencies: + fast-decode-uri-component "^1.0.1" + +fast-redact@^3.1.1: + version "3.5.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" + integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== + +fast-uri@^2.0.0, fast-uri@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.4.0.tgz#67eae6fbbe9f25339d5d3f4c4234787b65d7d55e" + integrity sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA== + +fast-uri@^3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" + integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== + +fastify-plugin@^4.0.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-4.5.1.tgz#44dc6a3cc2cce0988bc09e13f160120bbd91dbee" + integrity sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ== + +fastify@^4.28.1: + version "4.29.0" + resolved "https://registry.yarnpkg.com/fastify/-/fastify-4.29.0.tgz#ea3fcd92f4d9deaa841a6722dc6e3e7ff9392850" + integrity sha512-MaaUHUGcCgC8fXQDsDtioaCcag1fmPJ9j64vAKunqZF4aSub040ZGi/ag8NGE2714yREPOKZuHCfpPzuUD3UQQ== + dependencies: + "@fastify/ajv-compiler" "^3.5.0" + "@fastify/error" "^3.4.0" + "@fastify/fast-json-stringify-compiler" "^4.3.0" + abstract-logging "^2.0.1" + avvio "^8.3.0" + fast-content-type-parse "^1.1.0" + fast-json-stringify "^5.8.0" + find-my-way "^8.0.0" + light-my-request "^5.11.0" + pino "^9.0.0" + process-warning "^3.0.0" + proxy-addr "^2.0.7" + rfdc "^1.3.0" + secure-json-parse "^2.7.0" + semver "^7.5.4" + toad-cache "^3.3.0" + +fastq@^1.17.1: + version "1.19.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89" + integrity sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA== + dependencies: + reusify "^1.0.4" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-my-way@^8.0.0: + version "8.2.2" + resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-8.2.2.tgz#f3e78bc6ead2da4fdaa201335da3228600ed0285" + integrity sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA== + dependencies: + fast-deep-equal "^3.1.3" + fast-querystring "^1.0.0" + safe-regex2 "^3.1.0" + +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + +form-data@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c" + integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fractional-indexing-jittered@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/fractional-indexing-jittered/-/fractional-indexing-jittered-0.9.1.tgz#d1bf552cb0ab460ba992000c108b19c894900ba0" + integrity sha512-qyzDZ7JXWf/yZT2rQDpQwFBbIaZS2o+zb0s740vqreXQ6bFQPd8tAy4D1gGN0CUeIcnNHjuvb0EaLnqHhGV/PA== + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044" + integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + function-bind "^1.1.2" + get-proto "^1.0.0" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + +get-proto@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash-base@~3.0, hash-base@~3.0.4: + version "3.0.5" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.5.tgz#52480e285395cf7fba17dc4c9e47acdc7f248a8a" + integrity sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg== + dependencies: + inherits "^2.0.4" + safe-buffer "^5.2.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hotkeys-js@^3.11.2: + version "3.13.9" + resolved "https://registry.yarnpkg.com/hotkeys-js/-/hotkeys-js-3.13.9.tgz#e2f976dddfa695a4a40ee60d7888e3cf7637a77a" + integrity sha512-3TRCj9u9KUH6cKo25w4KIdBfdBfNRjfUwrljCLDC2XhmPDG0SjAZFcFZekpUZFmXzfYoGhFDcdx2gX/vUVtztQ== + +htmlparser2@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" + +htmlparser2@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.1.0.tgz#cdb498d8a75a51f739b61d3f718136c369bc8c23" + integrity sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.1.0" + entities "^4.5.0" + +iconv-lite@0.6.3, iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +idb@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" + integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== + +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +itty-router@^5.0.17: + version "5.0.18" + resolved "https://registry.yarnpkg.com/itty-router/-/itty-router-5.0.18.tgz#d2ba2e751c364c78178604fac598b5072325b412" + integrity sha512-mK3ReOt4ARAGy0V0J7uHmArG2USN2x0zprZ+u+YgmeRjXTDbaowDy3kPcsmQY6tH+uHhDgpWit9Vqmv/4rTXwA== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-schema-ref-resolver@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz#6586f483b76254784fc1d2120f717bdc9f0a99bf" + integrity sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw== + dependencies: + fast-deep-equal "^3.1.3" + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +lazyrepo@0.0.0-alpha.27: + version "0.0.0-alpha.27" + resolved "https://registry.yarnpkg.com/lazyrepo/-/lazyrepo-0.0.0-alpha.27.tgz#766aee234533d34d6c15fb7647580483c91daf2c" + integrity sha512-tnOEmd6fiWqgkLNt6AoCRzHFQegW5ZfdQ2z+cTbz9JdD5paOorPz7XZRpc6t/LrobwCf5Yqc/VSRtH3fNBLQdw== + dependencies: + "@sindresorhus/slugify" "^2.2.0" + cac "^6.7.14" + ci-info "^3.8.0" + cross-spawn "^7.0.3" + esbuild "^0.17.15" + fast-json-stable-stringify "^2.1.0" + micromatch "^4.0.5" + picocolors "^1.0.0" + slash "^5.0.1" + slice-ansi "^6.0.0" + source-map-support "^0.5.21" + strip-ansi "^7.0.1" + ts-dedent "^2.2.0" + yaml "^2.2.1" + zod "^3.21.4" + zod-validation-error "^1.3.0" + +light-my-request@^5.11.0: + version "5.14.0" + resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-5.14.0.tgz#11ddae56de4053fd5c1845cbfbee5c29e8a257e7" + integrity sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA== + dependencies: + cookie "^0.7.0" + process-warning "^3.0.0" + set-cookie-parser "^2.4.1" + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lz-string@^1.4.4: + version "1.5.0" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +micromatch@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +mnemonist@0.39.6: + version "0.39.6" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.39.6.tgz#0b3c9b7381d9edf6ce1957e74b25a8ad25732f57" + integrity sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA== + dependencies: + obliterator "^2.0.1" + +ms@^2.1.1, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoevents@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/nanoevents/-/nanoevents-7.0.1.tgz#181580b47787688d8cac775b977b1cf24e26e570" + integrity sha512-o6lpKiCxLeijK4hgsqfR6CNToPyRU3keKyyI6uwuHRvpRTbZ0wXw51WRgyldVugZqoJfkGFrjrIenYH3bfEO3Q== + +nanoid@^3.3.8: + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== + +node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +obliterator@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.5.tgz#031e0145354b0c18840336ae51d41e7d6d2c76aa" + integrity sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw== + +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + +once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +parse-asn1@^5.0.0, parse-asn1@^5.1.7: + version "5.1.7" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" + integrity sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg== + dependencies: + asn1.js "^4.10.1" + browserify-aes "^1.2.0" + evp_bytestokey "^1.0.3" + hash-base "~3.0" + pbkdf2 "^3.1.2" + safe-buffer "^5.2.1" + +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz#b5a806548ed893a43e24ccb42fbb78069311e81b" + integrity sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g== + dependencies: + domhandler "^5.0.3" + parse5 "^7.0.0" + +parse5-parser-stream@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz#d7c20eadc37968d272e2c02660fff92dd27e60e1" + integrity sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow== + dependencies: + parse5 "^7.0.0" + +parse5@^7.0.0, parse5@^7.1.2: + version "7.2.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.2.1.tgz#8928f55915e6125f430cc44309765bf17556a33a" + integrity sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ== + dependencies: + entities "^4.5.0" + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +pbkdf2@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picocolors@^1.0.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pino-abstract-transport@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60" + integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw== + dependencies: + split2 "^4.0.0" + +pino-std-serializers@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" + integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== + +pino@^9.0.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-9.6.0.tgz#6bc628159ba0cc81806d286718903b7fc6b13169" + integrity sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.1.1" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^2.0.0" + pino-std-serializers "^7.0.0" + process-warning "^4.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^3.0.0" + +postcss@^8.4.43: + version "8.5.3" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" + integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== + dependencies: + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process-warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b" + integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ== + +process-warning@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.1.tgz#5c1db66007c67c756e4e09eb170cdece15da32fb" + integrity sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q== + +proxy-addr@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +public-encrypt@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +react-dom@^18.2.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.2" + +react-remove-scroll-bar@^2.3.7: + version "2.3.8" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" + integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== + dependencies: + react-style-singleton "^2.2.2" + tslib "^2.0.0" + +react-remove-scroll@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2" + integrity sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ== + dependencies: + react-remove-scroll-bar "^2.3.7" + react-style-singleton "^2.2.3" + tslib "^2.1.0" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.3" + +react-router-dom@^6.24.1: + version "6.29.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.29.0.tgz#2ffb56b03ef3d6d6daafcfad9f3922132d2ced94" + integrity sha512-pkEbJPATRJ2iotK+wUwHfy0xs2T59YPEN8BQxVCPeBZvK7kfPESRc/nyxzdcxR17hXgUPYx2whMwl+eo9cUdnQ== + dependencies: + "@remix-run/router" "1.22.0" + react-router "6.29.0" + +react-router@6.29.0: + version "6.29.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.29.0.tgz#14a329ca838b4de048fc5cca82874b727ee546b7" + integrity sha512-DXZJoE0q+KyeVw75Ck6GkPxFak63C4fGqZGNijnWgzB/HzSP1ZfTlBj5COaGWwhrMQ/R8bXiq5Ooy4KG+ReyjQ== + dependencies: + "@remix-run/router" "1.22.0" + +react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" + integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== + dependencies: + get-nonce "^1.0.0" + tslib "^2.0.0" + +react@^18.2.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== + dependencies: + loose-envify "^1.1.0" + +readable-stream@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +ret@~0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.4.3.tgz#5243fa30e704a2e78a9b9b1e86079e15891aa85c" + integrity sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rfdc@^1.2.0, rfdc@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rollup@^4.20.0: + version "4.34.8" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.34.8.tgz#e859c1a51d899aba9bcf451d4eed1d11fb8e2a6e" + integrity sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ== + dependencies: + "@types/estree" "1.0.6" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.34.8" + "@rollup/rollup-android-arm64" "4.34.8" + "@rollup/rollup-darwin-arm64" "4.34.8" + "@rollup/rollup-darwin-x64" "4.34.8" + "@rollup/rollup-freebsd-arm64" "4.34.8" + "@rollup/rollup-freebsd-x64" "4.34.8" + "@rollup/rollup-linux-arm-gnueabihf" "4.34.8" + "@rollup/rollup-linux-arm-musleabihf" "4.34.8" + "@rollup/rollup-linux-arm64-gnu" "4.34.8" + "@rollup/rollup-linux-arm64-musl" "4.34.8" + "@rollup/rollup-linux-loongarch64-gnu" "4.34.8" + "@rollup/rollup-linux-powerpc64le-gnu" "4.34.8" + "@rollup/rollup-linux-riscv64-gnu" "4.34.8" + "@rollup/rollup-linux-s390x-gnu" "4.34.8" + "@rollup/rollup-linux-x64-gnu" "4.34.8" + "@rollup/rollup-linux-x64-musl" "4.34.8" + "@rollup/rollup-win32-arm64-msvc" "4.34.8" + "@rollup/rollup-win32-ia32-msvc" "4.34.8" + "@rollup/rollup-win32-x64-msvc" "4.34.8" + fsevents "~2.3.2" + +rxjs@^7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex2@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-3.1.0.tgz#fd7ec23908e2c730e1ce7359a5b72883a87d2763" + integrity sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug== + dependencies: + ret "~0.4.0" + +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== + dependencies: + loose-envify "^1.1.0" + +secure-json-parse@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" + integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + +set-cookie-parser@^2.4.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" + integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a" + integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA== + +slash@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" + integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== + +slice-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-6.0.0.tgz#f08a1e6703e3598256b667f015ccef9f12c59f7c" + integrity sha512-6bn4hRfkTvDfUoEQYkERg0BVF1D0vrX9HEkMl08uDiNWvVvjylLHvZFZWkDo6wjT8tUctbYl1nCOuE66ZTaUtA== + dependencies: + ansi-styles "^6.2.1" + is-fullwidth-code-point "^4.0.0" + +socket.io-client@^4.8.0: + version "4.8.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.8.1.tgz#1941eca135a5490b94281d0323fe2a35f6f291cb" + integrity sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.2" + engine.io-client "~6.6.1" + socket.io-parser "~4.2.4" + +socket.io-parser@~4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + +sonic-boom@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" + integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww== + dependencies: + atomic-sleep "^1.0.0" + +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map-support@^0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spawn-command@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" + integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== + +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + +stream-shift@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +thread-stream@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" + integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== + dependencies: + real-require "^0.2.0" + +tldraw@3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/tldraw/-/tldraw-3.6.1.tgz#85371045d51fc3c21b9959c6d183f5d931938499" + integrity sha512-fXyyZ0r1HJhNzRZONesIVlWjdhY3n+Px+EhYe0E5wGLG4oP5vqBAP9eIQ2QVZ0ZqGH1QpMGgCgs+OXdsUH2Exg== + dependencies: + "@radix-ui/react-alert-dialog" "^1.0.5" + "@radix-ui/react-context-menu" "^2.1.5" + "@radix-ui/react-dialog" "^1.0.5" + "@radix-ui/react-dropdown-menu" "^2.0.6" + "@radix-ui/react-popover" "^1.0.7" + "@radix-ui/react-slider" "^1.1.0" + "@radix-ui/react-toast" "^1.1.1" + "@tldraw/editor" "3.6.1" + "@tldraw/store" "3.6.1" + canvas-size "^1.2.6" + classnames "^2.3.2" + hotkeys-js "^3.11.2" + idb "^7.1.1" + lz-string "^1.4.4" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toad-cache@^3.3.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441" + integrity sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + +tslib@^2.0.0, tslib@^2.1.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +typescript@^5.3.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" + integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== + +undici@^6.19.5: + version "6.21.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.1.tgz#336025a14162e6837e44ad7b819b35b6c6af0e05" + integrity sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ== + +unfurl.js@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/unfurl.js/-/unfurl.js-6.4.0.tgz#222cfc95b71d26529b5baa5dde9813019fa87c67" + integrity sha512-DogJFWPkOWMcu2xPdpmbcsL+diOOJInD3/jXOv6saX1upnWmMK8ndAtDWUfJkuInqNI9yzADud4ID9T+9UeWCw== + dependencies: + debug "^3.2.7" + he "^1.2.0" + htmlparser2 "^8.0.1" + iconv-lite "^0.4.24" + node-fetch "^2.6.7" + +update-browserslist-db@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" + integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +use-callback-ref@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" + integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== + dependencies: + tslib "^2.0.0" + +use-sidecar@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" + integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +vite@^5.3.3: + version "5.4.14" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.14.tgz#ff8255edb02134df180dcfca1916c37a6abe8408" + integrity sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA== + dependencies: + esbuild "^0.21.3" + postcss "^8.4.43" + rollup "^4.20.0" + optionalDependencies: + fsevents "~2.3.3" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-encoding@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== + dependencies: + iconv-lite "0.6.3" + +whatwg-mimetype@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@^8.0.0, ws@^8.16.0: + version "8.18.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" + integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w== + +ws@~8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +xmlhttprequest-ssl@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz#e9e8023b3f29ef34b97a859f584c5e6c61418e23" + integrity sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yaml@^2.2.1: + version "2.7.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" + integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +zod-validation-error@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-1.5.0.tgz#2b355007a1c3b7fb04fa476bfad4e7b3fd5491e3" + integrity sha512-/7eFkAI4qV0tcxMBB/3+d2c1P6jzzZYdYSlBuAklzMuCrJu5bzJfHS0yVAS87dRHVlhftd6RFJDIvv03JgkSbw== + +zod@^3.21.4: + version "3.24.2" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.2.tgz#8efa74126287c675e92f46871cfc8d15c34372b3" + integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==