{"id":22740151,"url":"https://github.com/a-type/converge","last_synced_at":"2025-03-30T03:41:23.310Z","repository":{"id":65522553,"uuid":"484802295","full_name":"a-type/converge","owner":"a-type","description":"Create P2P connections in the browser with other clients interested in the same topic","archived":false,"fork":false,"pushed_at":"2022-04-24T23:58:26.000Z","size":52,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-05T09:51:39.620Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/a-type.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-04-23T16:41:40.000Z","updated_at":"2022-04-25T16:27:26.000Z","dependencies_parsed_at":"2023-01-27T06:00:48.929Z","dependency_job_id":null,"html_url":"https://github.com/a-type/converge","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-type%2Fconverge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-type%2Fconverge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-type%2Fconverge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-type%2Fconverge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/a-type","download_url":"https://codeload.github.com/a-type/converge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246273518,"owners_count":20750904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-10T23:07:45.000Z","updated_at":"2025-03-30T03:41:23.295Z","avatar_url":"https://github.com/a-type.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# converge\n\nCreate P2P connections in the browser with other clients interested in the same topic.\n\nThe goal of this project is to create a simple, minimal, self-hosted baseline for creating P2P connections in the browser with multiple peers at once. Ideally you would find it useful as a core networking component to build your own abstractions around.\n\n## Features\n\n- [x] Connect directly to other peers who are interested in the same topic\n- [x] Broadcast messages to all connected peers\n- [x] Set presence metadata for yourself and get presence of peers\n- [x] Direct message a single peer\n\n## Possible roadmap\n\n- [ ] Send media streams to peers\n- [ ] Require a password or other authorization to connect to discovery server\n- [ ] Gossip messages between a smaller subset of peers rather than connecting to all of them\n- [ ] Shutdown socket connection after bootstrap and discover new peers via gossip of signalling messages\n- [ ] Alternative signalling / bootstrapping\n- [ ] Bundle STUN/TURN into server portion\n- [ ] Multiple data channels to separate different streams and allow for reliable/unreliable delivery, etc\n- [ ] Security features like verifying the origin of a message, etc.\n\n## Usage\n\n### Client\n\n```typescript\nimport { ConvergeClient } from '@a-type/converge-client';\n\n/** Presence is any metadata you want to attach to your client. */\ntype YourPresenceInfo = {\n  name: string;\n};\n\nconst client = new ConvergeClient({\n  server: 'wss://your-server.com',\n  topic: 'some-topic-string',\n});\n\nclient.on('connected', (myId) =\u003e {\n  console.log(`Connected with id ${myId}`);\n});\n\nclient.on('peerConnected', (peerId) =\u003e {\n  console.log(`Peer connected with id ${peerId}`);\n});\n\nclient.on('peerPresenceChanged', (peerId, presence) =\u003e {\n  console.log(`Peer ${peerId} presence changed to ${presence}`);\n});\n\nclient.on('peerDisconnected', (peerId) =\u003e {\n  console.log(`Peer disconnected with id ${peerId}`);\n});\n\nclient.on('peerMessage', (peerId, message) =\u003e {\n  console.log(`Peer message from ${peerId}: ${message}`);\n});\n\n/**\n * Send a message to everyone\n */\nfunction sendMessage(message: string) {\n  client.broadcast(message);\n}\n\n/**\n * Update your presence metadata\n */\nfunction updateMyPresence(presence: YourPresenceInfo) {\n  client.updatePresence(presence);\n}\n\n/**\n * Get your own presence\n */\nclient.presence;\n\n/**\n * Get your own ID (may be undefined before 'connected' event)\n */\nclient.id;\n\n/**\n * Get a list of all connected peer ids\n */\nclient.peers;\n\n/**\n * Inspecting a single peer's presence\n */\nclient.getPresence(peerId);\n\n/**\n * Send a direct message to one peer\n */\nclient.directMessage(peerId, 'message');\n```\n\n### Server\n\n```typescript\nimport { createServer } from 'http';\nimport { attach } from '@a-type/converge-server';\n\nconst server = createServer();\nattach(server, {\n  cors: {\n    origin: '*',\n  },\n});\n\nserver.listen(8080);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-type%2Fconverge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa-type%2Fconverge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-type%2Fconverge/lists"}