From fe2d9a31e39175a252b3c6696c72c27142186428 Mon Sep 17 00:00:00 2001 From: Replit Agent Date: Wed, 18 Mar 2026 23:52:06 +0000 Subject: [PATCH] docs: add direction field to README custom-agent example --- .gitignore | 4 + README.md | 80 ++++ index.html | 60 +++ js/agent-defs.js | 28 ++ js/agents.js | 157 ++++++++ js/effects.js | 85 ++++ js/interaction.js | 21 + js/main.js | 49 +++ js/ui.js | 84 ++++ js/websocket.js | 115 ++++++ js/world.js | 60 +++ package-lock.json | 996 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 17 + vite.config.js | 13 + 14 files changed, 1769 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 index.html create mode 100644 js/agent-defs.js create mode 100644 js/agents.js create mode 100644 js/effects.js create mode 100644 js/interaction.js create mode 100644 js/main.js create mode 100644 js/ui.js create mode 100644 js/websocket.js create mode 100644 js/world.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 vite.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f99f737 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +.DS_Store +*.local diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a4d063 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# Timmy Tower World + +A Three.js 3D visualization of the Timmy agent network. Agents appear as +glowing icosahedra connected by lines, pulsing as they process jobs. A +matrix-rain particle effect fills the background. + +## Quick start + +```bash +npm install +npm run dev # Vite dev server with hot reload → http://localhost:5173 +npm run build # Production bundle → dist/ +npm run preview # Serve dist/ locally +``` + +## Configuration + +Set these in a `.env.local` file (not committed): + +``` +VITE_WS_URL=ws://localhost:8080/ws/agents +``` + +Leave `VITE_WS_URL` unset to run in offline/demo mode (agents animate but +receive no live updates). + +## Adding custom agents + +**Edit one file only: `js/agent-defs.js`** + +```js +export const AGENT_DEFS = [ + // existing agents … + { + id: 'zeta', // unique string — matches WebSocket message agentId + label: 'ZETA', // displayed in the 3D HUD + color: 0xff00aa, // hex integer (0xRRGGBB) + role: 'observer', // shown under the label sprite + direction: 'east', // cardinal facing direction (north/east/south/west) + x: 12, // world-space position (horizontal) + z: 0, // world-space position (depth) + }, +]; +``` + +Nothing else needs to change. `agents.js` reads positions from `x`/`z`, +and `websocket.js` reads colors and labels — both derive everything from +`AGENT_DEFS`. + +## Architecture + +``` +js/ +├── agent-defs.js ← single source of truth: id, label, color, role, position +├── agents.js ← Three.js scene objects, animation loop +├── effects.js ← matrix rain particles, starfield +├── interaction.js ← OrbitControls (pan, zoom, rotate) +├── main.js ← entry point, rAF loop +├── ui.js ← DOM HUD overlay (FPS, agent states, chat) +└── websocket.js ← WebSocket reconnect, message dispatch +``` + +## WebSocket protocol + +The backend sends JSON messages on the agents channel: + +| `type` | Fields | Effect | +|-----------------|-------------------------------------|-------------------------------| +| `agent_state` | `agentId`, `state` | Update agent visual state | +| `job_started` | `agentId`, `jobId` | Increment job counter, pulse | +| `job_completed` | `agentId`, `jobId` | Decrement job counter | +| `chat` | `agentId`, `text` | Append to chat panel | + +Agent states: `idle` (dim pulse) · `active` (bright pulse + fast ring spin) + +## Stack + +- [Three.js](https://threejs.org) 0.171.0 — 3D rendering +- [Vite](https://vitejs.dev) 5 — build + dev server +- `crypto.randomUUID()` — secure client session IDs (no external library) diff --git a/index.html b/index.html new file mode 100644 index 0000000..9e3624f --- /dev/null +++ b/index.html @@ -0,0 +1,60 @@ + + + + + + Timmy Tower World + + + +
+
+

TIMMY TOWER WORLD

+
AGENTS: 0
+
JOBS: 0
+
FPS: --
+
+
+
+
+
+
OFFLINE
+
+ + + diff --git a/js/agent-defs.js b/js/agent-defs.js new file mode 100644 index 0000000..d5572a3 --- /dev/null +++ b/js/agent-defs.js @@ -0,0 +1,28 @@ +/** + * agent-defs.js — Single source of truth for all agent definitions. + * + * To add a new agent, append one entry to AGENT_DEFS below and pick an + * unused (x, z) position. No other file needs to be edited. + * + * Fields: + * id — unique string key used in WebSocket messages and state maps + * label — display name shown in the 3D HUD and chat panel + * color — hex integer (0xRRGGBB) used for Three.js materials and lights + * role — human-readable role string shown under the label sprite + * direction — cardinal facing direction (for future mesh orientation use) + * x, z — world-space position on the horizontal plane (y is always 0) + */ +export const AGENT_DEFS = [ + { id: 'alpha', label: 'ALPHA', color: 0x00ff88, role: 'orchestrator', direction: 'north', x: 0, z: -6 }, + { id: 'beta', label: 'BETA', color: 0x00aaff, role: 'worker', direction: 'east', x: 6, z: 0 }, + { id: 'gamma', label: 'GAMMA', color: 0xff6600, role: 'validator', direction: 'south', x: 0, z: 6 }, + { id: 'delta', label: 'DELTA', color: 0xaa00ff, role: 'monitor', direction: 'west', x: -6, z: 0 }, +]; + +/** + * Convert an integer color (e.g. 0x00ff88) to a CSS hex string ('#00ff88'). + * Useful for DOM styling and canvas rendering. + */ +export function colorToCss(intColor) { + return '#' + intColor.toString(16).padStart(6, '0'); +} diff --git a/js/agents.js b/js/agents.js new file mode 100644 index 0000000..710be8a --- /dev/null +++ b/js/agents.js @@ -0,0 +1,157 @@ +import * as THREE from 'three'; +import { AGENT_DEFS, colorToCss } from './agent-defs.js'; + +const agents = new Map(); +let scene; +let connectionLines = []; + +class Agent { + constructor(def) { + this.id = def.id; + this.label = def.label; + this.color = def.color; + this.role = def.role; + this.position = new THREE.Vector3(def.x, 0, def.z); + this.state = 'idle'; + this.pulsePhase = Math.random() * Math.PI * 2; + + this.group = new THREE.Group(); + this.group.position.copy(this.position); + + this._buildMeshes(); + this._buildLabel(); + } + + _buildMeshes() { + const mat = new THREE.MeshStandardMaterial({ + color: this.color, + emissive: this.color, + emissiveIntensity: 0.4, + roughness: 0.3, + metalness: 0.8, + }); + + const geo = new THREE.IcosahedronGeometry(0.7, 1); + this.core = new THREE.Mesh(geo, mat); + this.group.add(this.core); + + const ringGeo = new THREE.TorusGeometry(1.1, 0.04, 8, 32); + const ringMat = new THREE.MeshBasicMaterial({ color: this.color, transparent: true, opacity: 0.5 }); + this.ring = new THREE.Mesh(ringGeo, ringMat); + this.ring.rotation.x = Math.PI / 2; + this.group.add(this.ring); + + const glowGeo = new THREE.SphereGeometry(1.3, 16, 16); + const glowMat = new THREE.MeshBasicMaterial({ + color: this.color, + transparent: true, + opacity: 0.05, + side: THREE.BackSide, + }); + this.glow = new THREE.Mesh(glowGeo, glowMat); + this.group.add(this.glow); + + const light = new THREE.PointLight(this.color, 1.5, 10); + this.group.add(light); + this.light = light; + } + + _buildLabel() { + const canvas = document.createElement('canvas'); + canvas.width = 256; canvas.height = 64; + const ctx = canvas.getContext('2d'); + ctx.fillStyle = 'rgba(0,0,0,0)'; + ctx.fillRect(0, 0, 256, 64); + ctx.font = 'bold 22px Courier New'; + ctx.fillStyle = colorToCss(this.color); + ctx.textAlign = 'center'; + ctx.fillText(this.label, 128, 28); + ctx.font = '14px Courier New'; + ctx.fillStyle = '#007722'; + ctx.fillText(this.role.toUpperCase(), 128, 50); + + const tex = new THREE.CanvasTexture(canvas); + const spriteMat = new THREE.SpriteMaterial({ map: tex, transparent: true }); + this.sprite = new THREE.Sprite(spriteMat); + this.sprite.scale.set(2.4, 0.6, 1); + this.sprite.position.y = 2; + this.group.add(this.sprite); + } + + update(time) { + const pulse = Math.sin(time * 0.002 + this.pulsePhase); + const active = this.state === 'active'; + + const intensity = active ? 0.6 + pulse * 0.4 : 0.2 + pulse * 0.1; + this.core.material.emissiveIntensity = intensity; + this.light.intensity = active ? 2 + pulse : 0.8 + pulse * 0.3; + + const scale = active ? 1 + pulse * 0.08 : 1 + pulse * 0.03; + this.core.scale.setScalar(scale); + this.ring.rotation.y += active ? 0.03 : 0.008; + this.ring.material.opacity = 0.3 + pulse * 0.2; + + this.group.position.y = this.position.y + Math.sin(time * 0.001 + this.pulsePhase) * 0.15; + } + + setState(state) { + this.state = state; + } +} + +export function initAgents(sceneRef) { + scene = sceneRef; + + AGENT_DEFS.forEach(def => { + const agent = new Agent(def); + agents.set(def.id, agent); + scene.add(agent.group); + }); + + buildConnectionLines(); +} + +function buildConnectionLines() { + connectionLines.forEach(l => scene.remove(l)); + connectionLines = []; + + const agentList = [...agents.values()]; + const lineMat = new THREE.LineBasicMaterial({ + color: 0x003300, + transparent: true, + opacity: 0.4, + }); + + for (let i = 0; i < agentList.length; i++) { + for (let j = i + 1; j < agentList.length; j++) { + const a = agentList[i]; + const b = agentList[j]; + if (a.position.distanceTo(b.position) <= 8) { + const points = [a.position.clone(), b.position.clone()]; + const geo = new THREE.BufferGeometry().setFromPoints(points); + const line = new THREE.Line(geo, lineMat.clone()); + connectionLines.push(line); + scene.add(line); + } + } + } +} + +export function updateAgents(time) { + agents.forEach(agent => agent.update(time)); +} + +export function getAgentCount() { + return agents.size; +} + +export function setAgentState(agentId, state) { + const agent = agents.get(agentId); + if (agent) agent.setState(state); +} + +export function getAgentDefs() { + return [...agents.values()].map(a => ({ + id: a.id, label: a.label, role: a.role, color: a.color, state: a.state, + })); +} diff --git a/js/effects.js b/js/effects.js new file mode 100644 index 0000000..b514b53 --- /dev/null +++ b/js/effects.js @@ -0,0 +1,85 @@ +import * as THREE from 'three'; + +let rainParticles; +let rainPositions; +let rainVelocities; +const RAIN_COUNT = 2000; + +export function initEffects(scene) { + initMatrixRain(scene); + initStarfield(scene); +} + +function initMatrixRain(scene) { + const geo = new THREE.BufferGeometry(); + const positions = new Float32Array(RAIN_COUNT * 3); + const velocities = new Float32Array(RAIN_COUNT); + const colors = new Float32Array(RAIN_COUNT * 3); + + for (let i = 0; i < RAIN_COUNT; i++) { + positions[i * 3] = (Math.random() - 0.5) * 100; + positions[i * 3 + 1] = Math.random() * 50 + 5; + positions[i * 3 + 2] = (Math.random() - 0.5) * 100; + velocities[i] = 0.05 + Math.random() * 0.15; + + const brightness = 0.3 + Math.random() * 0.7; + colors[i * 3] = 0; + colors[i * 3 + 1] = brightness; + colors[i * 3 + 2] = 0; + } + + geo.setAttribute('position', new THREE.BufferAttribute(positions, 3)); + geo.setAttribute('color', new THREE.BufferAttribute(colors, 3)); + rainPositions = positions; + rainVelocities = velocities; + + const mat = new THREE.PointsMaterial({ + size: 0.12, + vertexColors: true, + transparent: true, + opacity: 0.7, + sizeAttenuation: true, + }); + + rainParticles = new THREE.Points(geo, mat); + scene.add(rainParticles); +} + +function initStarfield(scene) { + const count = 500; + const geo = new THREE.BufferGeometry(); + const positions = new Float32Array(count * 3); + + for (let i = 0; i < count; i++) { + positions[i * 3] = (Math.random() - 0.5) * 300; + positions[i * 3 + 1] = Math.random() * 80 + 10; + positions[i * 3 + 2] = (Math.random() - 0.5) * 300; + } + + geo.setAttribute('position', new THREE.BufferAttribute(positions, 3)); + + const mat = new THREE.PointsMaterial({ + color: 0x003300, + size: 0.08, + transparent: true, + opacity: 0.5, + }); + + const stars = new THREE.Points(geo, mat); + scene.add(stars); +} + +export function updateEffects(_time) { + if (!rainParticles) return; + + for (let i = 0; i < RAIN_COUNT; i++) { + rainPositions[i * 3 + 1] -= rainVelocities[i]; + if (rainPositions[i * 3 + 1] < -1) { + rainPositions[i * 3 + 1] = 40 + Math.random() * 20; + rainPositions[i * 3] = (Math.random() - 0.5) * 100; + rainPositions[i * 3 + 2] = (Math.random() - 0.5) * 100; + } + } + + rainParticles.geometry.attributes.position.needsUpdate = true; +} diff --git a/js/interaction.js b/js/interaction.js new file mode 100644 index 0000000..3d56503 --- /dev/null +++ b/js/interaction.js @@ -0,0 +1,21 @@ +import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; + +let controls; + +export function initInteraction(camera, renderer) { + controls = new OrbitControls(camera, renderer.domElement); + controls.enableDamping = true; + controls.dampingFactor = 0.05; + controls.screenSpacePanning = false; + controls.minDistance = 5; + controls.maxDistance = 80; + controls.maxPolarAngle = Math.PI / 2.1; + controls.target.set(0, 0, 0); + controls.update(); + + renderer.domElement.addEventListener('contextmenu', e => e.preventDefault()); +} + +export function updateControls() { + if (controls) controls.update(); +} diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..df4b2c0 --- /dev/null +++ b/js/main.js @@ -0,0 +1,49 @@ +import { initWorld, onWindowResize } from './world.js'; +import { initAgents, updateAgents, getAgentCount } from './agents.js'; +import { initEffects, updateEffects } from './effects.js'; +import { initUI, updateUI } from './ui.js'; +import { initInteraction } from './interaction.js'; +import { initWebSocket, getConnectionState, getJobCount } from './websocket.js'; + +let frameCount = 0; +let lastFpsTime = performance.now(); +let currentFps = 0; + +function main() { + const { scene, camera, renderer } = initWorld(); + + initEffects(scene); + initAgents(scene); + initInteraction(camera, renderer); + initUI(); + initWebSocket(scene); + + window.addEventListener('resize', () => onWindowResize(camera, renderer)); + + function animate() { + requestAnimationFrame(animate); + + const now = performance.now(); + frameCount++; + if (now - lastFpsTime >= 1000) { + currentFps = Math.round(frameCount * 1000 / (now - lastFpsTime)); + frameCount = 0; + lastFpsTime = now; + } + + updateEffects(now); + updateAgents(now); + updateUI({ + fps: currentFps, + agentCount: getAgentCount(), + jobCount: getJobCount(), + connectionState: getConnectionState(), + }); + + renderer.render(scene, camera); + } + + animate(); +} + +main(); diff --git a/js/ui.js b/js/ui.js new file mode 100644 index 0000000..7ea5193 --- /dev/null +++ b/js/ui.js @@ -0,0 +1,84 @@ +import { getAgentDefs } from './agents.js'; +import { colorToCss } from './agent-defs.js'; + +const $agentCount = document.getElementById('agent-count'); +const $activeJobs = document.getElementById('active-jobs'); +const $fps = document.getElementById('fps'); +const $agentList = document.getElementById('agent-list'); +const $connStatus = document.getElementById('connection-status'); +const $chatPanel = document.getElementById('chat-panel'); + +const MAX_CHAT_ENTRIES = 12; +const chatEntries = []; + +export function initUI() { + renderAgentList(); +} + +function renderAgentList() { + const defs = getAgentDefs(); + $agentList.innerHTML = defs.map(a => { + const css = colorToCss(a.color); + return `
+ [ + ${a.label} + ] + IDLE +
`; + }).join(''); +} + +export function updateUI({ fps, agentCount, jobCount, connectionState }) { + $fps.textContent = `FPS: ${fps}`; + $agentCount.textContent = `AGENTS: ${agentCount}`; + $activeJobs.textContent = `JOBS: ${jobCount}`; + + if (connectionState === 'connected') { + $connStatus.textContent = '● CONNECTED'; + $connStatus.className = 'connected'; + } else if (connectionState === 'connecting') { + $connStatus.textContent = '◌ CONNECTING...'; + $connStatus.className = ''; + } else { + $connStatus.textContent = '○ OFFLINE'; + $connStatus.className = ''; + } + + const defs = getAgentDefs(); + defs.forEach(a => { + const el = document.getElementById(`agent-state-${a.id}`); + if (el) { + el.textContent = ` ${a.state.toUpperCase()}`; + el.style.color = a.state === 'active' ? '#00ff41' : '#003300'; + } + }); +} + +/** + * Append a line to the chat panel. + * @param {string} agentLabel — display name + * @param {string} message — message text (HTML-escaped before insertion) + * @param {string} cssColor — CSS color string, e.g. '#00ff88' + */ +export function appendChatMessage(agentLabel, message, cssColor) { + const color = cssColor || '#00ff41'; + const entry = document.createElement('div'); + entry.className = 'chat-entry'; + entry.innerHTML = `${agentLabel}: ${escapeHtml(message)}`; + chatEntries.push(entry); + + if (chatEntries.length > MAX_CHAT_ENTRIES) { + const removed = chatEntries.shift(); + $chatPanel.removeChild(removed); + } + + $chatPanel.appendChild(entry); + $chatPanel.scrollTop = $chatPanel.scrollHeight; +} + +function escapeHtml(str) { + return str + .replace(/&/g, '&') + .replace(//g, '>'); +} diff --git a/js/websocket.js b/js/websocket.js new file mode 100644 index 0000000..0a758c8 --- /dev/null +++ b/js/websocket.js @@ -0,0 +1,115 @@ +import { AGENT_DEFS, colorToCss } from './agent-defs.js'; +import { setAgentState } from './agents.js'; +import { appendChatMessage } from './ui.js'; + +const WS_URL = import.meta.env.VITE_WS_URL || ''; + +const agentById = Object.fromEntries(AGENT_DEFS.map(d => [d.id, d])); + +let ws = null; +let connectionState = 'disconnected'; +let jobCount = 0; +let reconnectTimer = null; +const RECONNECT_DELAY_MS = 5000; + +export function initWebSocket(_scene) { + if (!WS_URL) { + connectionState = 'disconnected'; + return; + } + connect(); +} + +function connect() { + if (ws) { + ws.onclose = null; + ws.close(); + } + + connectionState = 'connecting'; + + try { + ws = new WebSocket(WS_URL); + } catch { + connectionState = 'disconnected'; + scheduleReconnect(); + return; + } + + ws.onopen = () => { + connectionState = 'connected'; + clearTimeout(reconnectTimer); + ws.send(JSON.stringify({ + type: 'subscribe', + channel: 'agents', + clientId: crypto.randomUUID(), + })); + }; + + ws.onmessage = (event) => { + try { + handleMessage(JSON.parse(event.data)); + } catch { + } + }; + + ws.onerror = () => { + connectionState = 'disconnected'; + }; + + ws.onclose = () => { + connectionState = 'disconnected'; + scheduleReconnect(); + }; +} + +function scheduleReconnect() { + clearTimeout(reconnectTimer); + reconnectTimer = setTimeout(connect, RECONNECT_DELAY_MS); +} + +function handleMessage(msg) { + switch (msg.type) { + case 'agent_state': { + if (msg.agentId && msg.state) { + setAgentState(msg.agentId, msg.state); + } + break; + } + case 'job_started': { + jobCount++; + if (msg.agentId) setAgentState(msg.agentId, 'active'); + logEvent(`JOB ${(msg.jobId || '').slice(0, 8)} started`); + break; + } + case 'job_completed': { + if (jobCount > 0) jobCount--; + if (msg.agentId) setAgentState(msg.agentId, 'idle'); + logEvent(`JOB ${(msg.jobId || '').slice(0, 8)} completed`); + break; + } + case 'chat': { + const def = agentById[msg.agentId]; + if (def && msg.text) { + appendChatMessage(def.label, msg.text, colorToCss(def.color)); + } + break; + } + case 'agent_count': + break; + default: + break; + } +} + +function logEvent(text) { + appendChatMessage('SYS', text, colorToCss(0x003300)); +} + +export function getConnectionState() { + return connectionState; +} + +export function getJobCount() { + return jobCount; +} diff --git a/js/world.js b/js/world.js new file mode 100644 index 0000000..1620eb1 --- /dev/null +++ b/js/world.js @@ -0,0 +1,60 @@ +import * as THREE from 'three'; + +let scene, camera, renderer; + +export function initWorld() { + scene = new THREE.Scene(); + scene.background = new THREE.Color(0x000000); + scene.fog = new THREE.FogExp2(0x000000, 0.035); + + camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 500); + camera.position.set(0, 12, 28); + camera.lookAt(0, 0, 0); + + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize(window.innerWidth, window.innerHeight); + renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); + renderer.outputColorSpace = THREE.SRGBColorSpace; + document.body.prepend(renderer.domElement); + + addLights(scene); + addGrid(scene); + + return { scene, camera, renderer }; +} + +function addLights(scene) { + const ambient = new THREE.AmbientLight(0x001a00, 0.6); + scene.add(ambient); + + const point = new THREE.PointLight(0x00ff41, 2, 80); + point.position.set(0, 20, 0); + scene.add(point); + + const fill = new THREE.DirectionalLight(0x003300, 0.4); + fill.position.set(-10, 10, 10); + scene.add(fill); +} + +function addGrid(scene) { + const grid = new THREE.GridHelper(100, 40, 0x003300, 0x001a00); + grid.position.y = -0.01; + scene.add(grid); + + const planeGeo = new THREE.PlaneGeometry(100, 100); + const planeMat = new THREE.MeshBasicMaterial({ + color: 0x000a00, + transparent: true, + opacity: 0.5, + }); + const plane = new THREE.Mesh(planeGeo, planeMat); + plane.rotation.x = -Math.PI / 2; + plane.position.y = -0.02; + scene.add(plane); +} + +export function onWindowResize(camera, renderer) { + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + renderer.setSize(window.innerWidth, window.innerHeight); +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..cb95f0b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,996 @@ +{ + "name": "the-matrix", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "the-matrix", + "version": "0.1.0", + "dependencies": { + "three": "0.171.0" + }, + "devDependencies": { + "vite": "^5.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "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" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/three": { + "version": "0.171.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.171.0.tgz", + "integrity": "sha512-Y/lAXPaKZPcEdkKjh0JOAHVv8OOnv/NDJqm0wjfCzyQmfKxV7zvkwsnBgPBKTzJHToSOhRGQAGbPJObT59B/PQ==", + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..da145e7 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "the-matrix", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "three": "0.171.0" + }, + "devDependencies": { + "vite": "^5.4.0" + } +} diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..de86f5d --- /dev/null +++ b/vite.config.js @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite'; + +export default defineConfig({ + root: '.', + build: { + outDir: 'dist', + assetsDir: 'assets', + target: 'esnext', + }, + server: { + host: true, + }, +});