{"id":49659398,"url":"https://github.com/sockudo/sockudo-http-node","last_synced_at":"2026-05-06T11:05:05.873Z","repository":{"id":348465125,"uuid":"1195300510","full_name":"sockudo/sockudo-http-node","owner":"sockudo","description":"Sockudo Node HTTP server SDK","archived":false,"fork":false,"pushed_at":"2026-04-11T09:46:35.000Z","size":867,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-11T11:26:53.306Z","etag":null,"topics":["http","nodejs","realtime","sdk","sockudo"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/sockudo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-29T13:57:48.000Z","updated_at":"2026-04-11T09:46:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sockudo/sockudo-http-node","commit_stats":null,"previous_names":["sockudo/sockudo-http-node"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sockudo/sockudo-http-node","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sockudo%2Fsockudo-http-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sockudo%2Fsockudo-http-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sockudo%2Fsockudo-http-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sockudo%2Fsockudo-http-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sockudo","download_url":"https://codeload.github.com/sockudo/sockudo-http-node/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sockudo%2Fsockudo-http-node/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32690549,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-06T08:33:17.875Z","status":"ssl_error","status_checked_at":"2026-05-06T08:33:17.221Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["http","nodejs","realtime","sdk","sockudo"],"created_at":"2026-05-06T11:04:50.431Z","updated_at":"2026-05-06T11:05:05.865Z","avatar_url":"https://github.com/sockudo.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sockudo\n\nOfficial Node.js server SDK for [Sockudo](https://github.com/sockudo/sockudo) — a fast, self-hosted WebSocket server with full Pusher HTTP API compatibility.\n\n## Supported Platforms\n\nThis SDK supports **Node.js 16+**.\n\n## Installation\n\n```bash\nnpm install sockudo\n# or\nyarn add sockudo\n# or\nbun add sockudo\n```\n\n## Importing\n\n```javascript\n// CommonJS\nconst { Sockudo } = require(\"sockudo\")\n\n// ESM / TypeScript\nimport { Sockudo } from \"sockudo\"\n```\n\nAll external APIs have TypeScript definitions included — no separate `@types` package required.\n\n## Configuration\n\n```javascript\nconst sockudo = new Sockudo({\n  appId: \"your-app-id\",\n  key: \"your-app-key\",\n  secret: \"your-app-secret\",\n  host: \"127.0.0.1\",    // self-hosted Sockudo instance\n  port: 6001,\n  useTLS: false,\n})\n```\n\n| Option    | Type    | Default      | Description                           |\n|-----------|---------|--------------|---------------------------------------|\n| `appId`   | string  | —            | Application ID                        |\n| `key`     | string  | —            | Application key                       |\n| `secret`  | string  | —            | Application secret                    |\n| `host`    | string  | `127.0.0.1` | Sockudo server host                   |\n| `port`    | number  | `6001`       | Sockudo server port                   |\n| `useTLS`  | boolean | `false`      | Use HTTPS/WSS                         |\n| `timeout` | number  | `30000`      | Request timeout in milliseconds       |\n| `proxy`   | string  | —            | HTTP proxy URL                        |\n\n### Instantiation from URL\n\n```javascript\nconst sockudo = Sockudo.forURL(\"http://key:secret@127.0.0.1:6001/apps/app-id\")\n```\n\n## Publishing Events\n\n### Single Channel\n\n```javascript\nawait sockudo.trigger(\"my-channel\", \"my-event\", { message: \"hello world\" })\n```\n\n### Multiple Channels\n\n```javascript\nawait sockudo.trigger(\n  [\"channel-1\", \"channel-2\", \"channel-3\"],\n  \"my-event\",\n  { message: \"hello world\" }\n)\n```\n\nYou can trigger on up to 100 channels in a single call.\n\n### Batch Events\n\nSend multiple events in a single HTTP request (up to 10 events per call):\n\n```javascript\nawait sockudo.triggerBatch([\n  { channel: \"channel-1\", name: \"event-1\", data: { x: 1 } },\n  { channel: \"channel-2\", name: \"event-2\", data: { x: 2 } },\n  { channel: \"channel-3\", name: \"event-3\", data: { x: 3 } },\n])\n```\n\n### Excluding a Socket Recipient\n\nPass `socket_id` to prevent the triggering connection from receiving its own event:\n\n```javascript\nawait sockudo.trigger(\"my-channel\", \"my-event\", { message: \"hello\" }, {\n  socket_id: \"123.456\",\n})\n```\n\n## Idempotent Publishing\n\nUse `idempotency_key` to safely retry publishes without causing duplicate deliveries. The server deduplicates events with the same key within the configured window.\n\n### Explicit key\n\n```javascript\nawait sockudo.trigger(\"my-channel\", \"my-event\", { message: \"hello\" }, {\n  idempotency_key: \"order-shipped-order-789\",\n})\n```\n\n### Auto-generated UUID\n\nPass `true` to have the SDK generate a UUID automatically:\n\n```javascript\nawait sockudo.trigger(\"my-channel\", \"my-event\", { message: \"hello\" }, {\n  idempotency_key: true,\n})\n```\n\n## Channel Authorization\n\n### Private Channel\n\n```javascript\nconst auth = sockudo.authorizeChannel(socketId, channelName)\n// Returns: { auth: \"key:signature\" }\n```\n\n### Presence Channel\n\nPass user data as the third argument to authorize a presence channel subscription:\n\n```javascript\nconst auth = sockudo.authorizeChannel(socketId, channelName, {\n  user_id: \"user-123\",\n  user_info: {\n    name: \"Jane Doe\",\n    email: \"jane@example.com\",\n  },\n})\n// Returns: { auth: \"key:signature\", channel_data: \"...\" }\n```\n\n## User Authentication\n\nAuthenticate a user connection for user-targeted events:\n\n```javascript\nconst auth = sockudo.authenticateUser(socketId, {\n  id: \"user-123\",\n  user_info: {\n    name: \"Jane Doe\",\n    role: \"admin\",\n  },\n})\n// Returns: { auth: \"key:signature\", user_data: \"...\" }\n```\n\n## Terminating User Connections\n\nDisconnect all active connections for a given user:\n\n```javascript\nawait sockudo.terminateUserConnections(\"user-123\")\n```\n\n## Webhooks\n\nVerify and parse incoming Sockudo webhooks:\n\n```javascript\nconst webhook = sockudo.webhook({\n  rawBody: req.rawBody,     // raw string body\n  headers: req.headers,\n})\n\nif (webhook.isValid()) {\n  const data = webhook.getData()\n  const events = webhook.getEvents()\n  const time = webhook.getTime()\n\n  for (const event of events) {\n    console.log(event.name, event.channel, event.data)\n  }\n}\n```\n\n`isValid()` also accepts additional tokens to check against (useful during key rotation):\n\n```javascript\nwebhook.isValid([\n  { key: \"old-key\", secret: \"old-secret\" },\n])\n```\n\n## Application State\n\n```javascript\n// List all channels\nconst response = await sockudo.get({ path: \"/channels\", params: {} })\nconst body = await response.json()\n\n// Get a specific channel\nconst response = await sockudo.get({ path: \"/channels/my-channel\", params: {} })\n\n// List users in a presence channel\nconst response = await sockudo.get({ path: \"/channels/presence-room/users\" })\n```\n\n## Express Integration\n\n### Channel Authorization Endpoint\n\n```javascript\nimport express from \"express\"\nimport { Sockudo } from \"sockudo\"\n\nconst app = express()\nconst sockudo = new Sockudo({\n  appId: process.env.SOCKUDO_APP_ID,\n  key: process.env.SOCKUDO_KEY,\n  secret: process.env.SOCKUDO_SECRET,\n  host: \"127.0.0.1\",\n  port: 6001,\n})\n\napp.post(\"/sockudo/auth\", express.urlencoded({ extended: false }), (req, res) =\u003e {\n  const { socket_id, channel_name } = req.body\n\n  if (!isUserAuthorized(req, channel_name)) {\n    return res.status(403).json({ error: \"Forbidden\" })\n  }\n\n  let presenceData\n  if (channel_name.startsWith(\"presence-\")) {\n    presenceData = {\n      user_id: req.user.id,\n      user_info: { name: req.user.name },\n    }\n  }\n\n  const auth = sockudo.authorizeChannel(socket_id, channel_name, presenceData)\n  res.json(auth)\n})\n```\n\n### Webhook Endpoint\n\n```javascript\napp.post(\n  \"/sockudo/webhook\",\n  express.raw({ type: \"application/json\" }),\n  (req, res) =\u003e {\n    const webhook = sockudo.webhook({\n      rawBody: req.body.toString(),\n      headers: req.headers,\n    })\n\n    if (!webhook.isValid()) {\n      return res.status(401).send(\"Invalid signature\")\n    }\n\n    for (const event of webhook.getEvents()) {\n      console.log(\"Webhook event:\", event)\n    }\n\n    res.sendStatus(200)\n  }\n)\n```\n\n## Fastify Integration\n\n```javascript\nimport Fastify from \"fastify\"\nimport { Sockudo } from \"sockudo\"\n\nconst app = Fastify()\nconst sockudo = new Sockudo({\n  appId: process.env.SOCKUDO_APP_ID,\n  key: process.env.SOCKUDO_KEY,\n  secret: process.env.SOCKUDO_SECRET,\n})\n\napp.addContentTypeParser(\n  \"application/x-www-form-urlencoded\",\n  { parseAs: \"string\" },\n  (req, body, done) =\u003e {\n    done(null, Object.fromEntries(new URLSearchParams(body)))\n  }\n)\n\napp.post(\"/sockudo/auth\", (req, reply) =\u003e {\n  const { socket_id, channel_name } = req.body\n  const auth = sockudo.authorizeChannel(socket_id, channel_name)\n  reply.send(auth)\n})\n```\n\n## TypeScript\n\n```typescript\nimport { Sockudo, TriggerOptions, BatchEvent } from \"sockudo\"\n\nconst sockudo = new Sockudo({\n  appId: process.env.SOCKUDO_APP_ID!,\n  key: process.env.SOCKUDO_KEY!,\n  secret: process.env.SOCKUDO_SECRET!,\n})\n\nconst options: TriggerOptions = {\n  socket_id: \"123.456\",\n  idempotency_key: \"my-idempotency-key\",\n}\n\nawait sockudo.trigger(\"my-channel\", \"my-event\", { data: true }, options)\n\nconst batch: BatchEvent[] = [\n  { channel: \"ch-1\", name: \"event-a\", data: { value: 1 } },\n  { channel: \"ch-2\", name: \"event-b\", data: { value: 2 } },\n]\n\nawait sockudo.triggerBatch(batch)\n```\n\n## Testing\n\n```bash\nnpm install\nnpm test\n```\n\n## Channel History\n\n```javascript\nconst page = await sockudo.channelHistory(\"my-channel\", {\n  limit: 50,\n  direction: \"newest_first\",\n})\n\nconst nextPage = await sockudo.channelHistory(\"my-channel\", {\n  cursor: \"opaque-cursor-from-previous-page\",\n})\n```\n\n## Pusher SDK Compatibility\n\nSockudo implements the full Pusher HTTP API. If you prefer to use the official `pusher` npm package or are migrating from Pusher, point it at your Sockudo instance without any other changes:\n\n```javascript\nconst Pusher = require(\"pusher\")\n\nconst client = new Pusher({\n  appId: \"app-id\",\n  key: \"app-key\",\n  secret: \"app-secret\",\n  host: \"127.0.0.1\",\n  port: \"6001\",\n  useTLS: false,\n})\n```\n\nAll standard Pusher SDK calls work against a self-hosted Sockudo server without modification.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsockudo%2Fsockudo-http-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsockudo%2Fsockudo-http-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsockudo%2Fsockudo-http-node/lists"}