initial commit
This commit is contained in:
		
						commit
						e6a8e4795a
					
				
							
								
								
									
										34
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | # dependencies (bun install) | ||||||
|  | node_modules | ||||||
|  | 
 | ||||||
|  | # output | ||||||
|  | out | ||||||
|  | dist | ||||||
|  | *.tgz | ||||||
|  | 
 | ||||||
|  | # code coverage | ||||||
|  | coverage | ||||||
|  | *.lcov | ||||||
|  | 
 | ||||||
|  | # logs | ||||||
|  | logs | ||||||
|  | _.log | ||||||
|  | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json | ||||||
|  | 
 | ||||||
|  | # dotenv environment variable files | ||||||
|  | .env | ||||||
|  | .env.development.local | ||||||
|  | .env.test.local | ||||||
|  | .env.production.local | ||||||
|  | .env.local | ||||||
|  | 
 | ||||||
|  | # caches | ||||||
|  | .eslintcache | ||||||
|  | .cache | ||||||
|  | *.tsbuildinfo | ||||||
|  | 
 | ||||||
|  | # IntelliJ based IDEs | ||||||
|  | .idea | ||||||
|  | 
 | ||||||
|  | # Finder (MacOS) folder config | ||||||
|  | .DS_Store | ||||||
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | # arca-signaling | ||||||
|  | 
 | ||||||
|  | To install dependencies: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | bun install | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | To run: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | bun run index.ts | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | This project was created using `bun init` in bun v1.2.12. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. | ||||||
							
								
								
									
										36
									
								
								bun.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								bun.lock
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | { | ||||||
|  |   "lockfileVersion": 1, | ||||||
|  |   "workspaces": { | ||||||
|  |     "": { | ||||||
|  |       "name": "arca-signaling", | ||||||
|  |       "dependencies": { | ||||||
|  |         "ulid": "^3.0.0", | ||||||
|  |         "ws": "^8.18.2", | ||||||
|  |       }, | ||||||
|  |       "devDependencies": { | ||||||
|  |         "@types/bun": "latest", | ||||||
|  |         "@types/ws": "^8.18.1", | ||||||
|  |       }, | ||||||
|  |       "peerDependencies": { | ||||||
|  |         "typescript": "^5", | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   "packages": { | ||||||
|  |     "@types/bun": ["@types/bun@1.2.12", "", { "dependencies": { "bun-types": "1.2.12" } }, "sha512-lY/GQTXDGsolT/TiH72p1tuyUORuRrdV7VwOTOjDOt8uTBJQOJc5zz3ufwwDl0VBaoxotSk4LdP0hhjLJ6ypIQ=="], | ||||||
|  | 
 | ||||||
|  |     "@types/node": ["@types/node@22.15.17", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw=="], | ||||||
|  | 
 | ||||||
|  |     "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], | ||||||
|  | 
 | ||||||
|  |     "bun-types": ["bun-types@1.2.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-tvWMx5vPqbRXgE8WUZI94iS1xAYs8bkqESR9cxBB1Wi+urvfTrF1uzuDgBHFAdO0+d2lmsbG3HmeKMvUyj6pWA=="], | ||||||
|  | 
 | ||||||
|  |     "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], | ||||||
|  | 
 | ||||||
|  |     "ulid": ["ulid@3.0.0", "", { "bin": { "ulid": "dist/cli.js" } }, "sha512-yvZYdXInnJve6LdlPIuYmURdS2NP41ZoF4QW7SXwbUKYt53+0eDAySO+rGSvM2O/ciuB/G+8N7GQrZ1mCJpuqw=="], | ||||||
|  | 
 | ||||||
|  |     "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], | ||||||
|  | 
 | ||||||
|  |     "ws": ["ws@8.18.2", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ=="], | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										95
									
								
								index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | |||||||
|  | import { WebSocket, WebSocketServer } from 'ws'; | ||||||
|  | import { ulid } from 'ulid'; | ||||||
|  | 
 | ||||||
|  | const wss = new WebSocketServer({ port: 8080 }); | ||||||
|  | 
 | ||||||
|  | const rooms = new Map<string, Set<string>>(); | ||||||
|  | const sockets = new Map<string, WebSocket>(); | ||||||
|  | 
 | ||||||
|  | wss.on('connection', (ws) => { | ||||||
|  |     let peerId = ulid(); | ||||||
|  | 
 | ||||||
|  |     const join = (room: string) => { | ||||||
|  |         if (!rooms.has(room)) { | ||||||
|  |             rooms.set(room, new Set([peerId])); | ||||||
|  |         } else { | ||||||
|  |             rooms.get(room)!.add(peerId); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const unjoinAll = () => { | ||||||
|  |         rooms.entries().forEach(([room, peers]) => { | ||||||
|  |             peers.delete(peerId); | ||||||
|  |             if (!peers.size) rooms.delete(room); | ||||||
|  |         }); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     ws.on('message', (message) => { | ||||||
|  |         try { | ||||||
|  |             const text = message.toString('utf8'); | ||||||
|  |             const data = JSON.parse(text); | ||||||
|  | 
 | ||||||
|  |             if (data.type === 'self') { | ||||||
|  |                 ws.send(JSON.stringify({ | ||||||
|  |                     type: 'self', | ||||||
|  |                     id: peerId.toString(), | ||||||
|  |                 })); | ||||||
|  | 
 | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (data.type === 'join' && typeof data.room === 'string') { | ||||||
|  |                 unjoinAll(); | ||||||
|  |                 join(data.room); | ||||||
|  | 
 | ||||||
|  |                 const peers = rooms.get(data.room) ?? []; | ||||||
|  |                 peers.forEach((peer) => { | ||||||
|  |                     sockets.get(peer)!.send(JSON.stringify({ | ||||||
|  |                         type: 'peers', | ||||||
|  |                         peers: peers, | ||||||
|  |                     })); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (data.type === 'offer' && typeof data.peer === 'string' && typeof data.offer === 'object') { | ||||||
|  |                 const otherWS = sockets.get(data.peer); | ||||||
|  |                 if (!otherWS) return; | ||||||
|  | 
 | ||||||
|  |                 otherWS.send(JSON.stringify({ | ||||||
|  |                     type: 'offer', | ||||||
|  |                     from: peerId, | ||||||
|  |                     offer: data.offer, | ||||||
|  |                 })); | ||||||
|  | 
 | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (data.type === 'accept' && typeof data.peer === 'string' && typeof data.counterOffer === 'object') { | ||||||
|  |                 const otherWS = sockets.get(data.peer); | ||||||
|  |                 if (!otherWS) return; | ||||||
|  | 
 | ||||||
|  |                 otherWS.send(JSON.stringify({ | ||||||
|  |                     type: 'accept', | ||||||
|  |                     from: peerId, | ||||||
|  |                     counterOffer: data.counterOffer, | ||||||
|  |                 })); | ||||||
|  | 
 | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             throw 0; | ||||||
|  |         } catch (e) { | ||||||
|  |             ws.send(JSON.stringify({ | ||||||
|  |                 type: 'error', | ||||||
|  |                 message: 'Bad Request', | ||||||
|  |             })); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     ws.on('close', () => { | ||||||
|  |         unjoinAll(); | ||||||
|  |         sockets.delete(peerId); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
							
								
								
									
										17
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | { | ||||||
|  |   "name": "arca-signaling", | ||||||
|  |   "module": "index.ts", | ||||||
|  |   "type": "module", | ||||||
|  |   "private": true, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "@types/bun": "latest", | ||||||
|  |     "@types/ws": "^8.18.1" | ||||||
|  |   }, | ||||||
|  |   "peerDependencies": { | ||||||
|  |     "typescript": "^5" | ||||||
|  |   }, | ||||||
|  |   "dependencies": { | ||||||
|  |     "ulid": "^3.0.0", | ||||||
|  |     "ws": "^8.18.2" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										28
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | { | ||||||
|  |   "compilerOptions": { | ||||||
|  |     // Environment setup & latest features | ||||||
|  |     "lib": ["ESNext"], | ||||||
|  |     "target": "ESNext", | ||||||
|  |     "module": "ESNext", | ||||||
|  |     "moduleDetection": "force", | ||||||
|  |     "jsx": "react-jsx", | ||||||
|  |     "allowJs": true, | ||||||
|  | 
 | ||||||
|  |     // Bundler mode | ||||||
|  |     "moduleResolution": "bundler", | ||||||
|  |     "allowImportingTsExtensions": true, | ||||||
|  |     "verbatimModuleSyntax": true, | ||||||
|  |     "noEmit": true, | ||||||
|  | 
 | ||||||
|  |     // Best practices | ||||||
|  |     "strict": true, | ||||||
|  |     "skipLibCheck": true, | ||||||
|  |     "noFallthroughCasesInSwitch": true, | ||||||
|  |     "noUncheckedIndexedAccess": true, | ||||||
|  | 
 | ||||||
|  |     // Some stricter flags (disabled by default) | ||||||
|  |     "noUnusedLocals": false, | ||||||
|  |     "noUnusedParameters": false, | ||||||
|  |     "noPropertyAccessFromIndexSignature": false | ||||||
|  |   } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user