{"id":13801585,"url":"https://github.com/denyncrawford/dropper-deno","last_synced_at":"2026-02-24T17:45:31.337Z","repository":{"id":45235044,"uuid":"327196725","full_name":"denyncrawford/dropper-deno","owner":"denyncrawford","description":"Custom event-based WebSockets framework for building real-time apps on Deno 🦕","archived":false,"fork":false,"pushed_at":"2023-07-06T19:44:30.000Z","size":192,"stargazers_count":26,"open_issues_count":1,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-01T02:51:52.479Z","etag":null,"topics":["client","deno","real-time","server","socket","websocket","websockets"],"latest_commit_sha":null,"homepage":"","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/denyncrawford.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-06T04:13:23.000Z","updated_at":"2023-02-25T21:33:16.000Z","dependencies_parsed_at":"2024-08-04T00:17:51.711Z","dependency_job_id":null,"html_url":"https://github.com/denyncrawford/dropper-deno","commit_stats":{"total_commits":47,"total_committers":5,"mean_commits":9.4,"dds":"0.23404255319148937","last_synced_commit":"d9202a52f4fa924a6c1f13614ee6c5df591bcc5a"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denyncrawford%2Fdropper-deno","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denyncrawford%2Fdropper-deno/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denyncrawford%2Fdropper-deno/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/denyncrawford%2Fdropper-deno/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/denyncrawford","download_url":"https://codeload.github.com/denyncrawford/dropper-deno/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251815443,"owners_count":21648367,"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":["client","deno","real-time","server","socket","websocket","websockets"],"created_at":"2024-08-04T00:01:24.679Z","updated_at":"2026-02-24T17:45:26.315Z","avatar_url":"https://github.com/denyncrawford.png","language":"TypeScript","funding_links":["https://paypal.me/DENYNCRAWFORD?locale.x=en_US"],"categories":["Modules"],"sub_categories":["Assistants","WebSocket"],"readme":"# Dropper\n\nDropper is a custom **Event-driven WebSocket framework** for Deno, using the deno-std ws module as base.\n\n\u003e Send and receive notifications, messages, updates and any data, all in real-time with custom events and methods served on your own, Dropper is Open Source, self-served and FREE forever!\n\n## What can I do with Dropper?\n\nSince Dropper is a WebSocket solution for transporting data between servers and clients, you can do whatever you need to go on real-time, like chat apps, trading, bots, database and website hot refreshs, etc. Its Side by Side APIs are designed to handle custom events sent by the application peers, you can work with the structured event handlers that allows to send and receive filtered data in a woshhh.\n\n## Quick Demo\n\nThe chat test on this repo [lives on glitch](https://deno-dropper.glitch.me/), and you can test the app in production, but you can also run the demo on your local machine:\n\n```bash\ndeno run -A https://deno.land/x/dropper@1.10.0/examples/chat/src/server.js\n```\n\n\u003e It will start a server on 8080 port\n\n## Importing\n\n**Server:**\n\n```ts\nimport { Server } from 'https://deno.land/x/dropper@1.10.0/src/mod.ts';\n//or\nimport { Server } from 'https://x.nest.land/dropper@1.10.0/src/mod.ts'\n```\n\n**Deno client:**\n\nYou can import the client directly on your Deno app.\n\n```ts\nimport Dropper from 'https://deno.land/x/dropper@1.10.0/src/mod.ts';\n//or\nimport Dropper from 'https://x.nest.land/dropper@1.10.0/src/mod.ts'\n```\n\n**Browser client**\n\nYou can import this client on the browser in a module script.\n\n```ts\nimport Dropper from 'https://deno.land/x/dropper@1.10.0/dist/clients/dropper.js';\n//or\nimport Dropper from 'https://x.nest.land/dropper@1.10.0/dist/clients/dropper.js'\n```\n\n## Usage\n\nBy default, you can use two instances of Dropper, the server and the client. The API is very similar to the EventEmitter API, but it is WebScoekts using on custom events.\n\n## Server:\n\nThe server waits for socket connections using the global event `connection`. This event gets the new connected socket on its callback. This socket represents a client so the API is the same as in the client side.\n\n### Stand alone server\n\nDropper is stand alone by default, which means that you don't need to provide an http server, when you create a dropper it serves by default on port 8080. \n\n\u003e This is useful whe you are creating an app without a server side.\n\n```javascript\n\nconst options;\n\nconst dropper = new Server(options); // Creates a default server on port 8080\n\ndropper.on('connection', socket =\u003e { // W\n  socket.send('pizza', 'I sent you a pizza!')\n  socket.on('thanks', data =\u003e {\n    console.log(data) // =\u003e Thanks btw\n  })\n})\n\n// Listening for global events\n\ndropper.on('thanks', data =\u003e {\n  console.log(data) // =\u003e Thanks btw\n})\n\n```\n\n### Middleware server\n\nYou can also use Dropper with a server/framework setup since it handles each request separately with the method `Dropper.handle(req)`\n\n- **Using a framework like opine**:\n\n```javascript\nimport { opine } from 'https://deno.land/x/opine/mod.ts'\nconst app = opine();\nimport { Server as Dropper } from '...'\n\nconst dropper = new Dropper({\n  serve: false // Important\n})\n\napp.use('/dropper', (req) =\u003e dropper.handle(req)); // Don't respond or call next, just use the request.\n\napp.get('/', (req, res) =\u003e {\n  //...foo\n})\n\ndropper.on('connection', socket =\u003e {\n  ..foo\n})\n\napp.listen(3000)\n\n``` \n\n- **Using the Deno's std http server**:\n\n```javascript\nimport { serve } from 'https://deno.land/std/http/server.ts'\nimport { Server as Dropper } from '...'\n\nconst server = serve('localhost:3000')\n\nconst dropper = new Dropper({\n  serve: false // Important\n})\n\ndropper.on('connection', socket =\u003e {\n  ..foo\n})\n\nfor await (const req of server) {\n  if (req.url === '/dropper') {\n    dropper.handle(req);\n  } else {\n    // return static content, etc\n  }\n}\n\n```\n\n\u003e Please note that we use the `/dropper` endpoint on both of the examples. This is because we don't want to touch any usable endpoint, you can use whatever you want as endpoint, but you have to provide it in the Dropper **client** config object which is by default `/dropper`.\n\n### Options (optional) \n\n- `host`: The host you want to use if the serve option is true. \n  - Default: 'localhost',\n- `port`: The host you want to use if the serve option is true\n  - Default: 8080,\n- `interval`: The ping interval in ms.\n  - Default: 3000\n- `serve`: Set false if you don't want to serve Dropper (stand alone) - Using with your own http server.\n  - Default: true\n\n### API\n\n**Methods**:\n\n  - `Dropper.on` - Listen for the server events.\n\n    The `on` method receives two arguments:\n\n      - `event` - The event name\n      - `callback` - Callback function to get the new connected socket instance if the event is `connection` or the event data if the event is `any`. \n  \n  - `Dropper.send` - Send global data to all connected sockets\n    \n    The `send` method receive two arguments.\n\n      - Argument1: `event` | `data` - This argument changes to data if the data argument is not provided, by default it is the event name.\n      - `data` (optional) - This is the data to be sent.\n\n  - `Dropper.handle` - Handles the request to accept WebSockets\n\n    The `handle` method receive one arguments.\n\n      - `request` - This is a deno std http request object of the type `ServerRequest`.\n\n**Properties**:\n\n  - `Dropper.clients` - List of all connected clients instances.\n\n### Sending data to clients\n\nYou can send data to clients in three ways:\n\n- **Just to the current socket**:\n\n```javascript\ndropper.on('connection', socket =\u003e {\n  socket.send('hello')\n})\n```\n\nNo one will receive this data except the current socket.\n\n- **To all sockets but the current one**:\n\n```javascript\ndropper.on('connection', socket =\u003e {\n  socket.broadcast('hello')\n})\n```\n\nAll clients will receive the data except the current client.\n\n- **To all connected sockets**:\n\n```javascript\ndropper.send('hello')\n```\n\nAll clients will receive the data .\n\n### Listening for client events\n\n- **All events from current socket or globally**:\n\nThe event name for listening to all events is `_all_`\n\n```javascript\ndropper.on('connection', socket =\u003e {\n  socket.on('_all_', data =\u003e { // Listen for all events from this socket\n\n  })\n})\n\n// or globally\n\ndropper.on('_all_', ...foo)\n```\n\n- **Custom events from current socket or globally**:\n\n```javascript\n...\nsocket.on('custom_event', ...foo) // Catch event just from the socket\n...\n\ndropper.on('custom_event', ...foo) // Catch event from all sockets\n```\n\n- **No named events from current socket or globally**:\n\nIf the client send a no named event (`client_side_dropper.send('no named')`), you can listen to it with the event name `message`\n\n```javascript\n...\nsocket.on('message', ...foo) // Catch no named event just from the socket\n...\n\ndropper.on('message', ...foo) // Catch no named event from all sockets\n```\n\n### Handling disconnections from server\n\nYou can handle disconnections on two scopes:\n\n**From socket**:\n\nHandling disconnects from sockets only works if the socket is manually disconnected. It will not work if the client loses connection. The callback receives the same two arguments as in the client API (bellow).\n\n```javascript\ndropper.on('connection', socket =\u003e {\n  socket.on('close', (code, reason) =\u003e {\n    //...foo\n  })\n})\n```\n\n**From global**\n\nHandling global disconnects will listen to all clients that disconnect manually and also those that lose connection. The callback receives the same two arguments as in the client API (bellow) plus the disconnected socket as in the connection event.\n\n```javascript\ndropper.on('disconnection', (code, reason, socket) =\u003e {\n  //...foo\n})\n```\n\n### Reserved event senders\n\nThis is a list with the events you shouldn't play with:\n\n- `connection` - The connection event sending is reserved for handling peer connection on server.\n- `error` - The error event sending is reserved for handling connection issues.\n- `disconnection` - The disconnection event sending is reserved for handling peer disconnection on server.\n\n## Client\n\nThe client API connects to a server and it is a socket instance, so it has the same methods as the `socket` above.\n\u003e Note: For creating clients on deno you can import Dropper from the main module, please don't use the Browser bundle.\n\n\n```javascript\nconst dropper = new Dropper(); // Connect the client on port 8080\ndropper.on('pizza', function(data){\n  console.log(data) // =\u003e I sent you a pizza!\n  dropper.send('thanks', 'Thanks btw');\n  dropper.close() // Closes the connection manually\n});\n\ndropper.on('close' =\u003e console.log('done'))\n```\n### Connecting custom hosts\n\nBy default the Dropper clients connect to `ws://localhost:8080` but you can change it by passing the host string as first param, you must specify if the connection is secure or not with the protocols `ws || http` for insecure connections or `wss || https` for secure connections.\n\n```javascript\nconst dropper = new Dropper('ws://localhost:3000'); // Connect the client on port 3000\n\n// OR\n\nconst options = {\n  endpoint: '/myDropperServerReservedEndpoint'\n}\n\nconst dropper = new Dropper(`wss://${window.location.host}`, options); // Connects the client on the current host with a secure connection\n```\n\n### Options (optional)\n\n- `endpoint` - This is the endpoint that the server uses to handle wbsockets.\n  - Default: `/dropper`\n\n### API\n\n**Methods**:\n\n- `Dropper.close` - Closes the connection.\n\n  The `close` method receives two **optional** arguments:\n\n  - `code` - Connection close code number\n  - `reason` - A reason message for the close event.\n\n- `Dropper.broadcast` - Send the data to the server to be broadcasted to all peers except the emitter one.\n\n  The `broadcast` method receive two arguments.\n\n    - Argument1: `event` | `data` - This argument changes to data if the data argument is not provided, by default it is the event name.\n     - `data` (optional) - This is the data to be sent.\n\n- `Dropper.on` - Listen for the client events.\n\n  The `on` method receives two arguments:\n\n    - `event` - The event name\n    - `callback` - Callback function to get the event data. \n\n- `Dropper.send` - Send the data to the server.\n\n  The `send` method receive same arguments as the `broadcast` method.\n\n  **Properties**:\n\n  - `Dropper.uuid` - The id of the client.\n  - `Dropper._socket` - This is the WebSocket instance itself.\n  - `Dropper.uri` - The WebSockets connection uri.\n\n## Sending data to server\n\n- **Named event** \n\nThis is pushing a custom event to the server\n\n```javascript\ndropper.send('pizza', 'this is a pizza')\n```\n\n```javascript\ndropper.broadcast('pizza', 'this is a pizza')\n```\n\nThis is broadcasting a custom event to the server\n\n- **No named event** \n\nThis is pushing a no named event to the server\n\n```javascript\ndropper.send('this is a pizza')\n```\n\nThis is broadcasting a no named event to the server\n\n```javascript\ndropper.broadcast('this is a pizza')\n```\n\n### Listening for server events\n- **Named event** \n\nThis is listening a custom event from the server\n\n```javascript\ndropper.on('pizza', data =\u003e {\n  ...foo\n})\n```\n\n- **No named event** \n\nThis is listening a no named event from the server\n\n```javascript\ndropper.on('message', data =\u003e {\n  ...foo\n})\n```\n\n## Handling disconnections\n\n- **Handle own disconnection**\n\nTo handle the socket disconnection you can use the `close` event. It only listen when the sockets disconnects itself.\n\n```javascript\ndropper.on('close', (code, reason) =\u003e {\n  ...foo\n})\n```\n\n- **Handle other peers disconnection**\n\nWhen a peer disconnects the server trigger the `disconnection` event that is useful for listening when other peers leave. It provides de uuid of the leaving socket.\n\n```javascript\ndropper.on('disconnection', uuid =\u003e {\n  ...foo\n})\n```\n\n## Reserved event senders\n\nThis is a list with the events you shouldn't play with:\n\n- `_binary_` - The binary event sending is reserved for handling Uint8Array data.\n- `error` - The error event sending is reserved for handling connection issues.\n- `_all_` - The message event is the global event for listening to data.\n- `_ping_` - The ping event is a websockets connection handler.\n- `_pong_` - The pong event is a websockets connection handler.\n- `_broadcast_` - The broadcast event is an internal event for transport data to all users but the current one.\n\n## Event collision warning\n\nAll the Dropper internal events has as prefix and suffix `_`. For example this is an internal event: `_ping_`, This is for preventing event collisions.\n\n## Building the web client\n\n- Install rollup from [this module](https://deno.land/x/drollup)\n\n- Perform the bundle:\n\n```bash\nrollup -c\n```\n\n#### The documentation is WIP right now\n\nBy now, you can find detailed code in the examples folder.\n\n# 📝 Roadmap\n\n- Channels support\n- ✔️ Rename the `message` event to `_all_`\n- ✔️ Broadcast support\n- Auto reconnect\n- ✔️ Improve documentation\n- Website\n- ✔️ Prevent using internal events\n- ✔️ Handle forced client disconnection\n\n# 👊 Support this project by donating on:\n- [Paypal](https://paypal.me/DENYNCRAWFORD?locale.x=en_US).\n- BTC address: 39ik7oyYvmiMeTXTscY3bb9rUFMHdjf5pd\n\n# 📜 MIT License\n\nCopyright (c) Crawford.\n\n[Full license](/LICENSE.md)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenyncrawford%2Fdropper-deno","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdenyncrawford%2Fdropper-deno","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenyncrawford%2Fdropper-deno/lists"}