{"_id":"@al8b/runtime-realtime","_rev":"5-95dde9370a7d2720bc3131ef7d6998f2","name":"@al8b/runtime-realtime","dist-tags":{"latest":"0.1.15"},"versions":{"0.1.0":{"name":"@al8b/runtime-realtime","version":"0.1.0","keywords":["runtime","realtime","multiplayer","websocket"],"_id":"@al8b/runtime-realtime@0.1.0","maintainers":[{"name":"nonomxyz","email":"hi@nonom.xyz"}],"dist":{"shasum":"66fc9c7a20f03146363531cc3fad344b8cd4d52a","tarball":"https://registry.npmjs.org/@al8b/runtime-realtime/-/runtime-realtime-0.1.0.tgz","fileCount":20,"integrity":"sha512-W5MiHtNaPMimhZFruv493/f2cuzg8LLhx94CONjy7l01fCRbS8Oi0GOME0XySDvEuzW7CAdYQbVomDsM1TLvgQ==","signatures":[{"sig":"MEUCIHJuJr5VzFQTnZZvHeOKw5xrAJBrf6H19ZL9fRtcMDDQAiEAxsmy5WhlyH0ta73fkn1sQQMa3bukUBn6XhS0wCChDic=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30712},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"706a6a43341226da911509eb6de7fc287d24b385","scripts":{"test":"vitest run --passWithNoTests","build":"tsup","clean":"bun --bun ../../../scripts/clean-package.mjs dist"},"_npmUser":{"name":"nonomxyz","email":"hi@nonom.xyz"},"_npmVersion":"10.8.2","description":"Realtime transport adapter for [@al8b/runtime](../runtime/README.md). Enables multiplayer and synchronization features through a pluggable realtime bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"@al8b/runtime":"workspace:*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/runtime-realtime_0.1.0_1775495381500_0.08360728844322307","host":"s3://npm-registry-packages-npm-production"}},"0.1.12":{"name":"@al8b/runtime-realtime","version":"0.1.12","keywords":["runtime","realtime","multiplayer","websocket"],"_id":"@al8b/runtime-realtime@0.1.12","maintainers":[{"name":"nonomxyz","email":"hi@nonom.xyz"}],"dist":{"shasum":"5cbd450b09288e960d87baed231f25d99e4636da","tarball":"https://registry.npmjs.org/@al8b/runtime-realtime/-/runtime-realtime-0.1.12.tgz","fileCount":20,"integrity":"sha512-sfX1IMAfxtkqJMEnwj6TOtgVeesoQktLglljUx26Ng/G2ZFpC7chNOfKKrwh/lF6HjzdjZtAVsE4e/mn70+Dww==","signatures":[{"sig":"MEUCIGRoEnyidySetnlfjRAoKN7mBHk4cYMEv0+GgzPqel/HAiEAh+zGPXsXFMmQq+3URVTSl+z68wvr3CxSlzxyy2CV6EE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30713},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"c962234b8ec1d4ada4c9b1651e62747487c090c3","scripts":{"test":"vitest run --passWithNoTests","build":"tsup","clean":"bun --bun ../../../scripts/clean-package.mjs dist"},"_npmUser":{"name":"nonomxyz","email":"hi@nonom.xyz"},"_npmVersion":"10.8.2","description":"Realtime transport adapter for [@al8b/runtime](../runtime/README.md). Enables multiplayer and synchronization features through a pluggable realtime bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"@al8b/runtime":"workspace:*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/runtime-realtime_0.1.12_1775668120737_0.9967997487171296","host":"s3://npm-registry-packages-npm-production"}},"0.1.13":{"name":"@al8b/runtime-realtime","version":"0.1.13","keywords":["runtime","realtime","multiplayer","websocket"],"_id":"@al8b/runtime-realtime@0.1.13","maintainers":[{"name":"nonomxyz","email":"hi@nonom.xyz"}],"dist":{"shasum":"63acbe532b49656fce5ef98d90ca45fb7f1fc996","tarball":"https://registry.npmjs.org/@al8b/runtime-realtime/-/runtime-realtime-0.1.13.tgz","fileCount":20,"integrity":"sha512-ZB2/7zrwdMm7Yv7Dn40LLwG9PA+LwG1J/eHIEYJ/7ahxO4C+gNE25a3qSPHTEAWZgdBEcXK2LkOZ/I7Q/bICCw==","signatures":[{"sig":"MEYCIQCY23qQ/4FR2pYHnlVRmmwvYyXrmL6ystZT4V6mhwUFbQIhAKD+FfzC/ZmskZELB8N7nvbdgePfr2qjc2NgTCCZr/Gl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30770},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"2c32825289bf3e106bf87e4598adc38eda3ae9e3","scripts":{"test":"vitest run --passWithNoTests","build":"tsup","clean":"bun --bun ../../../scripts/clean-package.mjs dist"},"_npmUser":{"name":"nonomxyz","email":"hi@nonom.xyz"},"_npmVersion":"10.8.2","description":"Realtime transport adapter for [@al8b/runtime](../runtime/README.md). Enables multiplayer and synchronization features through a pluggable realtime bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"@al8b/runtime":"^0.1.13"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/runtime-realtime_0.1.13_1775668938836_0.8569140057649818","host":"s3://npm-registry-packages-npm-production"}},"0.1.14":{"name":"@al8b/runtime-realtime","version":"0.1.14","keywords":["runtime","realtime","multiplayer","websocket"],"_id":"@al8b/runtime-realtime@0.1.14","maintainers":[{"name":"nonomxyz","email":"hi@nonom.xyz"}],"dist":{"shasum":"bfeeaa93d24196b968394fdf64715bc847e397c5","tarball":"https://registry.npmjs.org/@al8b/runtime-realtime/-/runtime-realtime-0.1.14.tgz","fileCount":20,"integrity":"sha512-7NEGjq1R2ASUTJMY9a7wSLOJ7SQSLU7+V/XqI/qd0m2nRSShwVKNAPPTw5GJL7urtav6yMU1e13KOZfU0+WR7Q==","signatures":[{"sig":"MEYCIQDP1AIvmd1iJrRSzIuc4klBRdjKd2j7zak8t8JWKusfYgIhAN6eX2Gg3pvLaKkUNerbhOyN/nDflqOa+XOB7Lks9uwd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30770},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"27c3ab890a72431b9af215861be8f38049cb9a0b","scripts":{"test":"vitest run --passWithNoTests","build":"tsup","clean":"bun --bun ../../../scripts/clean-package.mjs dist"},"_npmUser":{"name":"nonomxyz","email":"hi@nonom.xyz"},"_npmVersion":"10.8.2","description":"Realtime transport adapter for [@al8b/runtime](../runtime/README.md). Enables multiplayer and synchronization features through a pluggable realtime bridge.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"@al8b/runtime":"^0.1.14"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/runtime-realtime_0.1.14_1775910922496_0.030661581281737016","host":"s3://npm-registry-packages-npm-production"}},"0.1.15":{"name":"@al8b/runtime-realtime","version":"0.1.15","sideEffects":false,"scripts":{"build":"tsup","clean":"bun --bun ../../../scripts/clean-package.mjs dist","test":"vitest run --passWithNoTests"},"main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"dependencies":{"@al8b/runtime":"^0.1.15"},"devDependencies":{"typescript":"~5.9.3"},"keywords":["runtime","realtime","multiplayer","websocket"],"publishConfig":{"access":"public"},"_id":"@al8b/runtime-realtime@0.1.15","gitHead":"77176c9f112ae7f55faa84a09c190174133c6b07","description":"Realtime transport adapter for [@al8b/runtime](../runtime/README.md). Enables multiplayer and synchronization features through a pluggable realtime bridge.","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-25sijIm7EG4plrqR412YHpun4kyxQE0OFMW7muR773J26pDExD+uZZvVpYIADukS//s6AcP7ESUhTMFxsk+Vqw==","shasum":"f8a6dc33a0533e8934b24f77a6cca7f3d6c73c8c","tarball":"https://registry.npmjs.org/@al8b/runtime-realtime/-/runtime-realtime-0.1.15.tgz","fileCount":26,"unpackedSize":82171,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAReONLn/C/HyO7VJwMnyEvmFIEfx19CyAqDfBVK3ZZKAiBgLVV1xHLdyZvXSHNKsAnFTWNkJzqeTneNvSGuLHvkOg=="}]},"_npmUser":{"name":"nonomxyz","email":"hi@nonom.xyz"},"directories":{},"maintainers":[{"name":"nonomxyz","email":"hi@nonom.xyz"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/runtime-realtime_0.1.15_1775979446219_0.17087550728837275"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-06T17:09:41.407Z","modified":"2026-04-12T07:37:26.508Z","0.1.0":"2026-04-06T17:09:41.650Z","0.1.12":"2026-04-08T17:08:40.932Z","0.1.13":"2026-04-08T17:22:19.028Z","0.1.14":"2026-04-11T12:35:22.631Z","0.1.15":"2026-04-12T07:37:26.379Z"},"keywords":["runtime","realtime","multiplayer","websocket"],"description":"Realtime transport adapter for [@al8b/runtime](../runtime/README.md). Enables multiplayer and synchronization features through a pluggable realtime bridge.","maintainers":[{"name":"nonomxyz","email":"hi@nonom.xyz"}],"readme":"# @al8b/runtime-realtime\n\nRealtime transport adapter for [@al8b/runtime](../runtime/README.md). Enables multiplayer and synchronization features through a pluggable realtime bridge.\n\n## Installation\n\n```bash\nnpm install @al8b/runtime-realtime @al8b/runtime\n```\n\n## Usage\n\nImplement a `RealtimeBridge` for your chosen transport (WebSocket, WebRTC, etc.), then adapt it to the runtime:\n\n```ts\nimport { createRealtimeBridge, type RealtimeBridge } from \"@al8b/runtime-realtime\";\nimport { createRuntime } from \"@al8b/runtime\";\n\n// Your realtime transport implementation\nconst myWebSocketBridge: RealtimeBridge = {\n  async connect() {\n    // Connect to websocket server\n  },\n  async disconnect() {\n    // Clean up websocket\n  },\n  send(channel, payload) {\n    // Send message on channel\n  },\n  subscribe(channel, handler) {\n    // Listen for messages on channel\n    return () => {\n      // Unsubscribe\n    };\n  },\n};\n\n// Adapt it to the runtime\nconst bridge = {\n  ...createRealtimeBridge(myWebSocketBridge),\n  // Optionally add other bridge capabilities\n  getSession: () => getSessionFromServer(),\n  saveSnapshot: (snap) => cloudSave(snap),\n};\n\n// Create runtime with realtime bridge\nconst runtime = createRuntime({\n  sources: { /* ... */ },\n  resources: { /* ... */ },\n  bridge,\n});\n\nawait runtime.start();\n```\n\n## API\n\n### `createRealtimeBridge(realtime: RealtimeBridge): RuntimeBridge`\n\nAdapts a `RealtimeBridge` to a `RuntimeBridge`.\n\n**Event Channels:**\n\nThe adapter subscribes to these channels:\n- `\"host.event\"` - Incoming host events (mapped to HostEvent)\n- `\"player.message\"` - Direct player-to-host messages\n\nGame emissions are sent on:\n- `\"runtime.emit\"` - Game-side events (name + payload)\n\n**Composition:**\n\nThe returned `RuntimeBridge` only implements `emit` and `subscribe`. To add other capabilities:\n\n```ts\nconst bridge = {\n  ...createRealtimeBridge(realtime),\n  request: async (name, payload) => { /* ... */ },\n  getSession: () => { /* ... */ },\n  saveSnapshot: async (snap) => { /* ... */ },\n  loadSnapshot: async (meta) => { /* ... */ },\n};\n```\n\n### `RealtimeBridge`\n\nInterface for a realtime transport:\n\n```ts\nexport interface RealtimeBridge {\n  connect(): Promise<void>;\n  disconnect(): Promise<void>;\n  send(channel: string, payload: unknown): void;\n  subscribe(channel: string, handler: (payload: unknown) => void): () => void;\n}\n```\n\n## Combining with `@al8b/http-bridge`\n\nFor multiplayer games that also need REST API access (user profiles, leaderboards, inventory), compose `@al8b/http-bridge` with `@al8b/runtime-realtime`:\n\n```ts\nimport { createRealtimeBridge } from \"@al8b/runtime-realtime\";\nimport { createHttpBridge } from \"@al8b/http-bridge\";\n\n// Realtime bridge handles real-time player sync\n// HttpBridge handles REST API calls\nconst bridge = {\n  ...createRealtimeBridge(myWebSocket),\n  ...createHttpBridge({ baseUrl: \"https://api.mygame.com\" }),\n  // Both getSession and saveSnapshot/loadSnapshot should come from\n  // your auth layer (server or secure storage), not just HTTP:\n  getSession: () => getSessionFromServer(),\n  saveSnapshot: async (snap) => cloudSave(snap),\n  loadSnapshot: async (meta) => cloudLoad(meta),\n};\n\ncreateRuntime({ bridge, sources: { main: \"...\" } });\n```\n\nIn your LootiScript game:\n```lua\n-- Realtime: fire-and-forget player events\nhost.emit(\"player.move\", { x: 100, y: 50 });\n\n-- REST: fetch data with callback\nhost.request(\"user.getProfile\", { id: session.user().id }, function(response)\n    print(\"Hello \" + response.name);\nend);\n```\n\n## Example: WebSocket Transport\n\n```ts\nimport { createRealtimeBridge } from \"@al8b/runtime-realtime\";\nimport type { RealtimeBridge } from \"@al8b/runtime-realtime\";\n\nclass WebSocketRealtimeBridge implements RealtimeBridge {\n  private ws: WebSocket | null = null;\n  private subscriptions = new Map<string, Set<(payload: unknown) => void>>();\n\n  async connect() {\n    return new Promise<void>((resolve, reject) => {\n      this.ws = new WebSocket(\"wss://realtime.example.com\");\n      this.ws.onopen = () => resolve();\n      this.ws.onerror = () => reject(new Error(\"WebSocket connection failed\"));\n      this.ws.onmessage = (event) => {\n        const message = JSON.parse(event.data);\n        const handlers = this.subscriptions.get(message.channel);\n        handlers?.forEach((h) => h(message.payload));\n      };\n    });\n  }\n\n  async disconnect() {\n    this.ws?.close();\n  }\n\n  send(channel: string, payload: unknown) {\n    this.ws?.send(JSON.stringify({ channel, payload }));\n  }\n\n  subscribe(channel: string, handler: (payload: unknown) => void) {\n    if (!this.subscriptions.has(channel)) {\n      this.subscriptions.set(channel, new Set());\n    }\n    this.subscriptions.get(channel)!.add(handler);\n    return () => {\n      this.subscriptions.get(channel)?.delete(handler);\n    };\n  }\n}\n\nconst bridge = createRealtimeBridge(new WebSocketRealtimeBridge());\n```\n\n## Multiplayer Patterns\n\nOnce integrated, games can emit realtime events:\n\n```loot\n// In LootiScript\nhost.emit(\"player.move\", { x: 100, y: 50 })\nhost.emit(\"player.action\", { action: \"jump\" })\n```\n\nThe realtime bridge forwards these to the backend, which can synchronize across players.\n\n## Notes\n\n- The adapter is transport-agnostic; implement `RealtimeBridge` for your chosen protocol\n- Channel names are conventions between your game and backend; adjust as needed\n- Reliability, ordering, and backpressure handling are transport responsibilities\n- Games should not assume synchronous delivery; use async request/response patterns for critical data\n\n## Scripts\n\n```bash\nbun run build  # Build the package\nbun run test   # Run tests\nbun run clean  # Clean build artifacts\n```\n","readmeFilename":"README.md"}