├── metaverse
├── .gitignore
├── .npmrc
├── .vscode
│ └── settings.json
├── README.md
├── apps
│ ├── frontend
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── eslint.config.js
│ │ ├── index.html
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── public
│ │ │ └── vite.svg
│ │ ├── src
│ │ │ ├── App.css
│ │ │ ├── App.tsx
│ │ │ ├── Game.tsx
│ │ │ ├── assets
│ │ │ │ └── react.svg
│ │ │ ├── index.css
│ │ │ ├── main.tsx
│ │ │ └── vite-env.d.ts
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ └── vite.config.ts
│ ├── http
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── config.ts
│ │ │ ├── index.ts
│ │ │ ├── middleware
│ │ │ │ ├── admin.ts
│ │ │ │ └── user.ts
│ │ │ ├── routes
│ │ │ │ └── v1
│ │ │ │ │ ├── admin.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── space.ts
│ │ │ │ │ └── user.ts
│ │ │ ├── scrypt.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── tsconfig.json
│ │ └── tsconfig.tsbuildinfo
│ └── ws
│ │ ├── package.json
│ │ ├── src
│ │ ├── RoomManager.ts
│ │ ├── User.ts
│ │ ├── config.ts
│ │ ├── index.ts
│ │ └── types.ts
│ │ └── tsconfig.json
├── package.json
├── packages
│ ├── db
│ │ ├── .gitignore
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── prisma
│ │ │ ├── migrations
│ │ │ │ ├── 20241030155258_init
│ │ │ │ │ └── migration.sql
│ │ │ │ ├── 20241030164544_made_password_non_unique
│ │ │ │ │ └── migration.sql
│ │ │ │ ├── 20241030164722_made_avatar_optional
│ │ │ │ │ └── migration.sql
│ │ │ │ ├── 20241031112104_add_static
│ │ │ │ │ └── migration.sql
│ │ │ │ ├── 20241031112726_add_thumbnail
│ │ │ │ │ └── migration.sql
│ │ │ │ └── migration_lock.toml
│ │ │ └── schema.prisma
│ │ ├── src
│ │ │ └── index.ts
│ │ ├── tsconfig.json
│ │ └── tsconfig.tsbuildinfo
│ ├── eslint-config
│ │ ├── README.md
│ │ ├── library.js
│ │ ├── next.js
│ │ ├── package.json
│ │ └── react-internal.js
│ ├── typescript-config
│ │ ├── base.json
│ │ ├── nextjs.json
│ │ ├── package.json
│ │ └── react-library.json
│ └── ui
│ │ ├── .eslintrc.js
│ │ ├── package.json
│ │ ├── src
│ │ ├── button.tsx
│ │ ├── card.tsx
│ │ └── code.tsx
│ │ ├── tsconfig.json
│ │ ├── tsconfig.lint.json
│ │ └── turbo
│ │ └── generators
│ │ ├── config.ts
│ │ └── templates
│ │ └── component.hbs
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── turbo.json
└── tests
├── .gitignore
├── index.test.js
├── package-lock.json
└── package.json
/metaverse/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # Dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # Local env files
9 | .env
10 | .env.local
11 | .env.development.local
12 | .env.test.local
13 | .env.production.local
14 |
15 | # Testing
16 | coverage
17 |
18 | # Turbo
19 | .turbo
20 |
21 | # Vercel
22 | .vercel
23 |
24 | # Build Outputs
25 | .next/
26 | out/
27 | build
28 | dist
29 |
30 |
31 | # Debug
32 | npm-debug.log*
33 | yarn-debug.log*
34 | yarn-error.log*
35 |
36 | # Misc
37 | .DS_Store
38 | *.pem
39 |
--------------------------------------------------------------------------------
/metaverse/.npmrc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hkirat/2d-metaverse/16c7ab9d40609071d979d75db02e8a2497658273/metaverse/.npmrc
--------------------------------------------------------------------------------
/metaverse/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.workingDirectories": [
3 | {
4 | "mode": "auto"
5 | }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/metaverse/README.md:
--------------------------------------------------------------------------------
1 | # Turborepo starter
2 |
3 | This is an official starter Turborepo.
4 |
5 | ## Using this example
6 |
7 | Run the following command:
8 |
9 | ```sh
10 | npx create-turbo@latest
11 | ```
12 |
13 | ## What's inside?
14 |
15 | This Turborepo includes the following packages/apps:
16 |
17 | ### Apps and Packages
18 |
19 | - `docs`: a [Next.js](https://nextjs.org/) app
20 | - `web`: another [Next.js](https://nextjs.org/) app
21 | - `@repo/ui`: a stub React component library shared by both `web` and `docs` applications
22 | - `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`)
23 | - `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo
24 |
25 | Each package/app is 100% [TypeScript](https://www.typescriptlang.org/).
26 |
27 | ### Utilities
28 |
29 | This Turborepo has some additional tools already setup for you:
30 |
31 | - [TypeScript](https://www.typescriptlang.org/) for static type checking
32 | - [ESLint](https://eslint.org/) for code linting
33 | - [Prettier](https://prettier.io) for code formatting
34 |
35 | ### Build
36 |
37 | To build all apps and packages, run the following command:
38 |
39 | ```
40 | cd my-turborepo
41 | pnpm build
42 | ```
43 |
44 | ### Develop
45 |
46 | To develop all apps and packages, run the following command:
47 |
48 | ```
49 | cd my-turborepo
50 | pnpm dev
51 | ```
52 |
53 | ### Remote Caching
54 |
55 | Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines.
56 |
57 | By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup), then enter the following commands:
58 |
59 | ```
60 | cd my-turborepo
61 | npx turbo login
62 | ```
63 |
64 | This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview).
65 |
66 | Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo:
67 |
68 | ```
69 | npx turbo link
70 | ```
71 |
72 | ## Useful Links
73 |
74 | Learn more about the power of Turborepo:
75 |
76 | - [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks)
77 | - [Caching](https://turbo.build/repo/docs/core-concepts/caching)
78 | - [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching)
79 | - [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering)
80 | - [Configuration Options](https://turbo.build/repo/docs/reference/configuration)
81 | - [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference)
82 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default tseslint.config({
18 | languageOptions: {
19 | // other options...
20 | parserOptions: {
21 | project: ['./tsconfig.node.json', './tsconfig.app.json'],
22 | tsconfigRootDir: import.meta.dirname,
23 | },
24 | },
25 | })
26 | ```
27 |
28 | - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
29 | - Optionally add `...tseslint.configs.stylisticTypeChecked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
31 |
32 | ```js
33 | // eslint.config.js
34 | import react from 'eslint-plugin-react'
35 |
36 | export default tseslint.config({
37 | // Set the react version
38 | settings: { react: { version: '18.3' } },
39 | plugins: {
40 | // Add the react plugin
41 | react,
42 | },
43 | rules: {
44 | // other rules...
45 | // Enable its recommended rules
46 | ...react.configs.recommended.rules,
47 | ...react.configs['jsx-runtime'].rules,
48 | },
49 | })
50 | ```
51 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import reactHooks from 'eslint-plugin-react-hooks'
4 | import reactRefresh from 'eslint-plugin-react-refresh'
5 | import tseslint from 'typescript-eslint'
6 |
7 | export default tseslint.config(
8 | { ignores: ['dist'] },
9 | {
10 | extends: [js.configs.recommended, ...tseslint.configs.recommended],
11 | files: ['**/*.{ts,tsx}'],
12 | languageOptions: {
13 | ecmaVersion: 2020,
14 | globals: globals.browser,
15 | },
16 | plugins: {
17 | 'react-hooks': reactHooks,
18 | 'react-refresh': reactRefresh,
19 | },
20 | rules: {
21 | ...reactHooks.configs.recommended.rules,
22 | 'react-refresh/only-export-components': [
23 | 'warn',
24 | { allowConstantExport: true },
25 | ],
26 | },
27 | },
28 | )
29 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "eslint .",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.3.1",
14 | "react-dom": "^18.3.1"
15 | },
16 | "devDependencies": {
17 | "@eslint/js": "^9.13.0",
18 | "@types/react": "^18.3.12",
19 | "@types/react-dom": "^18.3.1",
20 | "@vitejs/plugin-react": "^4.3.3",
21 | "eslint": "^9.13.0",
22 | "eslint-plugin-react-hooks": "^5.0.0",
23 | "eslint-plugin-react-refresh": "^0.4.14",
24 | "globals": "^15.11.0",
25 | "typescript": "~5.6.2",
26 | "typescript-eslint": "^8.11.0",
27 | "vite": "^5.4.10"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/src/App.tsx:
--------------------------------------------------------------------------------
1 | import Arena from "./Game";
2 |
3 | function App() {
4 |
5 | return (
6 | <>
7 |
8 | >
9 | )
10 | }
11 |
12 | export default App
13 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/src/Game.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useRef, useState } from 'react';
2 |
3 | const Arena = () => {
4 | const canvasRef = useRef(null);
5 | const wsRef = useRef(null);
6 | const [currentUser, setCurrentUser] = useState({});
7 | const [users, setUsers] = useState(new Map());
8 | const [params, setParams] = useState({ token: '', spaceId: '' });
9 |
10 | // Initialize WebSocket connection and handle URL params
11 | useEffect(() => {
12 | const urlParams = new URLSearchParams(window.location.search);
13 | const token = urlParams.get('token') || '';
14 | const spaceId = urlParams.get('spaceId') || '';
15 | setParams({ token, spaceId });
16 |
17 | // Initialize WebSocket
18 | wsRef.current = new WebSocket('ws://localhost:3001'); // Replace with your WS_URL
19 |
20 | wsRef.current.onopen = () => {
21 | // Join the space once connected
22 | wsRef.current.send(JSON.stringify({
23 | type: 'join',
24 | payload: {
25 | spaceId,
26 | token
27 | }
28 | }));
29 | };
30 |
31 | wsRef.current.onmessage = (event: any) => {
32 | const message = JSON.parse(event.data);
33 | handleWebSocketMessage(message);
34 | };
35 |
36 | return () => {
37 | if (wsRef.current) {
38 | wsRef.current.close();
39 | }
40 | };
41 | }, []);
42 |
43 | const handleWebSocketMessage = (message: any) => {
44 | switch (message.type) {
45 | case 'space-joined':
46 | // Initialize current user position and other users
47 | console.log("set")
48 | console.log({
49 | x: message.payload.spawn.x,
50 | y: message.payload.spawn.y,
51 | userId: message.payload.userId
52 | })
53 | setCurrentUser({
54 | x: message.payload.spawn.x,
55 | y: message.payload.spawn.y,
56 | userId: message.payload.userId
57 | });
58 |
59 | // Initialize other users from the payload
60 | const userMap = new Map();
61 | message.payload.users.forEach((user: any) => {
62 | userMap.set(user.userId, user);
63 | });
64 | setUsers(userMap);
65 | break;
66 |
67 | case 'user-joined':
68 | setUsers(prev => {
69 | const newUsers = new Map(prev);
70 | newUsers.set(message.payload.userId, {
71 | x: message.payload.x,
72 | y: message.payload.y,
73 | userId: message.payload.userId
74 | });
75 | return newUsers;
76 | });
77 | break;
78 |
79 | case 'movement':
80 | setUsers(prev => {
81 | const newUsers = new Map(prev);
82 | const user = newUsers.get(message.payload.userId);
83 | if (user) {
84 | user.x = message.payload.x;
85 | user.y = message.payload.y;
86 | newUsers.set(message.payload.userId, user);
87 | }
88 | return newUsers;
89 | });
90 | break;
91 |
92 | case 'movement-rejected':
93 | // Reset current user position if movement was rejected
94 | setCurrentUser((prev: any) => ({
95 | ...prev,
96 | x: message.payload.x,
97 | y: message.payload.y
98 | }));
99 | break;
100 |
101 | case 'user-left':
102 | setUsers(prev => {
103 | const newUsers = new Map(prev);
104 | newUsers.delete(message.payload.userId);
105 | return newUsers;
106 | });
107 | break;
108 | }
109 | };
110 |
111 | // Handle user movement
112 | const handleMove = (newX: any, newY: any) => {
113 | if (!currentUser) return;
114 |
115 | // Send movement request
116 | wsRef.current.send(JSON.stringify({
117 | type: 'move',
118 | payload: {
119 | x: newX,
120 | y: newY,
121 | userId: currentUser.userId
122 | }
123 | }));
124 | };
125 |
126 | // Draw the arena
127 | useEffect(() => {
128 | console.log("render")
129 | const canvas = canvasRef.current;
130 | if (!canvas) return;
131 | console.log("below render")
132 |
133 | const ctx = canvas.getContext('2d');
134 | ctx.clearRect(0, 0, canvas.width, canvas.height);
135 |
136 | // Draw grid
137 | ctx.strokeStyle = '#eee';
138 | for (let i = 0; i < canvas.width; i += 50) {
139 | ctx.beginPath();
140 | ctx.moveTo(i, 0);
141 | ctx.lineTo(i, canvas.height);
142 | ctx.stroke();
143 | }
144 | for (let i = 0; i < canvas.height; i += 50) {
145 | ctx.beginPath();
146 | ctx.moveTo(0, i);
147 | ctx.lineTo(canvas.width, i);
148 | ctx.stroke();
149 | }
150 |
151 | console.log("before curerntusert")
152 | console.log(currentUser)
153 | // Draw current user
154 | if (currentUser && currentUser.x) {
155 | console.log("drawing myself")
156 | console.log(currentUser)
157 | ctx.beginPath();
158 | ctx.fillStyle = '#FF6B6B';
159 | ctx.arc(currentUser.x * 50, currentUser.y * 50, 20, 0, Math.PI * 2);
160 | ctx.fill();
161 | ctx.fillStyle = '#000';
162 | ctx.font = '14px Arial';
163 | ctx.textAlign = 'center';
164 | ctx.fillText('You', currentUser.x * 50, currentUser.y * 50 + 40);
165 | }
166 |
167 | // Draw other users
168 | users.forEach(user => {
169 | if (!user.x) {
170 | return
171 | }
172 | console.log("drawing other user")
173 | console.log(user)
174 | ctx.beginPath();
175 | ctx.fillStyle = '#4ECDC4';
176 | ctx.arc(user.x * 50, user.y * 50, 20, 0, Math.PI * 2);
177 | ctx.fill();
178 | ctx.fillStyle = '#000';
179 | ctx.font = '14px Arial';
180 | ctx.textAlign = 'center';
181 | ctx.fillText(`User ${user.userId}`, user.x * 50, user.y * 50 + 40);
182 | });
183 | }, [currentUser, users]);
184 |
185 | const handleKeyDown = (e: any) => {
186 | if (!currentUser) return;
187 |
188 | const { x, y } = currentUser;
189 | switch (e.key) {
190 | case 'ArrowUp':
191 | handleMove(x, y - 1);
192 | break;
193 | case 'ArrowDown':
194 | handleMove(x, y + 1);
195 | break;
196 | case 'ArrowLeft':
197 | handleMove(x - 1, y);
198 | break;
199 | case 'ArrowRight':
200 | handleMove(x + 1, y);
201 | break;
202 | }
203 | };
204 |
205 | return (
206 |
207 |
Arena
208 |
209 |
Token: {params.token}
210 |
Space ID: {params.spaceId}
211 |
Connected Users: {users.size + (currentUser ? 1 : 0)}
212 |
213 |
214 |
220 |
221 |
Use arrow keys to move your avatar
222 |
223 | );
224 | };
225 |
226 | export default Arena;
--------------------------------------------------------------------------------
/metaverse/apps/frontend/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/src/index.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hkirat/2d-metaverse/16c7ab9d40609071d979d75db02e8a2497658273/metaverse/apps/frontend/src/index.css
--------------------------------------------------------------------------------
/metaverse/apps/frontend/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import './index.css'
4 | import App from './App.tsx'
5 |
6 | createRoot(document.getElementById('root')!).render(
7 |
8 |
9 | ,
10 | )
11 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4 | "target": "ES2020",
5 | "useDefineForClassFields": true,
6 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
7 | "module": "ESNext",
8 | "skipLibCheck": true,
9 |
10 | /* Bundler mode */
11 | "moduleResolution": "Bundler",
12 | "allowImportingTsExtensions": true,
13 | "isolatedModules": true,
14 | "moduleDetection": "force",
15 | "noEmit": true,
16 | "jsx": "react-jsx",
17 |
18 | /* Linting */
19 | "strict": true,
20 | "noUnusedLocals": true,
21 | "noUnusedParameters": true,
22 | "noFallthroughCasesInSwitch": true,
23 | "noUncheckedSideEffectImports": true
24 | },
25 | "include": ["src"]
26 | }
27 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfig.app.json" },
5 | { "path": "./tsconfig.node.json" }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4 | "target": "ES2022",
5 | "lib": ["ES2023"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "Bundler",
11 | "allowImportingTsExtensions": true,
12 | "isolatedModules": true,
13 | "moduleDetection": "force",
14 | "noEmit": true,
15 |
16 | /* Linting */
17 | "strict": true,
18 | "noUnusedLocals": true,
19 | "noUnusedParameters": true,
20 | "noFallthroughCasesInSwitch": true,
21 | "noUncheckedSideEffectImports": true
22 | },
23 | "include": ["vite.config.ts"]
24 | }
25 |
--------------------------------------------------------------------------------
/metaverse/apps/frontend/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vite.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/metaverse/apps/http/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "http",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "http",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@types/express": "^5.0.0",
13 | "express": "^4.21.1",
14 | "typescript": "^5.6.3"
15 | }
16 | },
17 | "node_modules/@types/body-parser": {
18 | "version": "1.19.5",
19 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
20 | "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
21 | "license": "MIT",
22 | "dependencies": {
23 | "@types/connect": "*",
24 | "@types/node": "*"
25 | }
26 | },
27 | "node_modules/@types/connect": {
28 | "version": "3.4.38",
29 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
30 | "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
31 | "license": "MIT",
32 | "dependencies": {
33 | "@types/node": "*"
34 | }
35 | },
36 | "node_modules/@types/express": {
37 | "version": "5.0.0",
38 | "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz",
39 | "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==",
40 | "license": "MIT",
41 | "dependencies": {
42 | "@types/body-parser": "*",
43 | "@types/express-serve-static-core": "^5.0.0",
44 | "@types/qs": "*",
45 | "@types/serve-static": "*"
46 | }
47 | },
48 | "node_modules/@types/express-serve-static-core": {
49 | "version": "5.0.1",
50 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz",
51 | "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==",
52 | "license": "MIT",
53 | "dependencies": {
54 | "@types/node": "*",
55 | "@types/qs": "*",
56 | "@types/range-parser": "*",
57 | "@types/send": "*"
58 | }
59 | },
60 | "node_modules/@types/http-errors": {
61 | "version": "2.0.4",
62 | "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
63 | "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
64 | "license": "MIT"
65 | },
66 | "node_modules/@types/mime": {
67 | "version": "1.3.5",
68 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
69 | "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
70 | "license": "MIT"
71 | },
72 | "node_modules/@types/node": {
73 | "version": "22.8.4",
74 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz",
75 | "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==",
76 | "license": "MIT",
77 | "dependencies": {
78 | "undici-types": "~6.19.8"
79 | }
80 | },
81 | "node_modules/@types/qs": {
82 | "version": "6.9.16",
83 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz",
84 | "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==",
85 | "license": "MIT"
86 | },
87 | "node_modules/@types/range-parser": {
88 | "version": "1.2.7",
89 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
90 | "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
91 | "license": "MIT"
92 | },
93 | "node_modules/@types/send": {
94 | "version": "0.17.4",
95 | "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
96 | "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
97 | "license": "MIT",
98 | "dependencies": {
99 | "@types/mime": "^1",
100 | "@types/node": "*"
101 | }
102 | },
103 | "node_modules/@types/serve-static": {
104 | "version": "1.15.7",
105 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
106 | "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
107 | "license": "MIT",
108 | "dependencies": {
109 | "@types/http-errors": "*",
110 | "@types/node": "*",
111 | "@types/send": "*"
112 | }
113 | },
114 | "node_modules/accepts": {
115 | "version": "1.3.8",
116 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
117 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
118 | "license": "MIT",
119 | "dependencies": {
120 | "mime-types": "~2.1.34",
121 | "negotiator": "0.6.3"
122 | },
123 | "engines": {
124 | "node": ">= 0.6"
125 | }
126 | },
127 | "node_modules/array-flatten": {
128 | "version": "1.1.1",
129 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
130 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
131 | "license": "MIT"
132 | },
133 | "node_modules/body-parser": {
134 | "version": "1.20.3",
135 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
136 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
137 | "license": "MIT",
138 | "dependencies": {
139 | "bytes": "3.1.2",
140 | "content-type": "~1.0.5",
141 | "debug": "2.6.9",
142 | "depd": "2.0.0",
143 | "destroy": "1.2.0",
144 | "http-errors": "2.0.0",
145 | "iconv-lite": "0.4.24",
146 | "on-finished": "2.4.1",
147 | "qs": "6.13.0",
148 | "raw-body": "2.5.2",
149 | "type-is": "~1.6.18",
150 | "unpipe": "1.0.0"
151 | },
152 | "engines": {
153 | "node": ">= 0.8",
154 | "npm": "1.2.8000 || >= 1.4.16"
155 | }
156 | },
157 | "node_modules/bytes": {
158 | "version": "3.1.2",
159 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
160 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
161 | "license": "MIT",
162 | "engines": {
163 | "node": ">= 0.8"
164 | }
165 | },
166 | "node_modules/call-bind": {
167 | "version": "1.0.7",
168 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
169 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
170 | "license": "MIT",
171 | "dependencies": {
172 | "es-define-property": "^1.0.0",
173 | "es-errors": "^1.3.0",
174 | "function-bind": "^1.1.2",
175 | "get-intrinsic": "^1.2.4",
176 | "set-function-length": "^1.2.1"
177 | },
178 | "engines": {
179 | "node": ">= 0.4"
180 | },
181 | "funding": {
182 | "url": "https://github.com/sponsors/ljharb"
183 | }
184 | },
185 | "node_modules/content-disposition": {
186 | "version": "0.5.4",
187 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
188 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
189 | "license": "MIT",
190 | "dependencies": {
191 | "safe-buffer": "5.2.1"
192 | },
193 | "engines": {
194 | "node": ">= 0.6"
195 | }
196 | },
197 | "node_modules/content-type": {
198 | "version": "1.0.5",
199 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
200 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
201 | "license": "MIT",
202 | "engines": {
203 | "node": ">= 0.6"
204 | }
205 | },
206 | "node_modules/cookie": {
207 | "version": "0.7.1",
208 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
209 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
210 | "license": "MIT",
211 | "engines": {
212 | "node": ">= 0.6"
213 | }
214 | },
215 | "node_modules/cookie-signature": {
216 | "version": "1.0.6",
217 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
218 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
219 | "license": "MIT"
220 | },
221 | "node_modules/debug": {
222 | "version": "2.6.9",
223 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
224 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
225 | "license": "MIT",
226 | "dependencies": {
227 | "ms": "2.0.0"
228 | }
229 | },
230 | "node_modules/define-data-property": {
231 | "version": "1.1.4",
232 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
233 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
234 | "license": "MIT",
235 | "dependencies": {
236 | "es-define-property": "^1.0.0",
237 | "es-errors": "^1.3.0",
238 | "gopd": "^1.0.1"
239 | },
240 | "engines": {
241 | "node": ">= 0.4"
242 | },
243 | "funding": {
244 | "url": "https://github.com/sponsors/ljharb"
245 | }
246 | },
247 | "node_modules/depd": {
248 | "version": "2.0.0",
249 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
250 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
251 | "license": "MIT",
252 | "engines": {
253 | "node": ">= 0.8"
254 | }
255 | },
256 | "node_modules/destroy": {
257 | "version": "1.2.0",
258 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
259 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
260 | "license": "MIT",
261 | "engines": {
262 | "node": ">= 0.8",
263 | "npm": "1.2.8000 || >= 1.4.16"
264 | }
265 | },
266 | "node_modules/ee-first": {
267 | "version": "1.1.1",
268 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
269 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
270 | "license": "MIT"
271 | },
272 | "node_modules/encodeurl": {
273 | "version": "2.0.0",
274 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
275 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
276 | "license": "MIT",
277 | "engines": {
278 | "node": ">= 0.8"
279 | }
280 | },
281 | "node_modules/es-define-property": {
282 | "version": "1.0.0",
283 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
284 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
285 | "license": "MIT",
286 | "dependencies": {
287 | "get-intrinsic": "^1.2.4"
288 | },
289 | "engines": {
290 | "node": ">= 0.4"
291 | }
292 | },
293 | "node_modules/es-errors": {
294 | "version": "1.3.0",
295 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
296 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
297 | "license": "MIT",
298 | "engines": {
299 | "node": ">= 0.4"
300 | }
301 | },
302 | "node_modules/escape-html": {
303 | "version": "1.0.3",
304 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
305 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
306 | "license": "MIT"
307 | },
308 | "node_modules/etag": {
309 | "version": "1.8.1",
310 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
311 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
312 | "license": "MIT",
313 | "engines": {
314 | "node": ">= 0.6"
315 | }
316 | },
317 | "node_modules/express": {
318 | "version": "4.21.1",
319 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
320 | "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
321 | "license": "MIT",
322 | "dependencies": {
323 | "accepts": "~1.3.8",
324 | "array-flatten": "1.1.1",
325 | "body-parser": "1.20.3",
326 | "content-disposition": "0.5.4",
327 | "content-type": "~1.0.4",
328 | "cookie": "0.7.1",
329 | "cookie-signature": "1.0.6",
330 | "debug": "2.6.9",
331 | "depd": "2.0.0",
332 | "encodeurl": "~2.0.0",
333 | "escape-html": "~1.0.3",
334 | "etag": "~1.8.1",
335 | "finalhandler": "1.3.1",
336 | "fresh": "0.5.2",
337 | "http-errors": "2.0.0",
338 | "merge-descriptors": "1.0.3",
339 | "methods": "~1.1.2",
340 | "on-finished": "2.4.1",
341 | "parseurl": "~1.3.3",
342 | "path-to-regexp": "0.1.10",
343 | "proxy-addr": "~2.0.7",
344 | "qs": "6.13.0",
345 | "range-parser": "~1.2.1",
346 | "safe-buffer": "5.2.1",
347 | "send": "0.19.0",
348 | "serve-static": "1.16.2",
349 | "setprototypeof": "1.2.0",
350 | "statuses": "2.0.1",
351 | "type-is": "~1.6.18",
352 | "utils-merge": "1.0.1",
353 | "vary": "~1.1.2"
354 | },
355 | "engines": {
356 | "node": ">= 0.10.0"
357 | }
358 | },
359 | "node_modules/finalhandler": {
360 | "version": "1.3.1",
361 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
362 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
363 | "license": "MIT",
364 | "dependencies": {
365 | "debug": "2.6.9",
366 | "encodeurl": "~2.0.0",
367 | "escape-html": "~1.0.3",
368 | "on-finished": "2.4.1",
369 | "parseurl": "~1.3.3",
370 | "statuses": "2.0.1",
371 | "unpipe": "~1.0.0"
372 | },
373 | "engines": {
374 | "node": ">= 0.8"
375 | }
376 | },
377 | "node_modules/forwarded": {
378 | "version": "0.2.0",
379 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
380 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
381 | "license": "MIT",
382 | "engines": {
383 | "node": ">= 0.6"
384 | }
385 | },
386 | "node_modules/fresh": {
387 | "version": "0.5.2",
388 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
389 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
390 | "license": "MIT",
391 | "engines": {
392 | "node": ">= 0.6"
393 | }
394 | },
395 | "node_modules/function-bind": {
396 | "version": "1.1.2",
397 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
398 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
399 | "license": "MIT",
400 | "funding": {
401 | "url": "https://github.com/sponsors/ljharb"
402 | }
403 | },
404 | "node_modules/get-intrinsic": {
405 | "version": "1.2.4",
406 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
407 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
408 | "license": "MIT",
409 | "dependencies": {
410 | "es-errors": "^1.3.0",
411 | "function-bind": "^1.1.2",
412 | "has-proto": "^1.0.1",
413 | "has-symbols": "^1.0.3",
414 | "hasown": "^2.0.0"
415 | },
416 | "engines": {
417 | "node": ">= 0.4"
418 | },
419 | "funding": {
420 | "url": "https://github.com/sponsors/ljharb"
421 | }
422 | },
423 | "node_modules/gopd": {
424 | "version": "1.0.1",
425 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
426 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
427 | "license": "MIT",
428 | "dependencies": {
429 | "get-intrinsic": "^1.1.3"
430 | },
431 | "funding": {
432 | "url": "https://github.com/sponsors/ljharb"
433 | }
434 | },
435 | "node_modules/has-property-descriptors": {
436 | "version": "1.0.2",
437 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
438 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
439 | "license": "MIT",
440 | "dependencies": {
441 | "es-define-property": "^1.0.0"
442 | },
443 | "funding": {
444 | "url": "https://github.com/sponsors/ljharb"
445 | }
446 | },
447 | "node_modules/has-proto": {
448 | "version": "1.0.3",
449 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
450 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
451 | "license": "MIT",
452 | "engines": {
453 | "node": ">= 0.4"
454 | },
455 | "funding": {
456 | "url": "https://github.com/sponsors/ljharb"
457 | }
458 | },
459 | "node_modules/has-symbols": {
460 | "version": "1.0.3",
461 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
462 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
463 | "license": "MIT",
464 | "engines": {
465 | "node": ">= 0.4"
466 | },
467 | "funding": {
468 | "url": "https://github.com/sponsors/ljharb"
469 | }
470 | },
471 | "node_modules/hasown": {
472 | "version": "2.0.2",
473 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
474 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
475 | "license": "MIT",
476 | "dependencies": {
477 | "function-bind": "^1.1.2"
478 | },
479 | "engines": {
480 | "node": ">= 0.4"
481 | }
482 | },
483 | "node_modules/http-errors": {
484 | "version": "2.0.0",
485 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
486 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
487 | "license": "MIT",
488 | "dependencies": {
489 | "depd": "2.0.0",
490 | "inherits": "2.0.4",
491 | "setprototypeof": "1.2.0",
492 | "statuses": "2.0.1",
493 | "toidentifier": "1.0.1"
494 | },
495 | "engines": {
496 | "node": ">= 0.8"
497 | }
498 | },
499 | "node_modules/iconv-lite": {
500 | "version": "0.4.24",
501 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
502 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
503 | "license": "MIT",
504 | "dependencies": {
505 | "safer-buffer": ">= 2.1.2 < 3"
506 | },
507 | "engines": {
508 | "node": ">=0.10.0"
509 | }
510 | },
511 | "node_modules/inherits": {
512 | "version": "2.0.4",
513 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
514 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
515 | "license": "ISC"
516 | },
517 | "node_modules/ipaddr.js": {
518 | "version": "1.9.1",
519 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
520 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
521 | "license": "MIT",
522 | "engines": {
523 | "node": ">= 0.10"
524 | }
525 | },
526 | "node_modules/media-typer": {
527 | "version": "0.3.0",
528 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
529 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
530 | "license": "MIT",
531 | "engines": {
532 | "node": ">= 0.6"
533 | }
534 | },
535 | "node_modules/merge-descriptors": {
536 | "version": "1.0.3",
537 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
538 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
539 | "license": "MIT",
540 | "funding": {
541 | "url": "https://github.com/sponsors/sindresorhus"
542 | }
543 | },
544 | "node_modules/methods": {
545 | "version": "1.1.2",
546 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
547 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
548 | "license": "MIT",
549 | "engines": {
550 | "node": ">= 0.6"
551 | }
552 | },
553 | "node_modules/mime": {
554 | "version": "1.6.0",
555 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
556 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
557 | "license": "MIT",
558 | "bin": {
559 | "mime": "cli.js"
560 | },
561 | "engines": {
562 | "node": ">=4"
563 | }
564 | },
565 | "node_modules/mime-db": {
566 | "version": "1.52.0",
567 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
568 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
569 | "license": "MIT",
570 | "engines": {
571 | "node": ">= 0.6"
572 | }
573 | },
574 | "node_modules/mime-types": {
575 | "version": "2.1.35",
576 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
577 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
578 | "license": "MIT",
579 | "dependencies": {
580 | "mime-db": "1.52.0"
581 | },
582 | "engines": {
583 | "node": ">= 0.6"
584 | }
585 | },
586 | "node_modules/ms": {
587 | "version": "2.0.0",
588 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
589 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
590 | "license": "MIT"
591 | },
592 | "node_modules/negotiator": {
593 | "version": "0.6.3",
594 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
595 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
596 | "license": "MIT",
597 | "engines": {
598 | "node": ">= 0.6"
599 | }
600 | },
601 | "node_modules/object-inspect": {
602 | "version": "1.13.2",
603 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
604 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
605 | "license": "MIT",
606 | "engines": {
607 | "node": ">= 0.4"
608 | },
609 | "funding": {
610 | "url": "https://github.com/sponsors/ljharb"
611 | }
612 | },
613 | "node_modules/on-finished": {
614 | "version": "2.4.1",
615 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
616 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
617 | "license": "MIT",
618 | "dependencies": {
619 | "ee-first": "1.1.1"
620 | },
621 | "engines": {
622 | "node": ">= 0.8"
623 | }
624 | },
625 | "node_modules/parseurl": {
626 | "version": "1.3.3",
627 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
628 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
629 | "license": "MIT",
630 | "engines": {
631 | "node": ">= 0.8"
632 | }
633 | },
634 | "node_modules/path-to-regexp": {
635 | "version": "0.1.10",
636 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
637 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
638 | "license": "MIT"
639 | },
640 | "node_modules/proxy-addr": {
641 | "version": "2.0.7",
642 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
643 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
644 | "license": "MIT",
645 | "dependencies": {
646 | "forwarded": "0.2.0",
647 | "ipaddr.js": "1.9.1"
648 | },
649 | "engines": {
650 | "node": ">= 0.10"
651 | }
652 | },
653 | "node_modules/qs": {
654 | "version": "6.13.0",
655 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
656 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
657 | "license": "BSD-3-Clause",
658 | "dependencies": {
659 | "side-channel": "^1.0.6"
660 | },
661 | "engines": {
662 | "node": ">=0.6"
663 | },
664 | "funding": {
665 | "url": "https://github.com/sponsors/ljharb"
666 | }
667 | },
668 | "node_modules/range-parser": {
669 | "version": "1.2.1",
670 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
671 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
672 | "license": "MIT",
673 | "engines": {
674 | "node": ">= 0.6"
675 | }
676 | },
677 | "node_modules/raw-body": {
678 | "version": "2.5.2",
679 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
680 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
681 | "license": "MIT",
682 | "dependencies": {
683 | "bytes": "3.1.2",
684 | "http-errors": "2.0.0",
685 | "iconv-lite": "0.4.24",
686 | "unpipe": "1.0.0"
687 | },
688 | "engines": {
689 | "node": ">= 0.8"
690 | }
691 | },
692 | "node_modules/safe-buffer": {
693 | "version": "5.2.1",
694 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
695 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
696 | "funding": [
697 | {
698 | "type": "github",
699 | "url": "https://github.com/sponsors/feross"
700 | },
701 | {
702 | "type": "patreon",
703 | "url": "https://www.patreon.com/feross"
704 | },
705 | {
706 | "type": "consulting",
707 | "url": "https://feross.org/support"
708 | }
709 | ],
710 | "license": "MIT"
711 | },
712 | "node_modules/safer-buffer": {
713 | "version": "2.1.2",
714 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
715 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
716 | "license": "MIT"
717 | },
718 | "node_modules/send": {
719 | "version": "0.19.0",
720 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
721 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
722 | "license": "MIT",
723 | "dependencies": {
724 | "debug": "2.6.9",
725 | "depd": "2.0.0",
726 | "destroy": "1.2.0",
727 | "encodeurl": "~1.0.2",
728 | "escape-html": "~1.0.3",
729 | "etag": "~1.8.1",
730 | "fresh": "0.5.2",
731 | "http-errors": "2.0.0",
732 | "mime": "1.6.0",
733 | "ms": "2.1.3",
734 | "on-finished": "2.4.1",
735 | "range-parser": "~1.2.1",
736 | "statuses": "2.0.1"
737 | },
738 | "engines": {
739 | "node": ">= 0.8.0"
740 | }
741 | },
742 | "node_modules/send/node_modules/encodeurl": {
743 | "version": "1.0.2",
744 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
745 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
746 | "license": "MIT",
747 | "engines": {
748 | "node": ">= 0.8"
749 | }
750 | },
751 | "node_modules/send/node_modules/ms": {
752 | "version": "2.1.3",
753 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
754 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
755 | "license": "MIT"
756 | },
757 | "node_modules/serve-static": {
758 | "version": "1.16.2",
759 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
760 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
761 | "license": "MIT",
762 | "dependencies": {
763 | "encodeurl": "~2.0.0",
764 | "escape-html": "~1.0.3",
765 | "parseurl": "~1.3.3",
766 | "send": "0.19.0"
767 | },
768 | "engines": {
769 | "node": ">= 0.8.0"
770 | }
771 | },
772 | "node_modules/set-function-length": {
773 | "version": "1.2.2",
774 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
775 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
776 | "license": "MIT",
777 | "dependencies": {
778 | "define-data-property": "^1.1.4",
779 | "es-errors": "^1.3.0",
780 | "function-bind": "^1.1.2",
781 | "get-intrinsic": "^1.2.4",
782 | "gopd": "^1.0.1",
783 | "has-property-descriptors": "^1.0.2"
784 | },
785 | "engines": {
786 | "node": ">= 0.4"
787 | }
788 | },
789 | "node_modules/setprototypeof": {
790 | "version": "1.2.0",
791 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
792 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
793 | "license": "ISC"
794 | },
795 | "node_modules/side-channel": {
796 | "version": "1.0.6",
797 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
798 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
799 | "license": "MIT",
800 | "dependencies": {
801 | "call-bind": "^1.0.7",
802 | "es-errors": "^1.3.0",
803 | "get-intrinsic": "^1.2.4",
804 | "object-inspect": "^1.13.1"
805 | },
806 | "engines": {
807 | "node": ">= 0.4"
808 | },
809 | "funding": {
810 | "url": "https://github.com/sponsors/ljharb"
811 | }
812 | },
813 | "node_modules/statuses": {
814 | "version": "2.0.1",
815 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
816 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
817 | "license": "MIT",
818 | "engines": {
819 | "node": ">= 0.8"
820 | }
821 | },
822 | "node_modules/toidentifier": {
823 | "version": "1.0.1",
824 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
825 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
826 | "license": "MIT",
827 | "engines": {
828 | "node": ">=0.6"
829 | }
830 | },
831 | "node_modules/type-is": {
832 | "version": "1.6.18",
833 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
834 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
835 | "license": "MIT",
836 | "dependencies": {
837 | "media-typer": "0.3.0",
838 | "mime-types": "~2.1.24"
839 | },
840 | "engines": {
841 | "node": ">= 0.6"
842 | }
843 | },
844 | "node_modules/typescript": {
845 | "version": "5.6.3",
846 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
847 | "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
848 | "license": "Apache-2.0",
849 | "bin": {
850 | "tsc": "bin/tsc",
851 | "tsserver": "bin/tsserver"
852 | },
853 | "engines": {
854 | "node": ">=14.17"
855 | }
856 | },
857 | "node_modules/undici-types": {
858 | "version": "6.19.8",
859 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
860 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
861 | "license": "MIT"
862 | },
863 | "node_modules/unpipe": {
864 | "version": "1.0.0",
865 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
866 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
867 | "license": "MIT",
868 | "engines": {
869 | "node": ">= 0.8"
870 | }
871 | },
872 | "node_modules/utils-merge": {
873 | "version": "1.0.1",
874 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
875 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
876 | "license": "MIT",
877 | "engines": {
878 | "node": ">= 0.4.0"
879 | }
880 | },
881 | "node_modules/vary": {
882 | "version": "1.1.2",
883 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
884 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
885 | "license": "MIT",
886 | "engines": {
887 | "node": ">= 0.8"
888 | }
889 | }
890 | }
891 | }
892 |
--------------------------------------------------------------------------------
/metaverse/apps/http/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "http",
3 | "version": "1.0.0",
4 | "main": "dist/index.js",
5 | "scripts": {
6 | "build": "npx esbuild src/index.ts --bundle --outfile=dist/index.js --platform=node --tsconfig=tsconfig.json",
7 | "start": "node dist/index.js",
8 | "dev": "npm run build && npm run start"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "description": "",
14 | "dependencies": {
15 | "@repo/db": "workspace:*",
16 | "@types/express": "^5.0.0",
17 | "@types/jsonwebtoken": "^9.0.7",
18 | "esbuild": "^0.24.0",
19 | "express": "^4.21.1",
20 | "jsonwebtoken": "^9.0.2",
21 | "typescript": "^5.6.3",
22 | "zod": "^3.23.8"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/metaverse/apps/http/src/config.ts:
--------------------------------------------------------------------------------
1 | export const JWT_PASSWORD = "123kasdk123"
--------------------------------------------------------------------------------
/metaverse/apps/http/src/index.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import { router } from "./routes/v1";
3 |
4 | const app = express();
5 | app.use(express.json())
6 |
7 | app.use("/api/v1", router)
8 |
9 | app.listen(process.env.PORT || 3000)
10 |
--------------------------------------------------------------------------------
/metaverse/apps/http/src/middleware/admin.ts:
--------------------------------------------------------------------------------
1 |
2 | import jwt from "jsonwebtoken";
3 | import { JWT_PASSWORD } from "../config";
4 | import { NextFunction, Request, Response } from "express";
5 |
6 | export const adminMiddleware = (req: Request, res: Response, next: NextFunction) => {
7 | const header = req.headers["authorization"];
8 | const token = header?.split(" ")[1];
9 |
10 | if (!token) {
11 | res.status(403).json({message: "Unauthorized"})
12 | return
13 | }
14 |
15 | try {
16 | const decoded = jwt.verify(token, JWT_PASSWORD) as { role: string, userId: string }
17 | if (decoded.role !== "Admin") {
18 | res.status(403).json({message: "Unauthorized"})
19 | return
20 | }
21 | req.userId = decoded.userId
22 | next()
23 | } catch(e) {
24 | res.status(401).json({message: "Unauthorized"})
25 | return
26 | }
27 | }
--------------------------------------------------------------------------------
/metaverse/apps/http/src/middleware/user.ts:
--------------------------------------------------------------------------------
1 |
2 | import jwt from "jsonwebtoken";
3 | import { JWT_PASSWORD } from "../config";
4 | import { NextFunction, Request, Response } from "express";
5 |
6 | export const userMiddleware = (req: Request, res: Response, next: NextFunction) => {
7 | const header = req.headers["authorization"];
8 | const token = header?.split(" ")[1];
9 | console.log(req.route.path)
10 | console.log(token)
11 |
12 | if (!token) {
13 | res.status(403).json({message: "Unauthorized"})
14 | return
15 | }
16 |
17 | try {
18 | const decoded = jwt.verify(token, JWT_PASSWORD) as { role: string, userId: string }
19 | req.userId = decoded.userId
20 | next()
21 | } catch(e) {
22 | res.status(401).json({message: "Unauthorized"})
23 | return
24 | }
25 | }
--------------------------------------------------------------------------------
/metaverse/apps/http/src/routes/v1/admin.ts:
--------------------------------------------------------------------------------
1 | import { Router } from "express";
2 | import { adminMiddleware } from "../../middleware/admin";
3 | import { AddElementSchema, CreateAvatarSchema, CreateElementSchema, CreateMapSchema, UpdateElementSchema } from "../../types";
4 | import client from "@repo/db/client";
5 | export const adminRouter = Router();
6 | adminRouter.use(adminMiddleware)
7 |
8 | adminRouter.post("/element", async (req, res) => {
9 | const parsedData = CreateElementSchema.safeParse(req.body)
10 | if (!parsedData.success) {
11 | res.status(400).json({message: "Validation failed"})
12 | return
13 | }
14 |
15 | const element = await client.element.create({
16 | data: {
17 | width: parsedData.data.width,
18 | height: parsedData.data.height,
19 | static: parsedData.data.static,
20 | imageUrl: parsedData.data.imageUrl,
21 | }
22 | })
23 |
24 | res.json({
25 | id: element.id
26 | })
27 | })
28 |
29 | adminRouter.put("/element/:elementId", (req, res) => {
30 | const parsedData = UpdateElementSchema.safeParse(req.body)
31 | if (!parsedData.success) {
32 | res.status(400).json({message: "Validation failed"})
33 | return
34 | }
35 | client.element.update({
36 | where: {
37 | id: req.params.elementId
38 | },
39 | data: {
40 | imageUrl: parsedData.data.imageUrl
41 | }
42 | })
43 | res.json({message: "Element updated"})
44 | })
45 |
46 | adminRouter.post("/avatar", async (req, res) => {
47 | const parsedData = CreateAvatarSchema.safeParse(req.body)
48 | if (!parsedData.success) {
49 | res.status(400).json({message: "Validation failed"})
50 | return
51 | }
52 | const avatar = await client.avatar.create({
53 | data: {
54 | name: parsedData.data.name,
55 | imageUrl: parsedData.data.imageUrl
56 | }
57 | })
58 | res.json({avatarId: avatar.id})
59 | })
60 |
61 | adminRouter.post("/map", async (req, res) => {
62 | const parsedData = CreateMapSchema.safeParse(req.body)
63 | if (!parsedData.success) {
64 | res.status(400).json({message: "Validation failed"})
65 | return
66 | }
67 | const map = await client.map.create({
68 | data: {
69 | name: parsedData.data.name,
70 | width: parseInt(parsedData.data.dimensions.split("x")[0]),
71 | height: parseInt(parsedData.data.dimensions.split("x")[1]),
72 | thumbnail: parsedData.data.thumbnail,
73 | mapElements: {
74 | create: parsedData.data.defaultElements.map(e => ({
75 | elementId: e.elementId,
76 | x: e.x,
77 | y: e.y
78 | }))
79 | }
80 | }
81 | })
82 |
83 | res.json({
84 | id: map.id
85 | })
86 | })
--------------------------------------------------------------------------------
/metaverse/apps/http/src/routes/v1/index.ts:
--------------------------------------------------------------------------------
1 | import { Router } from "express";
2 | import { userRouter } from "./user";
3 | import { spaceRouter } from "./space";
4 | import { adminRouter } from "./admin";
5 | import { SigninSchema, SignupSchema } from "../../types";
6 | import {hash, compare} from "../../scrypt";
7 | import client from "@repo/db/client";
8 | import jwt from "jsonwebtoken";
9 | import { JWT_PASSWORD } from "../../config";
10 |
11 | export const router = Router();
12 |
13 | router.post("/signup", async (req, res) => {
14 | console.log("inside signup")
15 | // check the user
16 | const parsedData = SignupSchema.safeParse(req.body)
17 | if (!parsedData.success) {
18 | console.log("parsed data incorrect")
19 | res.status(400).json({message: "Validation failed"})
20 | return
21 | }
22 |
23 | const hashedPassword = await hash(parsedData.data.password)
24 |
25 | try {
26 | const user = await client.user.create({
27 | data: {
28 | username: parsedData.data.username,
29 | password: hashedPassword,
30 | role: parsedData.data.type === "admin" ? "Admin" : "User",
31 | }
32 | })
33 | res.json({
34 | userId: user.id
35 | })
36 | } catch(e) {
37 | console.log("erroer thrown")
38 | console.log(e)
39 | res.status(400).json({message: "User already exists"})
40 | }
41 | })
42 |
43 | router.post("/signin", async (req, res) => {
44 | const parsedData = SigninSchema.safeParse(req.body)
45 | if (!parsedData.success) {
46 | res.status(403).json({message: "Validation failed"})
47 | return
48 | }
49 |
50 | try {
51 | const user = await client.user.findUnique({
52 | where: {
53 | username: parsedData.data.username
54 | }
55 | })
56 |
57 | if (!user) {
58 | res.status(403).json({message: "User not found"})
59 | return
60 | }
61 | const isValid = await compare(parsedData.data.password, user.password)
62 |
63 | if (!isValid) {
64 | res.status(403).json({message: "Invalid password"})
65 | return
66 | }
67 |
68 | const token = jwt.sign({
69 | userId: user.id,
70 | role: user.role
71 | }, JWT_PASSWORD);
72 |
73 | res.json({
74 | token
75 | })
76 | } catch(e) {
77 | res.status(400).json({message: "Internal server error"})
78 | }
79 | })
80 |
81 | router.get("/elements", async (req, res) => {
82 | const elements = await client.element.findMany()
83 |
84 | res.json({elements: elements.map(e => ({
85 | id: e.id,
86 | imageUrl: e.imageUrl,
87 | width: e.width,
88 | height: e.height,
89 | static: e.static
90 | }))})
91 | })
92 |
93 | router.get("/avatars", async (req, res) => {
94 | const avatars = await client.avatar.findMany()
95 | res.json({avatars: avatars.map(x => ({
96 | id: x.id,
97 | imageUrl: x.imageUrl,
98 | name: x.name
99 | }))})
100 | })
101 |
102 | router.use("/user", userRouter)
103 | router.use("/space", spaceRouter)
104 | router.use("/admin", adminRouter)
105 |
--------------------------------------------------------------------------------
/metaverse/apps/http/src/routes/v1/space.ts:
--------------------------------------------------------------------------------
1 | import { Router } from "express";
2 | import client from "@repo/db/client";
3 | import { userMiddleware } from "../../middleware/user";
4 | import { AddElementSchema, CreateElementSchema, CreateSpaceSchema, DeleteElementSchema } from "../../types";
5 | export const spaceRouter = Router();
6 |
7 | spaceRouter.post("/", userMiddleware, async (req, res) => {
8 | console.log("endopibnt")
9 | const parsedData = CreateSpaceSchema.safeParse(req.body)
10 | if (!parsedData.success) {
11 | console.log(JSON.stringify(parsedData))
12 | res.status(400).json({message: "Validation failed"})
13 | return
14 | }
15 |
16 | if (!parsedData.data.mapId) {
17 | const space = await client.space.create({
18 | data: {
19 | name: parsedData.data.name,
20 | width: parseInt(parsedData.data.dimensions.split("x")[0]),
21 | height: parseInt(parsedData.data.dimensions.split("x")[1]),
22 | creatorId: req.userId!
23 | }
24 | });
25 | res.json({spaceId: space.id})
26 | return;
27 | }
28 |
29 | const map = await client.map.findFirst({
30 | where: {
31 | id: parsedData.data.mapId
32 | }, select: {
33 | mapElements: true,
34 | width: true,
35 | height: true
36 | }
37 | })
38 | console.log("after")
39 | if (!map) {
40 | res.status(400).json({message: "Map not found"})
41 | return
42 | }
43 | console.log("map.mapElements.length")
44 | console.log(map.mapElements.length)
45 | let space = await client.$transaction(async () => {
46 | const space = await client.space.create({
47 | data: {
48 | name: parsedData.data.name,
49 | width: map.width,
50 | height: map.height,
51 | creatorId: req.userId!,
52 | }
53 | });
54 |
55 | await client.spaceElements.createMany({
56 | data: map.mapElements.map(e => ({
57 | spaceId: space.id,
58 | elementId: e.elementId,
59 | x: e.x!,
60 | y: e.y!
61 | }))
62 | })
63 |
64 | return space;
65 |
66 | })
67 | console.log("space crated")
68 | res.json({spaceId: space.id})
69 | })
70 |
71 |
72 | spaceRouter.delete("/element", userMiddleware, async (req, res) => {
73 | console.log("spaceElement?.space1 ")
74 | const parsedData = DeleteElementSchema.safeParse(req.body)
75 | if (!parsedData.success) {
76 | res.status(400).json({message: "Validation failed"})
77 | return
78 | }
79 | const spaceElement = await client.spaceElements.findFirst({
80 | where: {
81 | id: parsedData.data.id
82 | },
83 | include: {
84 | space: true
85 | }
86 | })
87 | console.log(spaceElement?.space)
88 | console.log("spaceElement?.space")
89 | if (!spaceElement?.space.creatorId || spaceElement.space.creatorId !== req.userId) {
90 | res.status(403).json({message: "Unauthorized"})
91 | return
92 | }
93 | await client.spaceElements.delete({
94 | where: {
95 | id: parsedData.data.id
96 | }
97 | })
98 | res.json({message: "Element deleted"})
99 | })
100 |
101 | spaceRouter.delete("/:spaceId", userMiddleware, async(req, res) => {
102 | console.log("req.params.spaceId", req.params.spaceId)
103 | const space = await client.space.findUnique({
104 | where: {
105 | id: req.params.spaceId
106 | }, select: {
107 | creatorId: true
108 | }
109 | })
110 | if (!space) {
111 | res.status(400).json({message: "Space not found"})
112 | return
113 | }
114 |
115 | if (space.creatorId !== req.userId) {
116 | console.log("code should reach here")
117 | res.status(403).json({message: "Unauthorized"})
118 | return
119 | }
120 |
121 | await client.space.delete({
122 | where: {
123 | id: req.params.spaceId
124 | }
125 | })
126 | res.json({message: "Space deleted"})
127 | })
128 |
129 | spaceRouter.get("/all", userMiddleware, async (req, res) => {
130 | const spaces = await client.space.findMany({
131 | where: {
132 | creatorId: req.userId!
133 | }
134 | });
135 |
136 | res.json({
137 | spaces: spaces.map(s => ({
138 | id: s.id,
139 | name: s.name,
140 | thumbnail: s.thumbnail,
141 | dimensions: `${s.width}x${s.height}`,
142 | }))
143 | })
144 |
145 |
146 | })
147 |
148 | spaceRouter.post("/element", userMiddleware, async (req, res) => {
149 | const parsedData = AddElementSchema.safeParse(req.body)
150 | if (!parsedData.success) {
151 | res.status(400).json({message: "Validation failed"})
152 | return
153 | }
154 | const space = await client.space.findUnique({
155 | where: {
156 | id: req.body.spaceId,
157 | creatorId: req.userId!
158 | }, select: {
159 | width: true,
160 | height: true
161 | }
162 | })
163 |
164 | if(req.body.x < 0 || req.body.y < 0 || req.body.x > space?.width! || req.body.y > space?.height!) {
165 | res.status(400).json({message: "Point is outside of the boundary"})
166 | return
167 | }
168 |
169 | if (!space) {
170 | res.status(400).json({message: "Space not found"})
171 | return
172 | }
173 | await client.spaceElements.create({
174 | data: {
175 | spaceId: req.body.spaceId,
176 | elementId: req.body.elementId,
177 | x: req.body.x,
178 | y: req.body.y
179 | }
180 | })
181 |
182 | res.json({message: "Element added"})
183 | })
184 |
185 | spaceRouter.get("/:spaceId",async (req, res) => {
186 | const space = await client.space.findUnique({
187 | where: {
188 | id: req.params.spaceId
189 | },
190 | include: {
191 | elements: {
192 | include: {
193 | element: true
194 | }
195 | },
196 | }
197 | })
198 |
199 | if (!space) {
200 | res.status(400).json({message: "Space not found"})
201 | return
202 | }
203 |
204 | res.json({
205 | "dimensions": `${space.width}x${space.height}`,
206 | elements: space.elements.map(e => ({
207 | id: e.id,
208 | element: {
209 | id: e.element.id,
210 | imageUrl: e.element.imageUrl,
211 | width: e.element.width,
212 | height: e.element.height,
213 | static: e.element.static
214 | },
215 | x: e.x,
216 | y: e.y
217 | })),
218 | })
219 | })
--------------------------------------------------------------------------------
/metaverse/apps/http/src/routes/v1/user.ts:
--------------------------------------------------------------------------------
1 | import { Router } from "express";
2 | import { UpdateMetadataSchema } from "../../types";
3 | import client from "@repo/db/client";
4 | import { userMiddleware } from "../../middleware/user";
5 |
6 | export const userRouter = Router();
7 |
8 | userRouter.post("/metadata", userMiddleware, async (req, res) => {
9 | const parsedData = UpdateMetadataSchema.safeParse(req.body)
10 | if (!parsedData.success) {
11 | console.log("parsed data incorrect")
12 | res.status(400).json({message: "Validation failed"})
13 | return
14 | }
15 | try {
16 | await client.user.update({
17 | where: {
18 | id: req.userId
19 | },
20 | data: {
21 | avatarId: parsedData.data.avatarId
22 | }
23 | })
24 | res.json({message: "Metadata updated"})
25 | } catch(e) {
26 | console.log("error")
27 | res.status(400).json({message: "Internal server error"})
28 | }
29 | })
30 |
31 | userRouter.get("/metadata/bulk", async (req, res) => {
32 | const userIdString = (req.query.ids ?? "[]") as string;
33 | const userIds = (userIdString).slice(1, userIdString?.length - 1).split(",");
34 | console.log(userIds)
35 | const metadata = await client.user.findMany({
36 | where: {
37 | id: {
38 | in: userIds
39 | }
40 | }, select: {
41 | avatar: true,
42 | id: true
43 | }
44 | })
45 |
46 | res.json({
47 | avatars: metadata.map(m => ({
48 | userId: m.id,
49 | avatarId: m.avatar?.imageUrl
50 | }))
51 | })
52 | })
--------------------------------------------------------------------------------
/metaverse/apps/http/src/scrypt.ts:
--------------------------------------------------------------------------------
1 | import { randomBytes, scrypt, timingSafeEqual } from 'node:crypto';
2 |
3 | /**
4 | * https://dev.to/advename/comment/24a9e
5 | */
6 | const keyLength = 32;
7 |
8 | /**
9 | * Has a password or a secret with a password hashing algorithm (scrypt)
10 | * @param {string} password
11 | * @returns {string} The salt+hash
12 | */
13 | export const hash = async (password: string): Promise => {
14 | return new Promise((resolve, reject) => {
15 | // generate random 16 bytes long salt - recommended by NodeJS Docs
16 | const salt = randomBytes(16).toString('hex');
17 |
18 | scrypt(password, salt, keyLength, (error, derivedKey) => {
19 | if (error) reject(error);
20 | // derivedKey is of type Buffer
21 | resolve(`${salt}.${derivedKey.toString('hex')}`);
22 | });
23 | });
24 | };
25 |
26 | /**
27 | * Compare a plain text password with a salt+hash password
28 | * @param {string} password The plain text password
29 | * @param {string} hash The hash+salt to check against
30 | * @returns {boolean}
31 | */
32 | export const compare = async (password: string, hash: string): Promise => {
33 | return new Promise((resolve, reject) => {
34 | const [salt, hashKey] = hash.split('.');
35 | // we need to pass buffer values to timingSafeEqual
36 | const hashKeyBuff = Buffer.from(hashKey, 'hex');
37 | scrypt(password, salt, keyLength, (error, derivedKey) => {
38 | if (error) reject(error);
39 | // compare the new supplied password with the hashed password using timeSafeEqual
40 | resolve(timingSafeEqual(hashKeyBuff, derivedKey));
41 | });
42 | });
43 | };
--------------------------------------------------------------------------------
/metaverse/apps/http/src/types/index.ts:
--------------------------------------------------------------------------------
1 | import z from "zod";
2 |
3 | export const SignupSchema = z.object({
4 | username: z.string(),
5 | password: z.string(),
6 | type: z.enum(["user", "admin"]),
7 | })
8 |
9 | export const SigninSchema = z.object({
10 | username: z.string(),
11 | password: z.string(),
12 | })
13 |
14 | export const UpdateMetadataSchema = z.object({
15 | avatarId: z.string()
16 | })
17 |
18 | export const CreateSpaceSchema = z.object({
19 | name: z.string(),
20 | dimensions: z.string().regex(/^[0-9]{1,4}x[0-9]{1,4}$/),
21 | mapId: z.string().optional(),
22 | })
23 |
24 | export const DeleteElementSchema = z.object({
25 | id: z.string(),
26 | })
27 |
28 | export const AddElementSchema = z.object({
29 | spaceId: z.string(),
30 | elementId: z.string(),
31 | x: z.number(),
32 | y: z.number(),
33 | })
34 |
35 | export const CreateElementSchema = z.object({
36 | imageUrl: z.string(),
37 | width: z.number(),
38 | height: z.number(),
39 | static: z.boolean(),
40 | })
41 |
42 | export const UpdateElementSchema = z.object({
43 | imageUrl: z.string(),
44 | })
45 |
46 | export const CreateAvatarSchema = z.object({
47 | name: z.string(),
48 | imageUrl: z.string(),
49 | })
50 |
51 | export const CreateMapSchema = z.object({
52 | thumbnail: z.string(),
53 | dimensions: z.string().regex(/^[0-9]{1,4}x[0-9]{1,4}$/),
54 | name: z.string(),
55 | defaultElements: z.array(z.object({
56 | elementId: z.string(),
57 | x: z.number(),
58 | y: z.number(),
59 | }))
60 | })
61 |
62 |
63 | declare global {
64 | namespace Express {
65 | export interface Request {
66 | role?: "Admin" | "User";
67 | userId?: string;
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/metaverse/apps/http/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2016",
4 | /* Modules */
5 | "rootDir": "./src", /* Specify the root folder within your source files. */
6 | "module": "NodeNext",
7 | "moduleDetection": "force",
8 | "moduleResolution": "NodeNext",
9 | "outDir": "./dist",
10 | "esModuleInterop": true,
11 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
12 | "strict": true, /* Enable all strict type-checking options. */
13 | "skipLibCheck": true,
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/metaverse/apps/http/tsconfig.tsbuildinfo:
--------------------------------------------------------------------------------
1 | {"root":["./src/config.ts","./src/index.ts","./src/scrypt.ts","./src/middleware/admin.ts","./src/middleware/user.ts","./src/routes/v1/admin.ts","./src/routes/v1/index.ts","./src/routes/v1/space.ts","./src/routes/v1/user.ts","./src/types/index.ts"],"version":"5.6.3"}
--------------------------------------------------------------------------------
/metaverse/apps/ws/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ws",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "scripts": {
6 | "build": "npx esbuild src/index.ts --bundle --outfile=dist/index.js --platform=node --tsconfig=tsconfig.json",
7 | "start": "node dist/index.js",
8 | "dev": "npm run build && npm run start"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "description": "",
14 | "dependencies": {
15 | "@repo/db": "workspace:*",
16 | "@types/jsonwebtoken": "^9.0.7",
17 | "@types/ws": "^8.5.12",
18 | "esbuild": "^0.24.0",
19 | "jsonwebtoken": "^9.0.2",
20 | "ws": "^8.18.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/metaverse/apps/ws/src/RoomManager.ts:
--------------------------------------------------------------------------------
1 | import type { User } from "./User";
2 | import { OutgoingMessage } from "./types";
3 |
4 | export class RoomManager {
5 | rooms: Map = new Map();
6 | static instance: RoomManager;
7 |
8 | private constructor() {
9 | this.rooms = new Map();
10 | }
11 |
12 | static getInstance() {
13 | if (!this.instance) {
14 | this.instance = new RoomManager();
15 | }
16 | return this.instance;
17 | }
18 |
19 | public removeUser(user: User, spaceId: string) {
20 | if (!this.rooms.has(spaceId)) {
21 | return;
22 | }
23 | this.rooms.set(spaceId, (this.rooms.get(spaceId)?.filter((u) => u.id !== user.id) ?? []));
24 | }
25 |
26 | public addUser(spaceId: string, user: User) {
27 | if (!this.rooms.has(spaceId)) {
28 | this.rooms.set(spaceId, [user]);
29 | return;
30 | }
31 | this.rooms.set(spaceId, [...(this.rooms.get(spaceId) ?? []), user]);
32 | }
33 |
34 | public broadcast(message: OutgoingMessage, user: User, roomId: string) {
35 | if (!this.rooms.has(roomId)) {
36 | return;
37 | }
38 | this.rooms.get(roomId)?.forEach((u) => {
39 | if (u.id !== user.id) {
40 | u.send(message);
41 | }
42 | });
43 | }
44 | }
--------------------------------------------------------------------------------
/metaverse/apps/ws/src/User.ts:
--------------------------------------------------------------------------------
1 | import { WebSocket } from "ws";
2 | import { RoomManager } from "./RoomManager";
3 | import { OutgoingMessage } from "./types";
4 | import client from "@repo/db/client";
5 | import jwt, { JwtPayload } from "jsonwebtoken";
6 | import { JWT_PASSWORD } from "./config";
7 |
8 | function getRandomString(length: number) {
9 | const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
10 | let result = "";
11 | for (let i = 0; i < length; i++) {
12 | result += characters.charAt(Math.floor(Math.random() * characters.length));
13 | }
14 | return result;
15 | }
16 |
17 | export class User {
18 | public id: string;
19 | public userId?: string;
20 | private spaceId?: string;
21 | private x: number;
22 | private y: number;
23 | private ws: WebSocket;
24 |
25 | constructor(ws: WebSocket) {
26 | this.id = getRandomString(10);
27 | this.x = 0;
28 | this.y = 0;
29 | this.ws = ws;
30 | this.initHandlers()
31 | }
32 |
33 | initHandlers() {
34 | this.ws.on("message", async (data) => {
35 | console.log(data)
36 | const parsedData = JSON.parse(data.toString());
37 | console.log(parsedData)
38 | console.log("parsedData")
39 | switch (parsedData.type) {
40 | case "join":
41 | console.log("jouin receiverdfd")
42 | const spaceId = parsedData.payload.spaceId;
43 | const token = parsedData.payload.token;
44 | const userId = (jwt.verify(token, JWT_PASSWORD) as JwtPayload).userId
45 | if (!userId) {
46 | this.ws.close()
47 | return
48 | }
49 | console.log("jouin receiverdfd 2")
50 | this.userId = userId
51 | const space = await client.space.findFirst({
52 | where: {
53 | id: spaceId
54 | }
55 | })
56 | console.log("jouin receiverdfd 3")
57 | if (!space) {
58 | this.ws.close()
59 | return;
60 | }
61 | console.log("jouin receiverdfd 4")
62 | this.spaceId = spaceId
63 | RoomManager.getInstance().addUser(spaceId, this);
64 | this.x = Math.floor(Math.random() * space?.width);
65 | this.y = Math.floor(Math.random() * space?.height);
66 | this.send({
67 | type: "space-joined",
68 | payload: {
69 | spawn: {
70 | x: this.x,
71 | y: this.y
72 | },
73 | users: RoomManager.getInstance().rooms.get(spaceId)?.filter(x => x.id !== this.id)?.map((u) => ({id: u.id})) ?? []
74 | }
75 | });
76 | console.log("jouin receiverdf5")
77 | RoomManager.getInstance().broadcast({
78 | type: "user-joined",
79 | payload: {
80 | userId: this.userId,
81 | x: this.x,
82 | y: this.y
83 | }
84 | }, this, this.spaceId!);
85 | break;
86 | case "move":
87 | const moveX = parsedData.payload.x;
88 | const moveY = parsedData.payload.y;
89 | const xDisplacement = Math.abs(this.x - moveX);
90 | const yDisplacement = Math.abs(this.y - moveY);
91 | if ((xDisplacement == 1 && yDisplacement== 0) || (xDisplacement == 0 && yDisplacement == 1)) {
92 | this.x = moveX;
93 | this.y = moveY;
94 | RoomManager.getInstance().broadcast({
95 | type: "movement",
96 | payload: {
97 | x: this.x,
98 | y: this.y
99 | }
100 | }, this, this.spaceId!);
101 | return;
102 | }
103 |
104 | this.send({
105 | type: "movement-rejected",
106 | payload: {
107 | x: this.x,
108 | y: this.y
109 | }
110 | });
111 |
112 | }
113 | });
114 | }
115 |
116 | destroy() {
117 | RoomManager.getInstance().broadcast({
118 | type: "user-left",
119 | payload: {
120 | userId: this.userId
121 | }
122 | }, this, this.spaceId!);
123 | RoomManager.getInstance().removeUser(this, this.spaceId!);
124 | }
125 |
126 | send(payload: OutgoingMessage) {
127 | this.ws.send(JSON.stringify(payload));
128 | }
129 | }
--------------------------------------------------------------------------------
/metaverse/apps/ws/src/config.ts:
--------------------------------------------------------------------------------
1 | export const JWT_PASSWORD = "123kasdk123"
--------------------------------------------------------------------------------
/metaverse/apps/ws/src/index.ts:
--------------------------------------------------------------------------------
1 | import { WebSocketServer } from 'ws';
2 | import { User } from './User';
3 |
4 | const wss = new WebSocketServer({ port: 3001 });
5 |
6 | wss.on('connection', function connection(ws) {
7 | console.log("yser connected")
8 | let user = new User(ws);
9 | ws.on('error', console.error);
10 |
11 | ws.on('close', () => {
12 | user?.destroy();
13 | });
14 | });
--------------------------------------------------------------------------------
/metaverse/apps/ws/src/types.ts:
--------------------------------------------------------------------------------
1 | export type OutgoingMessage = any;
--------------------------------------------------------------------------------
/metaverse/apps/ws/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2016",
4 | /* Modules */
5 | "rootDir": "./src", /* Specify the root folder within your source files. */
6 | "module": "NodeNext",
7 | "moduleDetection": "force",
8 | "moduleResolution": "NodeNext",
9 | "outDir": "./dist",
10 | "esModuleInterop": true,
11 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
12 | "strict": true, /* Enable all strict type-checking options. */
13 | "skipLibCheck": true,
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/metaverse/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "metaverse",
3 | "private": true,
4 | "scripts": {
5 | "build": "turbo build",
6 | "dev": "turbo dev",
7 | "lint": "turbo lint",
8 | "format": "prettier --write \"**/*.{ts,tsx,md}\""
9 | },
10 | "devDependencies": {
11 | "prettier": "^3.2.5",
12 | "turbo": "^2.2.3",
13 | "typescript": "5.5.4"
14 | },
15 | "packageManager": "pnpm@8.15.6",
16 | "engines": {
17 | "node": ">=18"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/metaverse/packages/db/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | # Keep environment variables out of version control
3 | .env
4 |
--------------------------------------------------------------------------------
/metaverse/packages/db/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@repo/db",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "@repo/db",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "@prisma/client": "^5.21.1",
13 | "prisma": "^5.21.1",
14 | "typescript": "^5.6.3"
15 | }
16 | },
17 | "node_modules/@prisma/client": {
18 | "version": "5.21.1",
19 | "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.21.1.tgz",
20 | "integrity": "sha512-3n+GgbAZYjaS/k0M03yQsQfR1APbr411r74foknnsGpmhNKBG49VuUkxIU6jORgvJPChoD4WC4PqoHImN1FP0w==",
21 | "hasInstallScript": true,
22 | "license": "Apache-2.0",
23 | "engines": {
24 | "node": ">=16.13"
25 | },
26 | "peerDependencies": {
27 | "prisma": "*"
28 | },
29 | "peerDependenciesMeta": {
30 | "prisma": {
31 | "optional": true
32 | }
33 | }
34 | },
35 | "node_modules/@prisma/debug": {
36 | "version": "5.21.1",
37 | "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.21.1.tgz",
38 | "integrity": "sha512-uY8SAhcnORhvgtOrNdvWS98Aq/nkQ9QDUxrWAgW8XrCZaI3j2X7zb7Xe6GQSh6xSesKffFbFlkw0c2luHQviZA==",
39 | "license": "Apache-2.0"
40 | },
41 | "node_modules/@prisma/engines": {
42 | "version": "5.21.1",
43 | "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.21.1.tgz",
44 | "integrity": "sha512-hGVTldUkIkTwoV8//hmnAAiAchi4oMEKD3aW5H2RrnI50tTdwza7VQbTTAyN3OIHWlK5DVg6xV7X8N/9dtOydA==",
45 | "hasInstallScript": true,
46 | "license": "Apache-2.0",
47 | "dependencies": {
48 | "@prisma/debug": "5.21.1",
49 | "@prisma/engines-version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36",
50 | "@prisma/fetch-engine": "5.21.1",
51 | "@prisma/get-platform": "5.21.1"
52 | }
53 | },
54 | "node_modules/@prisma/engines-version": {
55 | "version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36",
56 | "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36.tgz",
57 | "integrity": "sha512-qvnEflL0//lh44S/T9NcvTMxfyowNeUxTunPcDfKPjyJNrCNf2F1zQLcUv5UHAruECpX+zz21CzsC7V2xAeM7Q==",
58 | "license": "Apache-2.0"
59 | },
60 | "node_modules/@prisma/fetch-engine": {
61 | "version": "5.21.1",
62 | "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.21.1.tgz",
63 | "integrity": "sha512-70S31vgpCGcp9J+mh/wHtLCkVezLUqe/fGWk3J3JWZIN7prdYSlr1C0niaWUyNK2VflLXYi8kMjAmSxUVq6WGQ==",
64 | "license": "Apache-2.0",
65 | "dependencies": {
66 | "@prisma/debug": "5.21.1",
67 | "@prisma/engines-version": "5.21.1-1.bf0e5e8a04cada8225617067eaa03d041e2bba36",
68 | "@prisma/get-platform": "5.21.1"
69 | }
70 | },
71 | "node_modules/@prisma/get-platform": {
72 | "version": "5.21.1",
73 | "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.21.1.tgz",
74 | "integrity": "sha512-sRxjL3Igst3ct+e8ya/x//cDXmpLbZQ5vfps2N4tWl4VGKQAmym77C/IG/psSMsQKszc8uFC/q1dgmKFLUgXZQ==",
75 | "license": "Apache-2.0",
76 | "dependencies": {
77 | "@prisma/debug": "5.21.1"
78 | }
79 | },
80 | "node_modules/fsevents": {
81 | "version": "2.3.3",
82 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
83 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
84 | "hasInstallScript": true,
85 | "license": "MIT",
86 | "optional": true,
87 | "os": [
88 | "darwin"
89 | ],
90 | "engines": {
91 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
92 | }
93 | },
94 | "node_modules/prisma": {
95 | "version": "5.21.1",
96 | "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.21.1.tgz",
97 | "integrity": "sha512-PB+Iqzld/uQBPaaw2UVIk84kb0ITsLajzsxzsadxxl54eaU5Gyl2/L02ysivHxK89t7YrfQJm+Ggk37uvM70oQ==",
98 | "hasInstallScript": true,
99 | "license": "Apache-2.0",
100 | "dependencies": {
101 | "@prisma/engines": "5.21.1"
102 | },
103 | "bin": {
104 | "prisma": "build/index.js"
105 | },
106 | "engines": {
107 | "node": ">=16.13"
108 | },
109 | "optionalDependencies": {
110 | "fsevents": "2.3.3"
111 | }
112 | },
113 | "node_modules/typescript": {
114 | "version": "5.6.3",
115 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
116 | "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
117 | "license": "Apache-2.0",
118 | "bin": {
119 | "tsc": "bin/tsc",
120 | "tsserver": "bin/tsserver"
121 | },
122 | "engines": {
123 | "node": ">=14.17"
124 | }
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/metaverse/packages/db/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@repo/db",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "build": "tsc -b"
7 | },
8 | "exports": {
9 | "./client": "./src/index.ts"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "description": "",
15 | "dependencies": {
16 | "@prisma/client": "^5.21.1",
17 | "prisma": "^5.21.1",
18 | "typescript": "^5.6.3"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/metaverse/packages/db/prisma/migrations/20241030155258_init/migration.sql:
--------------------------------------------------------------------------------
1 | -- CreateEnum
2 | CREATE TYPE "Role" AS ENUM ('Admin', 'User');
3 |
4 | -- CreateTable
5 | CREATE TABLE "User" (
6 | "id" TEXT NOT NULL,
7 | "username" TEXT NOT NULL,
8 | "password" TEXT NOT NULL,
9 | "avatarId" TEXT NOT NULL,
10 | "role" "Role" NOT NULL,
11 |
12 | CONSTRAINT "User_pkey" PRIMARY KEY ("id")
13 | );
14 |
15 | -- CreateTable
16 | CREATE TABLE "Space" (
17 | "id" TEXT NOT NULL,
18 | "name" TEXT NOT NULL,
19 | "width" INTEGER NOT NULL,
20 | "height" INTEGER,
21 | "thumbnail" TEXT,
22 | "creatorId" TEXT NOT NULL,
23 |
24 | CONSTRAINT "Space_pkey" PRIMARY KEY ("id")
25 | );
26 |
27 | -- CreateTable
28 | CREATE TABLE "spaceElements" (
29 | "id" TEXT NOT NULL,
30 | "elementId" TEXT NOT NULL,
31 | "spaceId" TEXT NOT NULL,
32 | "x" INTEGER NOT NULL,
33 | "y" INTEGER NOT NULL,
34 |
35 | CONSTRAINT "spaceElements_pkey" PRIMARY KEY ("id")
36 | );
37 |
38 | -- CreateTable
39 | CREATE TABLE "Element" (
40 | "id" TEXT NOT NULL,
41 | "width" INTEGER NOT NULL,
42 | "height" INTEGER NOT NULL,
43 | "imageUrl" TEXT NOT NULL,
44 |
45 | CONSTRAINT "Element_pkey" PRIMARY KEY ("id")
46 | );
47 |
48 | -- CreateTable
49 | CREATE TABLE "Map" (
50 | "id" TEXT NOT NULL,
51 | "width" INTEGER NOT NULL,
52 | "height" INTEGER NOT NULL,
53 | "name" TEXT NOT NULL,
54 |
55 | CONSTRAINT "Map_pkey" PRIMARY KEY ("id")
56 | );
57 |
58 | -- CreateTable
59 | CREATE TABLE "MapElements" (
60 | "id" TEXT NOT NULL,
61 | "mapId" TEXT NOT NULL,
62 | "elementId" TEXT NOT NULL,
63 | "x" INTEGER,
64 | "y" INTEGER,
65 |
66 | CONSTRAINT "MapElements_pkey" PRIMARY KEY ("id")
67 | );
68 |
69 | -- CreateTable
70 | CREATE TABLE "Avatar" (
71 | "id" TEXT NOT NULL,
72 | "imageUrl" TEXT,
73 | "name" TEXT,
74 |
75 | CONSTRAINT "Avatar_pkey" PRIMARY KEY ("id")
76 | );
77 |
78 | -- CreateIndex
79 | CREATE UNIQUE INDEX "User_id_key" ON "User"("id");
80 |
81 | -- CreateIndex
82 | CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
83 |
84 | -- CreateIndex
85 | CREATE UNIQUE INDEX "User_password_key" ON "User"("password");
86 |
87 | -- CreateIndex
88 | CREATE UNIQUE INDEX "Space_id_key" ON "Space"("id");
89 |
90 | -- CreateIndex
91 | CREATE UNIQUE INDEX "spaceElements_id_key" ON "spaceElements"("id");
92 |
93 | -- CreateIndex
94 | CREATE UNIQUE INDEX "Element_id_key" ON "Element"("id");
95 |
96 | -- CreateIndex
97 | CREATE UNIQUE INDEX "Map_id_key" ON "Map"("id");
98 |
99 | -- CreateIndex
100 | CREATE UNIQUE INDEX "MapElements_id_key" ON "MapElements"("id");
101 |
102 | -- CreateIndex
103 | CREATE UNIQUE INDEX "Avatar_id_key" ON "Avatar"("id");
104 |
105 | -- AddForeignKey
106 | ALTER TABLE "User" ADD CONSTRAINT "User_avatarId_fkey" FOREIGN KEY ("avatarId") REFERENCES "Avatar"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
107 |
108 | -- AddForeignKey
109 | ALTER TABLE "Space" ADD CONSTRAINT "Space_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
110 |
111 | -- AddForeignKey
112 | ALTER TABLE "spaceElements" ADD CONSTRAINT "spaceElements_spaceId_fkey" FOREIGN KEY ("spaceId") REFERENCES "Space"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
113 |
114 | -- AddForeignKey
115 | ALTER TABLE "spaceElements" ADD CONSTRAINT "spaceElements_elementId_fkey" FOREIGN KEY ("elementId") REFERENCES "Element"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
116 |
117 | -- AddForeignKey
118 | ALTER TABLE "MapElements" ADD CONSTRAINT "MapElements_mapId_fkey" FOREIGN KEY ("mapId") REFERENCES "Map"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
119 |
120 | -- AddForeignKey
121 | ALTER TABLE "MapElements" ADD CONSTRAINT "MapElements_elementId_fkey" FOREIGN KEY ("elementId") REFERENCES "Element"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
122 |
--------------------------------------------------------------------------------
/metaverse/packages/db/prisma/migrations/20241030164544_made_password_non_unique/migration.sql:
--------------------------------------------------------------------------------
1 | -- DropIndex
2 | DROP INDEX "User_password_key";
3 |
--------------------------------------------------------------------------------
/metaverse/packages/db/prisma/migrations/20241030164722_made_avatar_optional/migration.sql:
--------------------------------------------------------------------------------
1 | -- DropForeignKey
2 | ALTER TABLE "User" DROP CONSTRAINT "User_avatarId_fkey";
3 |
4 | -- AlterTable
5 | ALTER TABLE "User" ALTER COLUMN "avatarId" DROP NOT NULL;
6 |
7 | -- AddForeignKey
8 | ALTER TABLE "User" ADD CONSTRAINT "User_avatarId_fkey" FOREIGN KEY ("avatarId") REFERENCES "Avatar"("id") ON DELETE SET NULL ON UPDATE CASCADE;
9 |
--------------------------------------------------------------------------------
/metaverse/packages/db/prisma/migrations/20241031112104_add_static/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - Added the required column `static` to the `Element` table without a default value. This is not possible if the table is not empty.
5 | - Made the column `height` on table `Space` required. This step will fail if there are existing NULL values in that column.
6 |
7 | */
8 | -- AlterTable
9 | ALTER TABLE "Element" ADD COLUMN "static" BOOLEAN NOT NULL;
10 |
11 | -- AlterTable
12 | ALTER TABLE "Space" ALTER COLUMN "height" SET NOT NULL;
13 |
--------------------------------------------------------------------------------
/metaverse/packages/db/prisma/migrations/20241031112726_add_thumbnail/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - Added the required column `thumbnail` to the `Map` table without a default value. This is not possible if the table is not empty.
5 |
6 | */
7 | -- AlterTable
8 | ALTER TABLE "Map" ADD COLUMN "thumbnail" TEXT NOT NULL;
9 |
--------------------------------------------------------------------------------
/metaverse/packages/db/prisma/migrations/migration_lock.toml:
--------------------------------------------------------------------------------
1 | # Please do not edit this file manually
2 | # It should be added in your version-control system (i.e. Git)
3 | provider = "postgresql"
--------------------------------------------------------------------------------
/metaverse/packages/db/prisma/schema.prisma:
--------------------------------------------------------------------------------
1 | // This is your Prisma schema file,
2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema
3 |
4 | // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
5 | // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
6 |
7 | generator client {
8 | provider = "prisma-client-js"
9 | }
10 |
11 | datasource db {
12 | provider = "postgresql"
13 | url = env("DATABASE_URL")
14 | }
15 |
16 | model User {
17 | id String @id @unique @default(cuid())
18 | username String @unique
19 | password String
20 | avatarId String?
21 | role Role
22 | spaces Space[]
23 | avatar Avatar? @relation(fields: [avatarId], references: [id])
24 | }
25 |
26 | model Space {
27 | id String @id @unique @default(cuid())
28 | name String
29 | width Int
30 | height Int
31 | thumbnail String?
32 | creatorId String
33 | creator User @relation(fields: [creatorId], references: [id])
34 | elements spaceElements[]
35 | }
36 |
37 | model spaceElements {
38 | id String @id @unique @default(cuid())
39 | elementId String
40 | spaceId String
41 | x Int
42 | y Int
43 | space Space @relation(fields: [spaceId], references: [id])
44 | element Element @relation(fields: [elementId], references: [id])
45 | }
46 |
47 | model Element {
48 | id String @id @unique @default(cuid())
49 | width Int
50 | height Int
51 | static Boolean
52 | imageUrl String
53 | spaces spaceElements[]
54 | mapElements MapElements[]
55 | }
56 |
57 | model Map {
58 | id String @id @unique @default(cuid())
59 | width Int
60 | height Int
61 | name String
62 | thumbnail String
63 | mapElements MapElements[]
64 | }
65 |
66 | model MapElements {
67 | id String @id @unique @default(cuid())
68 | mapId String
69 | elementId String
70 | x Int?
71 | y Int?
72 | map Map @relation(fields: [mapId], references: [id])
73 | element Element @relation(fields: [elementId], references: [id])
74 | }
75 |
76 | model Avatar {
77 | id String @id @unique @default(cuid())
78 | imageUrl String?
79 | name String?
80 | users User[]
81 | }
82 |
83 | enum Role {
84 | Admin
85 | User
86 | }
87 |
--------------------------------------------------------------------------------
/metaverse/packages/db/src/index.ts:
--------------------------------------------------------------------------------
1 | import { PrismaClient } from "@prisma/client"
2 |
3 | export default new PrismaClient();
--------------------------------------------------------------------------------
/metaverse/packages/db/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26 |
27 | /* Modules */
28 | "module": "commonjs", /* Specify what module code is generated. */
29 | "rootDir": "./src", /* Specify the root folder within your source files. */
30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42 | // "resolveJsonModule": true, /* Enable importing .json files. */
43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */
45 |
46 | /* JavaScript Support */
47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50 |
51 | /* Emit */
52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58 | "outDir": "./dist", /* Specify an output folder for all emitted files. */
59 | // "removeComments": true, /* Disable emitting comments. */
60 | // "noEmit": true, /* Disable emitting files from a compilation. */
61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
63 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
64 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
65 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
66 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
67 | // "newLine": "crlf", /* Set the newline character for emitting files. */
68 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
69 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
70 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
71 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
72 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
73 |
74 | /* Interop Constraints */
75 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
76 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
77 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
78 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
79 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
80 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
81 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
82 |
83 | /* Type Checking */
84 | "strict": true, /* Enable all strict type-checking options. */
85 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
86 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
87 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
88 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
89 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
90 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
91 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
92 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
93 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
94 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
95 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
96 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
97 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
98 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
99 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
100 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
101 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
102 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
103 |
104 | /* Completeness */
105 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
106 | "skipLibCheck": true, /* Skip type checking all .d.ts files. */
107 | "composite": true
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/metaverse/packages/db/tsconfig.tsbuildinfo:
--------------------------------------------------------------------------------
1 | {"fileNames":["../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.dom.iterable.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.scripthost.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.esnext.intl.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../node_modules/.pnpm/typescript@5.6.3/node_modules/typescript/lib/lib.es2016.full.d.ts","../../node_modules/.pnpm/@prisma+client@5.21.1_prisma@5.21.1/node_modules/@prisma/client/runtime/library.d.ts","../../node_modules/.pnpm/@prisma+client@5.21.1_prisma@5.21.1/node_modules/.prisma/client/index.d.ts","../../node_modules/.pnpm/@prisma+client@5.21.1_prisma@5.21.1/node_modules/.prisma/client/default.d.ts","../../node_modules/.pnpm/@prisma+client@5.21.1_prisma@5.21.1/node_modules/@prisma/client/default.d.ts","./src/index.ts","../../node_modules/.pnpm/@types+eslint@8.56.12/node_modules/@types/eslint/helpers.d.ts","../../node_modules/.pnpm/@types+estree@1.0.5/node_modules/@types/estree/index.d.ts","../../node_modules/.pnpm/@types+json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts","../../node_modules/.pnpm/@types+eslint@8.56.12/node_modules/@types/eslint/index.d.ts","../../../../node_modules/@types/node/assert.d.ts","../../../../node_modules/@types/node/assert/strict.d.ts","../../../../node_modules/@types/node/globals.d.ts","../../../../node_modules/@types/node/async_hooks.d.ts","../../../../node_modules/@types/node/buffer.d.ts","../../../../node_modules/@types/node/child_process.d.ts","../../../../node_modules/@types/node/cluster.d.ts","../../../../node_modules/@types/node/console.d.ts","../../../../node_modules/@types/node/constants.d.ts","../../../../node_modules/@types/node/crypto.d.ts","../../../../node_modules/@types/node/dgram.d.ts","../../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../../node_modules/@types/node/dns.d.ts","../../../../node_modules/@types/node/dns/promises.d.ts","../../../../node_modules/@types/node/domain.d.ts","../../../../node_modules/@types/node/dom-events.d.ts","../../../../node_modules/@types/node/events.d.ts","../../../../node_modules/@types/node/fs.d.ts","../../../../node_modules/@types/node/fs/promises.d.ts","../../../../node_modules/@types/node/http.d.ts","../../../../node_modules/@types/node/http2.d.ts","../../../../node_modules/@types/node/https.d.ts","../../../../node_modules/@types/node/inspector.d.ts","../../../../node_modules/@types/node/module.d.ts","../../../../node_modules/@types/node/net.d.ts","../../../../node_modules/@types/node/os.d.ts","../../../../node_modules/@types/node/path.d.ts","../../../../node_modules/@types/node/perf_hooks.d.ts","../../../../node_modules/@types/node/process.d.ts","../../../../node_modules/@types/node/punycode.d.ts","../../../../node_modules/@types/node/querystring.d.ts","../../../../node_modules/@types/node/readline.d.ts","../../../../node_modules/@types/node/readline/promises.d.ts","../../../../node_modules/@types/node/repl.d.ts","../../../../node_modules/@types/node/stream.d.ts","../../../../node_modules/@types/node/stream/promises.d.ts","../../../../node_modules/@types/node/stream/consumers.d.ts","../../../../node_modules/@types/node/stream/web.d.ts","../../../../node_modules/@types/node/string_decoder.d.ts","../../../../node_modules/@types/node/test.d.ts","../../../../node_modules/@types/node/timers.d.ts","../../../../node_modules/@types/node/timers/promises.d.ts","../../../../node_modules/@types/node/tls.d.ts","../../../../node_modules/@types/node/trace_events.d.ts","../../../../node_modules/@types/node/tty.d.ts","../../../../node_modules/@types/node/url.d.ts","../../../../node_modules/@types/node/util.d.ts","../../../../node_modules/@types/node/v8.d.ts","../../../../node_modules/@types/node/vm.d.ts","../../../../node_modules/@types/node/wasi.d.ts","../../../../node_modules/@types/node/worker_threads.d.ts","../../../../node_modules/@types/node/zlib.d.ts","../../../../node_modules/@types/node/globals.global.d.ts","../../../../node_modules/@types/node/index.d.ts","../../../../node_modules/@types/connect/index.d.ts","../../../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../../../node_modules/@types/istanbul-lib-report/index.d.ts","../../../../node_modules/@types/istanbul-reports/index.d.ts","../../../../node_modules/@types/node-forge/index.d.ts","../../../../node_modules/@types/stack-utils/index.d.ts","../../../../node_modules/@types/uuid/index.d.ts","../../../../node_modules/@types/ws/index.d.ts","../../../../node_modules/@types/yargs-parser/index.d.ts","../../../../node_modules/@types/yargs/index.d.ts"],"fileIdsList":[[52,106],[51,106],[53,106],[106],[56,57,58,106],[54,106],[79,106,113],[106,115],[106,116],[106,113],[60,106],[63,106],[64,69,97,106],[65,76,77,84,94,105,106],[65,66,76,84,106],[67,106],[68,69,77,85,106],[69,94,102,106],[70,72,76,84,106],[71,106],[72,73,106],[76,106],[74,76,106],[76,77,78,94,105,106],[76,77,78,91,94,97,106],[106,110],[72,79,84,94,105,106],[76,77,79,80,84,94,102,105,106],[79,81,94,102,105,106],[60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112],[76,82,106],[83,105,106],[72,76,84,94,106],[85,106],[86,106],[63,87,106],[88,104,106,110],[89,106],[90,106],[76,91,92,106],[91,93,106,108],[64,76,94,95,96,97,106],[64,94,96,106],[94,95,106],[97,106],[98,106],[76,100,101,106],[100,101,106],[69,84,94,102,106],[103,106],[84,104,106],[64,79,90,105,106],[69,106],[94,106,107],[106,108],[106,109],[64,69,76,78,87,94,105,106,108,110],[94,106,111],[76,79,81,84,94,102,105,106,111,113],[106,122]],"fileInfos":[{"version":"44e584d4f6444f58791784f1d530875970993129442a847597db702a073ca68c","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"9a68c0c07ae2fa71b44384a839b7b8d81662a236d4b9ac30916718f7510b1b2d","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"9e8ca8ed051c2697578c023d9c29d6df689a083561feba5c14aedee895853999","affectsGlobalScope":true,"impliedFormat":1},{"version":"69e65d976bf166ce4a9e6f6c18f94d2424bf116e90837ace179610dbccad9b42","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"6920e1448680767498a0b77c6a00a8e77d14d62c3da8967b171f1ddffa3c18e4","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"45d8ccb3dfd57355eb29749919142d4321a0aa4df6acdfc54e30433d7176600a","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"93495ff27b8746f55d19fcbcdbaccc99fd95f19d057aed1bd2c0cafe1335fbf0","affectsGlobalScope":true,"impliedFormat":1},{"version":"6fc23bb8c3965964be8c597310a2878b53a0306edb71d4b5a4dfe760186bcc01","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea011c76963fb15ef1cdd7ce6a6808b46322c527de2077b6cfdf23ae6f5f9ec7","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"4738f2420687fd85629c9efb470793bb753709c2379e5f85bc1815d875ceadcd","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"9fc46429fbe091ac5ad2608c657201eb68b6f1b8341bd6d670047d32ed0a88fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1a94697425a99354df73d9c8291e2ecd4dddd370aed4023c2d6dee6cccb32666","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"bf14a426dbbf1022d11bd08d6b8e709a2e9d246f0c6c1032f3b2edb9a902adbe","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3f9fc0ec0b96a9e642f11eda09c0be83a61c7b336977f8b9fdb1e9788e925fe","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"479553e3779be7d4f68e9f40cdb82d038e5ef7592010100410723ceced22a0f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"33358442698bb565130f52ba79bfd3d4d484ac85fe33f3cb1759c54d18201393","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"807e0e0bdc67605dd28efe18f20ab5fcd75d944ef95936120702335f9379094b","impliedFormat":1},{"version":"8bbaee3df87495f955400252869914d72159835151e73f9ac6b67fabc75393d8","impliedFormat":1},{"version":"91f45b546bb83a11e79c96b309c93c5a7b9ea63bc8e013eb539c4345d331e5ff","impliedFormat":1},{"version":"d5eb5865d4cbaa9985cc3cfb920b230cdcf3363f1e70903a08dc4baab80b0ce1","impliedFormat":1},{"version":"51ebca098538b252953b1ef83c165f25b52271bfb6049cd09d197dddd4cd43c5","impliedFormat":1},{"version":"cee1ce581f32de4155032a973db9fd1c05c7fe784eaa3eb8cd5f9d102c110a85","signature":"0ce8b2974c17ca4d1834116180a56bfe1f7e57acbb1fbab7d02c457b9bd48b41"},{"version":"64d4b35c5456adf258d2cf56c341e203a073253f229ef3208fc0d5020253b241","affectsGlobalScope":true,"impliedFormat":1},{"version":"ee7d8894904b465b072be0d2e4b45cf6b887cdba16a467645c4e200982ece7ea","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"dd0c1b380ba3437adedef134b2e48869449b1db0b07b2a229069309ce7b9dd39","impliedFormat":1},{"version":"7e771891adaa85b690266bc37bd6eb43bc57eecc4b54693ead36467e7369952a","impliedFormat":1},{"version":"a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a","impliedFormat":1},{"version":"8d81612302e009aacd595b125ae1530b6342f690eb83da7788503617d1362185","affectsGlobalScope":true,"impliedFormat":1},{"version":"11e2d554398d2bd460e7d06b2fa5827a297c8acfbe00b4f894a224ac0862857f","impliedFormat":1},{"version":"e193e634a99c9c1d71f1c6e4e1567a4a73584328d21ea02dd5cddbaad6693f61","affectsGlobalScope":true,"impliedFormat":1},{"version":"374ca798f244e464346f14301dc2a8b4b111af1a83b49fffef5906c338a1f922","impliedFormat":1},{"version":"5a94487653355b56018122d92392beb2e5f4a6c63ba5cef83bbe1c99775ef713","impliedFormat":1},{"version":"d5135ad93b33adcce80b18f8065087934cdc1730d63db58562edcf017e1aad9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","impliedFormat":1},{"version":"e596c9bb2f29a2699fdd4ae89139612652245192f67f45617c5a4b20832aaae9","impliedFormat":1},{"version":"bb9c4ffa5e6290c6980b63c815cdd1625876dadb2efaf77edbe82984be93e55e","impliedFormat":1},{"version":"1cdcfc1f624d6c08aa12c73935f6e13f095919cd99edf95752951796eb225729","impliedFormat":1},{"version":"216717f17c095cde1dc19375e1ab3af0a4a485355860c077a4f9d6ea59fab5b5","impliedFormat":1},{"version":"14b5aa23c5d0ae1907bc696ac7b6915d88f7d85799cc0dc2dcf98fbce2c5a67c","impliedFormat":1},{"version":"5c439dafdc09abe4d6c260a96b822fa0ba5be7203c71a63ab1f1423cd9e838ea","impliedFormat":1},{"version":"6b526a5ec4a401ca7c26cfe6a48e641d8f30af76673bad3b06a1b4504594a960","affectsGlobalScope":true,"impliedFormat":1},{"version":"816ad2e607a96de5bcac7d437f843f5afd8957f1fa5eefa6bba8e4ed7ca8fd84","affectsGlobalScope":true,"impliedFormat":1},{"version":"80473bd0dd90ca1e166514c2dfead9d5803f9c51418864ca35abbeec6e6847e1","impliedFormat":1},{"version":"1c84b46267610a34028edfd0d035509341751262bac1062857f3c8df7aff7153","impliedFormat":1},{"version":"e6c86d83bd526c8bdb5d0bf935b8e72ce983763d600743f74d812fdf4abf4df6","impliedFormat":1},{"version":"a3d541d303ee505053f5dcbf9fafb65cac3d5631037501cd616195863a6c5740","impliedFormat":1},{"version":"8d3c583a07e0c37e876908c2d5da575019f689df8d9fa4c081d99119d53dba22","impliedFormat":1},{"version":"2c828a5405191d006115ab34e191b8474bc6c86ffdc401d1a9864b1b6e088a58","impliedFormat":1},{"version":"e630e5528e899219ae319e83bef54bf3bcb91b01d76861ecf881e8e614b167f0","affectsGlobalScope":true,"impliedFormat":1},{"version":"bcebb922784739bdb34c18ee51095d25a92b560c78ccd2eaacd6bd00f7443d83","impliedFormat":1},{"version":"7ee6ed878c4528215c82b664fe0cfe80e8b4da6c0d4cc80869367868774db8b1","impliedFormat":1},{"version":"b0973c3cbcdc59b37bf477731d468696ecaf442593ec51bab497a613a580fe30","impliedFormat":1},{"version":"4989e92ba5b69b182d2caaea6295af52b7dc73a4f7a2e336a676722884e7139d","affectsGlobalScope":true,"impliedFormat":1},{"version":"0715e4cd28ad471b2a93f3e552ff51a3ae423417a01a10aa1d3bc7c6b95059d6","affectsGlobalScope":true,"impliedFormat":1},{"version":"5153a2fd150e46ce57bb3f8db1318d33f6ad3261ed70ceeff92281c0608c74a3","impliedFormat":1},{"version":"210d54cd652ec0fec8c8916e4af59bb341065576ecda039842f9ffb2e908507c","impliedFormat":1},{"version":"36b03690b628eab08703d63f04eaa89c5df202e5f1edf3989f13ad389cd2c091","impliedFormat":1},{"version":"0effadd232a20498b11308058e334d3339cc5bf8c4c858393e38d9d4c0013dcf","impliedFormat":1},{"version":"25846d43937c672bab7e8195f3d881f93495df712ee901860effc109918938cc","impliedFormat":1},{"version":"4f3fdeba4e28e21aa719c081b8dc8f91d47e12e773389b9d35679c08151c9d37","impliedFormat":1},{"version":"1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff","impliedFormat":1},{"version":"69ee23dd0d215b09907ad30d23f88b7790c93329d1faf31d7835552a10cf7cbf","impliedFormat":1},{"version":"44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","impliedFormat":1},{"version":"23b89798789dffbd437c0c423f5d02d11f9736aea73d6abf16db4f812ff36eda","impliedFormat":1},{"version":"f69ff39996a61a0dd10f4bce73272b52e8024a4d58b13ab32bf4712909d0a2b7","impliedFormat":1},{"version":"3c4ba1dd9b12ffa284b565063108f2f031d150ea15b8fafbdc17f5d2a07251f3","affectsGlobalScope":true,"impliedFormat":1},{"version":"e10177274a35a9d07c825615340b2fcde2f610f53f3fb40269fd196b4288dda6","impliedFormat":1},{"version":"c4577fb855ca259bdbf3ea663ca73988ce5f84251a92b4aef80a1f4122b6f98e","impliedFormat":1},{"version":"3c13ef48634e7b5012fcf7e8fce7496352c2d779a7201389ca96a2a81ee4314d","impliedFormat":1},{"version":"5d0a25ec910fa36595f85a67ac992d7a53dd4064a1ba6aea1c9f14ab73a023f2","impliedFormat":1},{"version":"f0900cd5d00fe1263ff41201fb8073dbeb984397e4af3b8002a5c207a30bdc33","affectsGlobalScope":true,"impliedFormat":1},{"version":"ff07a9a03c65732ccc59b3c65bc584173da093bd563a6565411c01f5703bd3cb","affectsGlobalScope":true,"impliedFormat":1},{"version":"6de4a219df57d2b27274d59b67708f13c2cbf7ed211abe57d8f9ab8b25cde776","impliedFormat":1},{"version":"0fe8985a28f82c450a04a6edf1279d7181c0893f37da7d2a27f8efd4fd5edb03","impliedFormat":1},{"version":"e59a892d87e72733e2a9ca21611b9beb52977be2696c7ba4b216cbbb9a48f5aa","impliedFormat":1},{"version":"da26af7362f53d122283bc69fed862b9a9fe27e01bc6a69d1d682e0e5a4df3e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"8a300fa9b698845a1f9c41ecbe2c5966634582a8e2020d51abcace9b55aa959e","impliedFormat":1},{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true,"impliedFormat":1},{"version":"d8d555f3d607ecaa18d55de6995ea8f206342ecc93305919eac945c7c78c78c6","impliedFormat":1},{"version":"104c67f0da1bdf0d94865419247e20eded83ce7f9911a1aa75fc675c077ca66e","impliedFormat":1},{"version":"035a5df183489c2e22f3cf59fc1ed2b043d27f357eecc0eb8d8e840059d44245","impliedFormat":1},{"version":"a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","impliedFormat":1},{"version":"5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","impliedFormat":1},{"version":"8b5402ae709d042c3530ed3506c135a967159f42aed3221267e70c5b7240b577","impliedFormat":1},{"version":"ab82804a14454734010dcdcd43f564ff7b0389bee4c5692eec76ff5b30d4cf66","impliedFormat":1},{"version":"fab58e600970e66547644a44bc9918e3223aa2cbd9e8763cec004b2cfb48827e","impliedFormat":1},{"version":"bc81aff061c53a7140270555f4b22da4ecfe8601e8027cf5aa175fbdc7927c31","impliedFormat":1},{"version":"bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","impliedFormat":1},{"version":"26a770cec4bd2e7dbba95c6e536390fffe83c6268b78974a93727903b515c4e7","impliedFormat":1}],"root":[55],"options":{"composite":true,"esModuleInterop":true,"module":1,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"strict":true,"target":3},"referencedMap":[[53,1],[52,2],[54,3],[51,4],[56,4],[59,5],[57,4],[58,4],[48,4],[49,4],[8,4],[9,4],[13,4],[12,4],[2,4],[14,4],[15,4],[16,4],[17,4],[18,4],[19,4],[20,4],[21,4],[3,4],[50,4],[22,4],[4,4],[23,4],[27,4],[24,4],[25,4],[26,4],[28,4],[29,4],[30,4],[5,4],[31,4],[32,4],[33,4],[34,4],[6,4],[38,4],[35,4],[36,4],[37,4],[39,4],[7,4],[40,4],[45,4],[46,4],[41,4],[42,4],[43,4],[44,4],[1,4],[47,4],[11,4],[10,4],[55,6],[114,7],[115,4],[116,8],[117,9],[118,10],[60,11],[61,11],[63,12],[64,13],[65,14],[66,15],[67,16],[68,17],[69,18],[70,19],[71,20],[72,21],[73,21],[75,22],[74,23],[76,22],[77,24],[78,25],[62,26],[112,4],[79,27],[80,28],[81,29],[113,30],[82,31],[83,32],[84,33],[85,34],[86,35],[87,36],[88,37],[89,38],[90,39],[91,40],[92,40],[93,41],[94,42],[96,43],[95,44],[97,45],[98,46],[99,4],[100,47],[101,48],[102,49],[103,50],[104,51],[105,52],[106,53],[107,54],[108,55],[109,56],[110,57],[111,58],[119,4],[120,4],[121,59],[122,4],[123,60]],"latestChangedDtsFile":"./dist/index.d.ts","version":"5.6.3"}
--------------------------------------------------------------------------------
/metaverse/packages/eslint-config/README.md:
--------------------------------------------------------------------------------
1 | # `@turbo/eslint-config`
2 |
3 | Collection of internal eslint configurations.
4 |
--------------------------------------------------------------------------------
/metaverse/packages/eslint-config/library.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require("node:path");
2 |
3 | const project = resolve(process.cwd(), "tsconfig.json");
4 |
5 | /** @type {import("eslint").Linter.Config} */
6 | module.exports = {
7 | extends: ["eslint:recommended", "prettier", "turbo"],
8 | plugins: ["only-warn"],
9 | globals: {
10 | React: true,
11 | JSX: true,
12 | },
13 | env: {
14 | node: true,
15 | },
16 | settings: {
17 | "import/resolver": {
18 | typescript: {
19 | project,
20 | },
21 | },
22 | },
23 | ignorePatterns: [
24 | // Ignore dotfiles
25 | ".*.js",
26 | "node_modules/",
27 | "dist/",
28 | ],
29 | overrides: [
30 | {
31 | files: ["*.js?(x)", "*.ts?(x)"],
32 | },
33 | ],
34 | };
35 |
--------------------------------------------------------------------------------
/metaverse/packages/eslint-config/next.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require("node:path");
2 |
3 | const project = resolve(process.cwd(), "tsconfig.json");
4 |
5 | /** @type {import("eslint").Linter.Config} */
6 | module.exports = {
7 | extends: [
8 | "eslint:recommended",
9 | "prettier",
10 | require.resolve("@vercel/style-guide/eslint/next"),
11 | "turbo",
12 | ],
13 | globals: {
14 | React: true,
15 | JSX: true,
16 | },
17 | env: {
18 | node: true,
19 | browser: true,
20 | },
21 | plugins: ["only-warn"],
22 | settings: {
23 | "import/resolver": {
24 | typescript: {
25 | project,
26 | },
27 | },
28 | },
29 | ignorePatterns: [
30 | // Ignore dotfiles
31 | ".*.js",
32 | "node_modules/",
33 | ],
34 | overrides: [{ files: ["*.js?(x)", "*.ts?(x)"] }],
35 | };
36 |
--------------------------------------------------------------------------------
/metaverse/packages/eslint-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@repo/eslint-config",
3 | "version": "0.0.0",
4 | "private": true,
5 | "files": [
6 | "library.js",
7 | "next.js",
8 | "react-internal.js"
9 | ],
10 | "devDependencies": {
11 | "@vercel/style-guide": "^5.2.0",
12 | "eslint-config-turbo": "^2.0.0",
13 | "eslint-config-prettier": "^9.1.0",
14 | "eslint-plugin-only-warn": "^1.1.0",
15 | "@typescript-eslint/parser": "^7.1.0",
16 | "@typescript-eslint/eslint-plugin": "^7.1.0",
17 | "typescript": "5.5.4"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/metaverse/packages/eslint-config/react-internal.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require("node:path");
2 |
3 | const project = resolve(process.cwd(), "tsconfig.json");
4 |
5 | /*
6 | * This is a custom ESLint configuration for use with
7 | * internal (bundled by their consumer) libraries
8 | * that utilize React.
9 | */
10 |
11 | /** @type {import("eslint").Linter.Config} */
12 | module.exports = {
13 | extends: ["eslint:recommended", "prettier", "turbo"],
14 | plugins: ["only-warn"],
15 | globals: {
16 | React: true,
17 | JSX: true,
18 | },
19 | env: {
20 | browser: true,
21 | },
22 | settings: {
23 | "import/resolver": {
24 | typescript: {
25 | project,
26 | },
27 | },
28 | },
29 | ignorePatterns: [
30 | // Ignore dotfiles
31 | ".*.js",
32 | "node_modules/",
33 | "dist/",
34 | ],
35 | overrides: [
36 | // Force ESLint to detect .tsx files
37 | { files: ["*.js?(x)", "*.ts?(x)"] },
38 | ],
39 | };
40 |
--------------------------------------------------------------------------------
/metaverse/packages/typescript-config/base.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "compilerOptions": {
4 | "declaration": true,
5 | "declarationMap": true,
6 | "esModuleInterop": true,
7 | "incremental": false,
8 | "isolatedModules": true,
9 | "lib": ["es2022", "DOM", "DOM.Iterable"],
10 | "module": "NodeNext",
11 | "moduleDetection": "force",
12 | "moduleResolution": "NodeNext",
13 | "noUncheckedIndexedAccess": true,
14 | "resolveJsonModule": true,
15 | "skipLibCheck": true,
16 | "strict": true,
17 | "target": "ES2022"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/metaverse/packages/typescript-config/nextjs.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "./base.json",
4 | "compilerOptions": {
5 | "plugins": [{ "name": "next" }],
6 | "module": "ESNext",
7 | "moduleResolution": "Bundler",
8 | "allowJs": true,
9 | "jsx": "preserve",
10 | "noEmit": true
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/metaverse/packages/typescript-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@repo/typescript-config",
3 | "version": "0.0.0",
4 | "private": true,
5 | "license": "MIT",
6 | "publishConfig": {
7 | "access": "public"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/metaverse/packages/typescript-config/react-library.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "./base.json",
4 | "compilerOptions": {
5 | "jsx": "react-jsx"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /** @type {import("eslint").Linter.Config} */
2 | module.exports = {
3 | root: true,
4 | extends: ["@repo/eslint-config/react-internal.js"],
5 | parser: "@typescript-eslint/parser",
6 | parserOptions: {
7 | project: "./tsconfig.lint.json",
8 | tsconfigRootDir: __dirname,
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@repo/ui",
3 | "version": "0.0.0",
4 | "private": true,
5 | "exports": {
6 | "./button": "./src/button.tsx",
7 | "./card": "./src/card.tsx",
8 | "./code": "./src/code.tsx"
9 | },
10 | "scripts": {
11 | "lint": "eslint . --max-warnings 0",
12 | "generate:component": "turbo gen react-component"
13 | },
14 | "devDependencies": {
15 | "@repo/eslint-config": "workspace:*",
16 | "@repo/typescript-config": "workspace:*",
17 | "@turbo/gen": "^1.12.4",
18 | "@types/node": "^20.11.24",
19 | "@types/eslint": "^8.56.5",
20 | "@types/react": "^18.2.61",
21 | "@types/react-dom": "^18.2.19",
22 | "eslint": "^8.57.0",
23 | "typescript": "5.5.4"
24 | },
25 | "dependencies": {
26 | "react": "^18.2.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/src/button.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { ReactNode } from "react";
4 |
5 | interface ButtonProps {
6 | children: ReactNode;
7 | className?: string;
8 | appName: string;
9 | }
10 |
11 | export const Button = ({ children, className, appName }: ButtonProps) => {
12 | return (
13 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/src/card.tsx:
--------------------------------------------------------------------------------
1 | export function Card({
2 | className,
3 | title,
4 | children,
5 | href,
6 | }: {
7 | className?: string;
8 | title: string;
9 | children: React.ReactNode;
10 | href: string;
11 | }): JSX.Element {
12 | return (
13 |
19 |
20 | {title} ->
21 |
22 | {children}
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/src/code.tsx:
--------------------------------------------------------------------------------
1 | export function Code({
2 | children,
3 | className,
4 | }: {
5 | children: React.ReactNode;
6 | className?: string;
7 | }): JSX.Element {
8 | return {children}
;
9 | }
10 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/react-library.json",
3 | "compilerOptions": {
4 | "outDir": "dist"
5 | },
6 | "include": ["src"],
7 | "exclude": ["node_modules", "dist"]
8 | }
9 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/tsconfig.lint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/react-library.json",
3 | "compilerOptions": {
4 | "outDir": "dist"
5 | },
6 | "include": ["src", "turbo"],
7 | "exclude": ["node_modules", "dist"]
8 | }
9 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/turbo/generators/config.ts:
--------------------------------------------------------------------------------
1 | import type { PlopTypes } from "@turbo/gen";
2 |
3 | // Learn more about Turborepo Generators at https://turbo.build/repo/docs/core-concepts/monorepos/code-generation
4 |
5 | export default function generator(plop: PlopTypes.NodePlopAPI): void {
6 | // A simple generator to add a new React component to the internal UI library
7 | plop.setGenerator("react-component", {
8 | description: "Adds a new react component",
9 | prompts: [
10 | {
11 | type: "input",
12 | name: "name",
13 | message: "What is the name of the component?",
14 | },
15 | ],
16 | actions: [
17 | {
18 | type: "add",
19 | path: "src/{{kebabCase name}}.tsx",
20 | templateFile: "templates/component.hbs",
21 | },
22 | {
23 | type: "append",
24 | path: "package.json",
25 | pattern: /"exports": {(?)/g,
26 | template: ' "./{{kebabCase name}}": "./src/{{kebabCase name}}.tsx",',
27 | },
28 | ],
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/metaverse/packages/ui/turbo/generators/templates/component.hbs:
--------------------------------------------------------------------------------
1 | export const {{ pascalCase name }} = ({ children }: { children: React.ReactNode }) => {
2 | return (
3 |
4 |
{{ pascalCase name }} Component
5 | {children}
6 |
7 | );
8 | };
9 |
--------------------------------------------------------------------------------
/metaverse/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - "apps/*"
3 | - "packages/*"
4 |
--------------------------------------------------------------------------------
/metaverse/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turbo.build/schema.json",
3 | "ui": "tui",
4 | "tasks": {
5 | "build": {
6 | "dependsOn": ["^build"],
7 | "inputs": ["$TURBO_DEFAULT$", ".env*"],
8 | "outputs": [".next/**", "!.next/cache/**"]
9 | },
10 | "lint": {
11 | "dependsOn": ["^lint"]
12 | },
13 | "dev": {
14 | "cache": false,
15 | "persistent": true
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/tests/index.test.js:
--------------------------------------------------------------------------------
1 | const axios2 = require("axios");
2 |
3 | const BACKEND_URL = "http://localhost:3000"
4 | const WS_URL = "ws://localhost:3001"
5 |
6 | const axios = {
7 | post: async (...args) => {
8 | try {
9 | const res = await axios2.post(...args)
10 | return res
11 | } catch(e) {
12 | return e.response
13 | }
14 | },
15 | get: async (...args) => {
16 | try {
17 | const res = await axios2.get(...args)
18 | return res
19 | } catch(e) {
20 | return e.response
21 | }
22 | },
23 | put: async (...args) => {
24 | try {
25 | const res = await axios2.put(...args)
26 | return res
27 | } catch(e) {
28 | return e.response
29 | }
30 | },
31 | delete: async (...args) => {
32 | try {
33 | const res = await axios2.delete(...args)
34 | return res
35 | } catch(e) {
36 | return e.response
37 | }
38 | },
39 | }
40 |
41 | describe("Authentication", () => {
42 | test('User is able to sign up only once', async () => {
43 | const username = "kirat" + Math.random(); // kirat0.12331313
44 | const password = "123456";
45 | const response = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
46 | username,
47 | password,
48 | type: "admin"
49 | })
50 |
51 | expect(response.status).toBe(200)
52 | const updatedResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
53 | username,
54 | password,
55 | type: "admin"
56 | })
57 |
58 | expect(updatedResponse.status).toBe(400);
59 | });
60 |
61 | test('Signup request fails if the username is empty', async () => {
62 | const username = `kirat-${Math.random()}` // kirat-0.12312313
63 | const password = "123456"
64 |
65 | const response = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
66 | password
67 | })
68 |
69 | expect(response.status).toBe(400)
70 | })
71 |
72 | test('Signin succeeds if the username and password are correct', async() => {
73 | const username = `kirat-${Math.random()}`
74 | const password = "123456"
75 |
76 | await axios.post(`${BACKEND_URL}/api/v1/signup`, {
77 | username,
78 | password,
79 | type: "admin"
80 | });
81 |
82 | const response = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
83 | username,
84 | password
85 | });
86 |
87 | expect(response.status).toBe(200)
88 | expect(response.data.token).toBeDefined()
89 |
90 | })
91 |
92 | test('Signin fails if the username and password are incorrect', async() => {
93 | const username = `kirat-${Math.random()}`
94 | const password = "123456"
95 |
96 | await axios.post(`${BACKEND_URL}/api/v1/signup`, {
97 | username,
98 | password,
99 | role: "admin"
100 | });
101 |
102 | const response = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
103 | username: "WrongUsername",
104 | password
105 | })
106 |
107 | expect(response.status).toBe(403)
108 | })
109 | })
110 |
111 | describe("User metadata endpoint", () => {
112 | let token = "";
113 | let avatarId = ""
114 |
115 | beforeAll(async () => {
116 | const username = `kirat-${Math.random()}`
117 | const password = "123456"
118 |
119 | await axios.post(`${BACKEND_URL}/api/v1/signup`, {
120 | username,
121 | password,
122 | type: "admin"
123 | });
124 |
125 | const response = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
126 | username,
127 | password
128 | })
129 |
130 | token = response.data.token
131 |
132 | const avatarResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/avatar`, {
133 | "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQm3RFDZM21teuCMFYx_AROjt-AzUwDBROFww&s",
134 | "name": "Timmy"
135 | }, {
136 | headers: {
137 | authorization: `Bearer ${token}`
138 | }
139 | })
140 | console.log("avatarresponse is " + avatarResponse.data.avatarId)
141 |
142 | avatarId = avatarResponse.data.avatarId;
143 |
144 | })
145 |
146 | test("User cant update their metadata with a wrong avatar id", async () => {
147 | const response = await axios.post(`${BACKEND_URL}/api/v1/user/metadata`, {
148 | avatarId: "123123123"
149 | }, {
150 | headers: {
151 | "authorization": `Bearer ${token}`
152 | }
153 | })
154 |
155 | expect(response.status).toBe(400)
156 | })
157 |
158 | test("User can update their metadata with the right avatar id", async () => {
159 | const response = await axios.post(`${BACKEND_URL}/api/v1/user/metadata`, {
160 | avatarId
161 | }, {
162 | headers: {
163 | "authorization": `Bearer ${token}`
164 | }
165 | })
166 |
167 | expect(response.status).toBe(200)
168 | })
169 |
170 | test("User is not able to update their metadata if the auth header is not present", async () => {
171 | const response = await axios.post(`${BACKEND_URL}/api/v1/user/metadata`, {
172 | avatarId
173 | })
174 |
175 | expect(response.status).toBe(403)
176 | })
177 |
178 | test("test 3", () => {
179 |
180 | })
181 | });
182 |
183 | describe("User avatar information", () => {
184 | let avatarId;
185 | let token;
186 | let userId;
187 |
188 | beforeAll(async () => {
189 | const username = `kirat-${Math.random()}`
190 | const password = "123456"
191 |
192 | const signupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
193 | username,
194 | password,
195 | type: "admin"
196 | });
197 |
198 | userId = signupResponse.data.userId
199 |
200 | console.log("userid is " + userId)
201 | const response = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
202 | username,
203 | password
204 | })
205 |
206 | token = response.data.token
207 |
208 | const avatarResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/avatar`, {
209 | "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQm3RFDZM21teuCMFYx_AROjt-AzUwDBROFww&s",
210 | "name": "Timmy"
211 | }, {
212 | headers: {
213 | authorization: `Bearer ${token}`
214 | }
215 | })
216 |
217 | avatarId = avatarResponse.data.avatarId;
218 |
219 | })
220 |
221 | test("Get back avatar information for a user", async () => {
222 | console.log("asking for user with id " + userId)
223 | const response = await axios.get(`${BACKEND_URL}/api/v1/user/metadata/bulk?ids=[${userId}]`);
224 | console.log("response was " + userId)
225 | console.log(JSON.stringify(response.data))
226 | expect(response.data.avatars.length).toBe(1);
227 | expect(response.data.avatars[0].userId).toBe(userId);
228 | })
229 |
230 | test("Available avatars lists the recently created avatar", async () => {
231 | const response = await axios.get(`${BACKEND_URL}/api/v1/avatars`);
232 | expect(response.data.avatars.length).not.toBe(0);
233 | const currentAvatar = response.data.avatars.find(x => x.id == avatarId);
234 | expect(currentAvatar).toBeDefined()
235 | })
236 |
237 | })
238 |
239 | describe("Space information", () => {
240 | let mapId;
241 | let element1Id;
242 | let element2Id;
243 | let adminToken;
244 | let adminId;
245 | let userToken;
246 | let userId;
247 |
248 | beforeAll(async () => {
249 | const username = `kirat-${Math.random()}`
250 | const password = "123456"
251 |
252 | const signupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
253 | username,
254 | password,
255 | type: "admin"
256 | });
257 |
258 | adminId = signupResponse.data.userId
259 |
260 | const response = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
261 | username,
262 | password
263 | })
264 |
265 | adminToken = response.data.token
266 |
267 | const userSignupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
268 | username: username + "-user",
269 | password,
270 | type: "user"
271 | });
272 |
273 | userId = userSignupResponse.data.userId
274 |
275 | const userSigninResponse = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
276 | username: username + "-user",
277 | password
278 | })
279 |
280 | userToken = userSigninResponse.data.token
281 |
282 | const element1Response = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
283 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
284 | "width": 1,
285 | "height": 1,
286 | "static": true
287 | }, {
288 | headers: {
289 | authorization: `Bearer ${adminToken}`
290 | }
291 | });
292 |
293 | const element2Response = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
294 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
295 | "width": 1,
296 | "height": 1,
297 | "static": true
298 | }, {
299 | headers: {
300 | authorization: `Bearer ${adminToken}`
301 | }
302 | })
303 | element1Id = element1Response.data.id
304 | element2Id = element2Response.data.id
305 | console.log(element2Id)
306 | console.log(element1Id)
307 | const mapResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/map`, {
308 | "thumbnail": "https://thumbnail.com/a.png",
309 | "dimensions": "100x200",
310 | "name": "Test space",
311 | "defaultElements": [{
312 | elementId: element1Id,
313 | x: 20,
314 | y: 20
315 | }, {
316 | elementId: element1Id,
317 | x: 18,
318 | y: 20
319 | }, {
320 | elementId: element2Id,
321 | x: 19,
322 | y: 20
323 | }
324 | ]
325 | }, {
326 | headers: {
327 | authorization: `Bearer ${adminToken}`
328 | }
329 | })
330 | console.log("mapResponse.status")
331 | console.log(mapResponse.data.id)
332 |
333 | mapId = mapResponse.data.id
334 |
335 | });
336 |
337 | test("User is able to create a space", async () => {
338 |
339 | const response = await axios.post(`${BACKEND_URL}/api/v1/space`, {
340 | "name": "Test",
341 | "dimensions": "100x200",
342 | "mapId": mapId
343 | }, {
344 | headers: {
345 | authorization: `Bearer ${userToken}`
346 | }
347 | })
348 | expect(response.status).toBe(200)
349 | expect(response.data.spaceId).toBeDefined()
350 | })
351 |
352 | test("User is able to create a space without mapId (empty space)", async () => {
353 | const response = await axios.post(`${BACKEND_URL}/api/v1/space`, {
354 | "name": "Test",
355 | "dimensions": "100x200",
356 | }, {
357 | headers: {
358 | authorization: `Bearer ${userToken}`
359 | }
360 | })
361 |
362 | expect(response.data.spaceId).toBeDefined()
363 | })
364 |
365 | test("User is not able to create a space without mapId and dimensions", async () => {
366 | const response = await axios.post(`${BACKEND_URL}/api/v1/space`, {
367 | "name": "Test",
368 | }, {
369 | headers: {
370 | authorization: `Bearer ${userToken}`
371 | }
372 | })
373 |
374 | expect(response.status).toBe(400)
375 | })
376 |
377 | test("User is not able to delete a space that doesnt exist", async () => {
378 | const response = await axios.delete(`${BACKEND_URL}/api/v1/space/randomIdDoesntExist`, {
379 | headers: {
380 | authorization: `Bearer ${userToken}`
381 | }
382 | })
383 |
384 | expect(response.status).toBe(400)
385 | })
386 |
387 | test("User is able to delete a space that does exist", async () => {
388 | const response = await axios.post(`${BACKEND_URL}/api/v1/space`, {
389 | "name": "Test",
390 | "dimensions": "100x200",
391 | }, {
392 | headers: {
393 | authorization: `Bearer ${userToken}`
394 | }
395 | })
396 |
397 | const deleteReponse = await axios.delete(`${BACKEND_URL}/api/v1/space/${response.data.spaceId}`, {
398 | headers: {
399 | authorization: `Bearer ${userToken}`
400 | }
401 | })
402 |
403 | expect(deleteReponse.status).toBe(200)
404 | })
405 |
406 | test("User should not be able to delete a space created by another user", async () => {
407 | const response = await axios.post(`${BACKEND_URL}/api/v1/space`, {
408 | "name": "Test",
409 | "dimensions": "100x200",
410 | }, {
411 | headers: {
412 | authorization: `Bearer ${userToken}`
413 | }
414 | })
415 |
416 | const deleteReponse = await axios.delete(`${BACKEND_URL}/api/v1/space/${response.data.spaceId}`, {
417 | headers: {
418 | authorization: `Bearer ${adminToken}`
419 | }
420 | })
421 |
422 | expect(deleteReponse.status).toBe(403)
423 | })
424 |
425 | test("Admin has no spaces initially", async () => {
426 | const response = await axios.get(`${BACKEND_URL}/api/v1/space/all`, {
427 | headers: {
428 | authorization: `Bearer ${adminToken}`
429 | }
430 | });
431 | expect(response.data.spaces.length).toBe(0)
432 | })
433 |
434 | test("Admin has gets once space after", async () => {
435 | const spaceCreateReponse = await axios.post(`${BACKEND_URL}/api/v1/space`, {
436 | "name": "Test",
437 | "dimensions": "100x200",
438 | }, {
439 | headers: {
440 | authorization: `Bearer ${adminToken}`
441 | }
442 | });
443 | console.log('jhflksdjflksdfjlksdfj')
444 | console.log(spaceCreateReponse.data)
445 | const response = await axios.get(`${BACKEND_URL}/api/v1/space/all`, {
446 | headers: {
447 | authorization: `Bearer ${adminToken}`
448 | }
449 | });
450 | const filteredSpace = response.data.spaces.find(x => x.id == spaceCreateReponse.data.spaceId)
451 | expect(response.data.spaces.length).toBe(1)
452 | expect(filteredSpace).toBeDefined()
453 |
454 | })
455 | })
456 |
457 | describe("Arena endpoints", () => {
458 | let mapId;
459 | let element1Id;
460 | let element2Id;
461 | let adminToken;
462 | let adminId;
463 | let userToken;
464 | let userId;
465 | let spaceId;
466 |
467 | beforeAll(async () => {
468 | const username = `kirat-${Math.random()}`
469 | const password = "123456"
470 |
471 | const signupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
472 | username,
473 | password,
474 | type: "admin"
475 | });
476 |
477 | adminId = signupResponse.data.userId
478 |
479 | const response = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
480 | username: username,
481 | password
482 | })
483 |
484 | adminToken = response.data.token
485 |
486 | const userSignupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
487 | username: username + "-user",
488 | password,
489 | type: "user"
490 | });
491 |
492 | userId = userSignupResponse.data.userId
493 |
494 | const userSigninResponse = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
495 | username: username + "-user",
496 | password
497 | })
498 |
499 | userToken = userSigninResponse.data.token
500 |
501 | const element1Response = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
502 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
503 | "width": 1,
504 | "height": 1,
505 | "static": true
506 | }, {
507 | headers: {
508 | authorization: `Bearer ${adminToken}`
509 | }
510 | });
511 |
512 | const element2Response = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
513 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
514 | "width": 1,
515 | "height": 1,
516 | "static": true
517 | }, {
518 | headers: {
519 | authorization: `Bearer ${adminToken}`
520 | }
521 | })
522 | element1Id = element1Response.data.id
523 | element2Id = element2Response.data.id
524 |
525 | const mapResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/map`, {
526 | "thumbnail": "https://thumbnail.com/a.png",
527 | "dimensions": "100x200",
528 | name: "Default space",
529 | "defaultElements": [{
530 | elementId: element1Id,
531 | x: 20,
532 | y: 20
533 | }, {
534 | elementId: element1Id,
535 | x: 18,
536 | y: 20
537 | }, {
538 | elementId: element2Id,
539 | x: 19,
540 | y: 20
541 | }
542 | ]
543 | }, {
544 | headers: {
545 | authorization: `Bearer ${adminToken}`
546 | }
547 | })
548 | mapId = mapResponse.data.id
549 |
550 | const spaceResponse = await axios.post(`${BACKEND_URL}/api/v1/space`, {
551 | "name": "Test",
552 | "dimensions": "100x200",
553 | "mapId": mapId
554 | }, {headers: {
555 | "authorization": `Bearer ${userToken}`
556 | }})
557 | console.log(spaceResponse.data)
558 | spaceId = spaceResponse.data.spaceId
559 | });
560 |
561 | test("Incorrect spaceId returns a 400", async () => {
562 | const response = await axios.get(`${BACKEND_URL}/api/v1/space/123kasdk01`, {
563 | headers: {
564 | "authorization": `Bearer ${userToken}`
565 | }
566 | });
567 | expect(response.status).toBe(400)
568 | })
569 |
570 | test("Correct spaceId returns all the elements", async () => {
571 | const response = await axios.get(`${BACKEND_URL}/api/v1/space/${spaceId}`, {
572 | headers: {
573 | "authorization": `Bearer ${userToken}`
574 | }
575 | });
576 | console.log(response.data)
577 | expect(response.data.dimensions).toBe("100x200")
578 | expect(response.data.elements.length).toBe(3)
579 | })
580 |
581 | test("Delete endpoint is able to delete an element", async () => {
582 | const response = await axios.get(`${BACKEND_URL}/api/v1/space/${spaceId}`, {
583 | headers: {
584 | "authorization": `Bearer ${userToken}`
585 | }
586 | });
587 |
588 | console.log(response.data.elements[0].id )
589 | let res = await axios.delete(`${BACKEND_URL}/api/v1/space/element`, {
590 | data: {id: response.data.elements[0].id},
591 | headers: {
592 | "authorization": `Bearer ${userToken}`
593 | }
594 | });
595 |
596 |
597 | const newResponse = await axios.get(`${BACKEND_URL}/api/v1/space/${spaceId}`, {
598 | headers: {
599 | "authorization": `Bearer ${userToken}`
600 | }
601 | });
602 |
603 | expect(newResponse.data.elements.length).toBe(2)
604 | })
605 |
606 | test("Adding an element fails if the element lies outside the dimensions", async () => {
607 | const newResponse = await axios.post(`${BACKEND_URL}/api/v1/space/element`, {
608 | "elementId": element1Id,
609 | "spaceId": spaceId,
610 | "x": 10000,
611 | "y": 210000
612 | }, {
613 | headers: {
614 | "authorization": `Bearer ${userToken}`
615 | }
616 | });
617 |
618 | expect(newResponse.status).toBe(400)
619 | })
620 |
621 | test("Adding an element works as expected", async () => {
622 | await axios.post(`${BACKEND_URL}/api/v1/space/element`, {
623 | "elementId": element1Id,
624 | "spaceId": spaceId,
625 | "x": 50,
626 | "y": 20
627 | }, {
628 | headers: {
629 | "authorization": `Bearer ${userToken}`
630 | }
631 | });
632 |
633 | const newResponse = await axios.get(`${BACKEND_URL}/api/v1/space/${spaceId}`, {
634 | headers: {
635 | "authorization": `Bearer ${userToken}`
636 | }
637 | });
638 |
639 | expect(newResponse.data.elements.length).toBe(3)
640 | })
641 |
642 | })
643 |
644 | describe("Admin Endpoints", () => {
645 | let adminToken;
646 | let adminId;
647 | let userToken;
648 | let userId;
649 |
650 | beforeAll(async () => {
651 | const username = `kirat-${Math.random()}`
652 | const password = "123456"
653 |
654 | const signupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
655 | username,
656 | password,
657 | type: "admin"
658 | });
659 |
660 | adminId = signupResponse.data.userId
661 |
662 | const response = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
663 | username: username,
664 | password
665 | })
666 |
667 | adminToken = response.data.token
668 |
669 | const userSignupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
670 | username: username + "-user",
671 | password,
672 | type: "user"
673 | });
674 |
675 | userId = userSignupResponse.data.userId
676 |
677 | const userSigninResponse = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
678 | username: username + "-user",
679 | password
680 | })
681 |
682 | userToken = userSigninResponse.data.token
683 | });
684 |
685 | test("User is not able to hit admin Endpoints", async () => {
686 | const elementReponse = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
687 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
688 | "width": 1,
689 | "height": 1,
690 | "static": true
691 | }, {
692 | headers: {
693 | authorization: `Bearer ${userToken}`
694 | }
695 | });
696 |
697 | const mapResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/map`, {
698 | "thumbnail": "https://thumbnail.com/a.png",
699 | "dimensions": "100x200",
700 | "name": "test space",
701 | "defaultElements": []
702 | }, {
703 | headers: {
704 | authorization: `Bearer ${userToken}`
705 | }
706 | })
707 |
708 | const avatarResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/avatar`, {
709 | "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQm3RFDZM21teuCMFYx_AROjt-AzUwDBROFww&s",
710 | "name": "Timmy"
711 | }, {
712 | headers: {
713 | "authorization": `Bearer ${userToken}`
714 | }
715 | })
716 |
717 | const updateElementResponse = await axios.put(`${BACKEND_URL}/api/v1/admin/element/123`, {
718 | "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQm3RFDZM21teuCMFYx_AROjt-AzUwDBROFww&s",
719 | }, {
720 | headers: {
721 | "authorization": `Bearer ${userToken}`
722 | }
723 | })
724 |
725 | expect(elementReponse.status).toBe(403)
726 | expect(mapResponse.status).toBe(403)
727 | expect(avatarResponse.status).toBe(403)
728 | expect(updateElementResponse.status).toBe(403)
729 | })
730 |
731 | test("Admin is able to hit admin Endpoints", async () => {
732 | const elementReponse = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
733 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
734 | "width": 1,
735 | "height": 1,
736 | "static": true
737 | }, {
738 | headers: {
739 | authorization: `Bearer ${adminToken}`
740 | }
741 | });
742 |
743 | const mapResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/map`, {
744 | "thumbnail": "https://thumbnail.com/a.png",
745 | "name": "Space",
746 | "dimensions": "100x200",
747 | "defaultElements": []
748 | }, {
749 | headers: {
750 | authorization: `Bearer ${adminToken}`
751 | }
752 | })
753 |
754 | const avatarResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/avatar`, {
755 | "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQm3RFDZM21teuCMFYx_AROjt-AzUwDBROFww&s",
756 | "name": "Timmy"
757 | }, {
758 | headers: {
759 | "authorization": `Bearer ${adminToken}`
760 | }
761 | })
762 | expect(elementReponse.status).toBe(200)
763 | expect(mapResponse.status).toBe(200)
764 | expect(avatarResponse.status).toBe(200)
765 | })
766 |
767 | test("Admin is able to update the imageUrl for an element", async () => {
768 | const elementResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
769 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
770 | "width": 1,
771 | "height": 1,
772 | "static": true
773 | }, {
774 | headers: {
775 | authorization: `Bearer ${adminToken}`
776 | }
777 | });
778 |
779 | const updateElementResponse = await axios.put(`${BACKEND_URL}/api/v1/admin/element/${elementResponse.data.id}`, {
780 | "imageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQm3RFDZM21teuCMFYx_AROjt-AzUwDBROFww&s",
781 | }, {
782 | headers: {
783 | "authorization": `Bearer ${adminToken}`
784 | }
785 | })
786 |
787 | expect(updateElementResponse.status).toBe(200);
788 |
789 | })
790 | });
791 |
792 | describe("Websocket tests", () => {
793 | let adminToken;
794 | let adminUserId;
795 | let userToken;
796 | let adminId;
797 | let userId;
798 | let mapId;
799 | let element1Id;
800 | let element2Id;
801 | let spaceId;
802 | let ws1;
803 | let ws2;
804 | let ws1Messages = []
805 | let ws2Messages = []
806 | let userX;
807 | let userY;
808 | let adminX;
809 | let adminY;
810 |
811 | function waitForAndPopLatestMessage(messageArray) {
812 | return new Promise(resolve => {
813 | if (messageArray.length > 0) {
814 | resolve(messageArray.shift())
815 | } else {
816 | let interval = setInterval(() => {
817 | if (messageArray.length > 0) {
818 | resolve(messageArray.shift())
819 | clearInterval(interval)
820 | }
821 | }, 100)
822 | }
823 | })
824 | }
825 |
826 | async function setupHTTP() {
827 | const username = `kirat-${Math.random()}`
828 | const password = "123456"
829 | const adminSignupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
830 | username,
831 | password,
832 | type: "admin"
833 | })
834 |
835 | const adminSigninResponse = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
836 | username,
837 | password
838 | })
839 |
840 | adminUserId = adminSignupResponse.data.userId;
841 | adminToken = adminSigninResponse.data.token;
842 | console.log("adminSignupResponse.status")
843 | console.log(adminSignupResponse.status)
844 |
845 | const userSignupResponse = await axios.post(`${BACKEND_URL}/api/v1/signup`, {
846 | username: username + `-user`,
847 | password,
848 | type: "user"
849 | })
850 | const userSigninResponse = await axios.post(`${BACKEND_URL}/api/v1/signin`, {
851 | username: username + `-user`,
852 | password
853 | })
854 | userId = userSignupResponse.data.userId
855 | userToken = userSigninResponse.data.token
856 | console.log("useroktne", userToken)
857 | const element1Response = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
858 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
859 | "width": 1,
860 | "height": 1,
861 | "static": true
862 | }, {
863 | headers: {
864 | authorization: `Bearer ${adminToken}`
865 | }
866 | });
867 |
868 | const element2Response = await axios.post(`${BACKEND_URL}/api/v1/admin/element`, {
869 | "imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcRCRca3wAR4zjPPTzeIY9rSwbbqB6bB2hVkoTXN4eerXOIkJTG1GpZ9ZqSGYafQPToWy_JTcmV5RHXsAsWQC3tKnMlH_CsibsSZ5oJtbakq&usqp=CAE",
870 | "width": 1,
871 | "height": 1,
872 | "static": true
873 | }, {
874 | headers: {
875 | authorization: `Bearer ${adminToken}`
876 | }
877 | })
878 | element1Id = element1Response.data.id
879 | element2Id = element2Response.data.id
880 |
881 | const mapResponse = await axios.post(`${BACKEND_URL}/api/v1/admin/map`, {
882 | "thumbnail": "https://thumbnail.com/a.png",
883 | "dimensions": "100x200",
884 | "name": "Defaul space",
885 | "defaultElements": [{
886 | elementId: element1Id,
887 | x: 20,
888 | y: 20
889 | }, {
890 | elementId: element1Id,
891 | x: 18,
892 | y: 20
893 | }, {
894 | elementId: element2Id,
895 | x: 19,
896 | y: 20
897 | }
898 | ]
899 | }, {
900 | headers: {
901 | authorization: `Bearer ${adminToken}`
902 | }
903 | })
904 | mapId = mapResponse.data.id
905 |
906 | const spaceResponse = await axios.post(`${BACKEND_URL}/api/v1/space`, {
907 | "name": "Test",
908 | "dimensions": "100x200",
909 | "mapId": mapId
910 | }, {headers: {
911 | "authorization": `Bearer ${userToken}`
912 | }})
913 |
914 | console.log(spaceResponse.status)
915 | spaceId = spaceResponse.data.spaceId
916 | }
917 | async function setupWs() {
918 | ws1 = new WebSocket(WS_URL)
919 |
920 | ws1.onmessage = (event) => {
921 | console.log("got back adata 1")
922 | console.log(event.data)
923 |
924 | ws1Messages.push(JSON.parse(event.data))
925 | }
926 | await new Promise(r => {
927 | ws1.onopen = r
928 | })
929 |
930 | ws2 = new WebSocket(WS_URL)
931 |
932 | ws2.onmessage = (event) => {
933 | console.log("got back data 2")
934 | console.log(event.data)
935 | ws2Messages.push(JSON.parse(event.data))
936 | }
937 | await new Promise(r => {
938 | ws2.onopen = r
939 | })
940 | }
941 |
942 | beforeAll(async () => {
943 | await setupHTTP()
944 | await setupWs()
945 | })
946 |
947 | test("Get back ack for joining the space", async () => {
948 | console.log("insixce first test")
949 | ws1.send(JSON.stringify({
950 | "type": "join",
951 | "payload": {
952 | "spaceId": spaceId,
953 | "token": adminToken
954 | }
955 | }))
956 | console.log("insixce first test1")
957 | const message1 = await waitForAndPopLatestMessage(ws1Messages);
958 | console.log("insixce first test2")
959 | ws2.send(JSON.stringify({
960 | "type": "join",
961 | "payload": {
962 | "spaceId": spaceId,
963 | "token": userToken
964 | }
965 | }))
966 | console.log("insixce first test3")
967 |
968 | const message2 = await waitForAndPopLatestMessage(ws2Messages);
969 | const message3 = await waitForAndPopLatestMessage(ws1Messages);
970 |
971 | expect(message1.type).toBe("space-joined")
972 | expect(message2.type).toBe("space-joined")
973 | expect(message1.payload.users.length).toBe(0)
974 | expect(message2.payload.users.length).toBe(1)
975 | expect(message3.type).toBe("user-joined");
976 | expect(message3.payload.x).toBe(message2.payload.spawn.x);
977 | expect(message3.payload.y).toBe(message2.payload.spawn.y);
978 | expect(message3.payload.userId).toBe(userId);
979 |
980 | adminX = message1.payload.spawn.x
981 | adminY = message1.payload.spawn.y
982 |
983 | userX = message2.payload.spawn.x
984 | userY = message2.payload.spawn.y
985 | })
986 |
987 | test("User should not be able to move across the boundary of the wall", async () => {
988 | ws1.send(JSON.stringify({
989 | type: "move",
990 | payload: {
991 | x: 1000000,
992 | y: 10000
993 | }
994 | }));
995 |
996 | const message = await waitForAndPopLatestMessage(ws1Messages);
997 | expect(message.type).toBe("movement-rejected")
998 | expect(message.payload.x).toBe(adminX)
999 | expect(message.payload.y).toBe(adminY)
1000 | })
1001 |
1002 | test("User should not be able to move two blocks at the same time", async () => {
1003 | ws1.send(JSON.stringify({
1004 | type: "move",
1005 | payload: {
1006 | x: adminX + 2,
1007 | y: adminY
1008 | }
1009 | }));
1010 |
1011 | const message = await waitForAndPopLatestMessage(ws1Messages);
1012 | expect(message.type).toBe("movement-rejected")
1013 | expect(message.payload.x).toBe(adminX)
1014 | expect(message.payload.y).toBe(adminY)
1015 | })
1016 |
1017 | test("Correct movement should be broadcasted to the other sockets in the room",async () => {
1018 | ws1.send(JSON.stringify({
1019 | type: "move",
1020 | payload: {
1021 | x: adminX + 1,
1022 | y: adminY,
1023 | userId: adminId
1024 | }
1025 | }));
1026 |
1027 | const message = await waitForAndPopLatestMessage(ws2Messages);
1028 | expect(message.type).toBe("movement")
1029 | expect(message.payload.x).toBe(adminX + 1)
1030 | expect(message.payload.y).toBe(adminY)
1031 | })
1032 |
1033 | test("If a user leaves, the other user receives a leave event", async () => {
1034 | ws1.close()
1035 | const message = await waitForAndPopLatestMessage(ws2Messages);
1036 | expect(message.type).toBe("user-left")
1037 | expect(message.payload.userId).toBe(adminUserId)
1038 | })
1039 | })
--------------------------------------------------------------------------------
/tests/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tests",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "scripts": {
6 | "test": "jest"
7 | },
8 | "keywords": [],
9 | "author": "",
10 | "license": "ISC",
11 | "description": "",
12 | "devDependencies": {
13 | "jest": "^29.7.0"
14 | },
15 | "dependencies": {
16 | "axios": "^1.7.7"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------