{"id":"elentium/wire","name":"wire","scope":"elentium","platform":"roblox","description":"High performance BindableEvent + BindableFunction implementation library for Roblox","version":"0.0.4","latest":"0.0.4","versions":["0.0.1","0.0.2","0.0.3","0.0.4"],"license":"Apache-2.0","licenseRating":"safe","licenseCaveats":["Modified files must carry a notice of changes. If the package ships a NOTICE file, its attributions must be preserved."],"licenseVerified":true,"dependencies":{},"integrity":"3830004e1b8557afeea23562878605e529a23a4bb2c29aadb97bb81f8ed2d0ab","likes":0,"downloads":0,"install":"forest install elentium/wire","url":"https://forest.dev/p/roblox/elentium/wire","files":"https://api.forest.dev/ai/package/roblox/elentium/wire/files","readme":"# Wire\n<p align=\"center\">\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/badge/License-Apache%202.0-blue?style=flat-square\" alt=\"License\" /></a>\n  <a href=\"https://wally.run/package/elentium/wire\"><img src=\"https://img.shields.io/badge/📦_Wally-elentium/wire-00b4ab?style=flat-square\" alt=\"Wally\"/></a>\n</p>\n\n<p align=\"center\">\n  <strong>A high-performance, signal and request library for Roblox. Wire provides lightweight alternatives to `BindableEvent` and `BindableFunction` with superior performance and a clean, functional API.\n</strong>\n</p>\n\n\n## Features\n\n- **Blazing Fast** — Outperforms GoodSignal, SignalPlus, and FastSignal in benchmarks\n- **O(1) Disconnect** — Doubly-linked list architecture enables constant-time connection removal\n- **Thread Pool Recycling** — Efficient coroutine reuse for async operations\n- **Parallel Luau Support** — First-class support for parallel execution with `connectParallel`\n- **Dual Paradigm** — Both event-style signals and RPC-style requests\n- **Type-Safe** — Full Luau strict mode with exported types\n- **Zero Dependencies** — Pure Luau implementation\n- **Memory-Efficient** — Instead of creating a table & using metatables for every signal object, it simply creates an ID and only stores head & tail connections when needed\n\n## Installation\n\n### Wally\n\n```toml\n[dependencies]\nWire = \"elentium/wire@0.0.4\"\n```\n\n### Manual\n\ninstall the roblox-direct/Wire.rbxm and insert in studio\n\n## Quick Start\n\n```luau\nlocal Wire = require(path.to.Wire)\n\n-- Create a signal\nlocal PlayerDamaged = Wire.signal()\n\n-- Connect a listener\nlocal connection = Wire.connect(PlayerDamaged, function(player, damage)\n    print(player.Name .. \" took \" .. damage .. \" damage!\")\nend)\n\n-- Fire the signal\nWire.fire(PlayerDamaged, player, 25)\n\n-- Disconnect when done\nconnection:disconnect()\n```\n\n## API Reference\n\n### Constructors\n\n#### `Wire.signal() -> number`\nCreates a new signal and returns its entity ID.\n\n```luau\nlocal MySignal = Wire.signal()\n```\n\n#### `Wire.request(callback?) -> number`\nCreates a new request (similar to BindableFunction) and returns its entity ID.\n\n```luau\nlocal GetPlayerData = Wire.request(function(player)\n    return playerDataStore[player]\nend)\n```\n\n### Signal Methods\n\n#### `Wire.connect(entityID, callback) -> WireConnection`\nConnects a callback to a signal. Returns a connection object.\n\n```luau\nlocal connection = Wire.connect(MySignal, function(...)\n    print(\"Signal fired with:\", ...)\nend)\n```\n\n#### `Wire.connectParallel(entityID, callback) -> WireConnection`\nConnects a callback that runs in parallel (for Parallel Luau).\n\n```luau\nWire.connectParallel(HeavyComputation, function(data)\n    -- This runs desynchronized from the main thread\n    processData(data)\nend)\n```\n\n#### `Wire.once(entityID, callback) -> WireConnection`\nConnects a callback that automatically disconnects after the first fire.\n\n```luau\nWire.once(GameStarted, function()\n    print(\"Game has started!\")\nend)\n```\n\n#### `Wire.onceParallel(entityID, callback) -> WireConnection`\nCombines `once` and `connectParallel` — runs once in parallel, then disconnects.\n\n#### `Wire.fire(entityID, ...) -> ()`\nFires a signal synchronously. All callbacks execute sequentially in the current thread.\n\n```luau\nWire.fire(MySignal, \"arg1\", \"arg2\", 123)\n```\n\n> **Recommended** for non-yielding callbacks. Most performant option.\n\n#### `Wire.fireSafe(entityID, ...) -> ()`\nFires a signal synchronously. All callbacks are wrapped in `pcall` and are executed sequentially in the current thread.\n\n```luau\nWire.fire(MySignal, \"arg1\", \"arg2\", 123)\n```\n\n> **Recommended** for non-yielding callbacks that can error and you do not want it to stop other connections.\n\n#### `Wire.fireAsync(entityID, ...) -> ()`\nFires a signal asynchronously. Each callback runs in its own coroutine.\n\n```luau\nWire.fireAsync(MySignal, data)\n```\n\n> **Use when** callbacks may yield (e.g., contain `task.wait`, HTTP requests, etc.)\n\n#### `Wire.await(entityID) -> ...any`\nYields the current thread until the signal fires, then returns the fired arguments.\n\n```luau\nlocal damage, attacker = Wire.await(PlayerDamaged)\nprint(\"Received damage:\", damage, \"from\", attacker)\n```\n\n#### `Wire.disconnectAll(entityID) -> ()`\nDisconnects all connections from a signal. Can also serve as a signal destructor.\n\n```luau\nWire.disconnectAll(MySignal)\n```\n\n### Request Methods\n\n#### `Wire.onInvoke(entityID, callback) -> ()`\nSets or updates the callback for a request.\n\n```luau\nWire.onInvoke(GetPlayerData, function(player)\n    return database:GetAsync(player.UserId)\nend)\n```\n\n#### `Wire.invoke(entityID, ...) -> ...any`\nInvokes a request and returns the result.\n\n```luau\nlocal data = Wire.invoke(GetPlayerData, player)\n```\n\n#### `Wire.destroyRequest(entityID) -> ()`\nRemoves the request callback, freeing the reference.\n\n```luau\nWire.destroyRequest(GetPlayerData)\n```\n\n### Connection Object\n\n#### `connection:disconnect() -> ()`\nDisconnects the connection from its signal.\n\n```luau\nlocal connection = Wire.connect(MySignal, callback)\n-- Later...\nconnection:disconnect()\n```\n\n## Performance\n\nBenchmarks run with 10 connections per signal:\n\n| Operation | Wire | GoodSignal | SignalPlus | FastSignal |\n|-----------|------|------------|------------|------------|\n| Fire (100k iterations) | **0.490s** | 0.552s | 0.587s | 0.677s |\n| Disconnect (1k items) | **0.00007s** | 0.0155s | 0.00008s | 0.00009s |\n\nWire achieves the fastest fire times and the fastest disconnect times thanks to its doubly-linked list architecture (O(1) removal vs O(n) for array-based implementations).\n\n## Best Practices\n\n### Use `fire` over `fireAsync` when possible\n`fire` is significantly faster because it avoids coroutine overhead. Only use `fireAsync` when your callbacks yield.\n\n```luau\n-- ✅ Good: Non-yielding callback with fire\nWire.connect(DamageDealt, function(amount)\n    healthBar:Update(amount)\nend)\nWire.fire(DamageDealt, 50)\n\n-- ✅ Good: Yielding callback with fireAsync\nWire.connect(SaveData, function(player)\n    dataStore:SetAsync(player.UserId, getData(player))\nend)\nWire.fireAsync(SaveData, player)\n```\n\n### Handle errors in callbacks when using `fire`\nWith `fire`, an error in any callback will halt execution. Wrap risky code in `pcall`:\n\n```luau\nWire.connect(RiskySignal, function(data)\n    local success, err = pcall(function()\n        processUnsafeData(data)\n    end)\n    if not success then\n        warn(\"Handler error:\", err)\n    end\nend)\n```\n\n### Clean up connections\nAlways disconnect connections when they're no longer needed to prevent memory leaks:\n\n```luau\nlocal connections = {}\n\nfunction module:Init()\n    table.insert(connections, Wire.connect(Signal1, handler1))\n    table.insert(connections, Wire.connect(Signal2, handler2))\nend\n\nfunction module:Destroy()\n    for _, conn in connections do\n        conn:disconnect()\n    end\n    table.clear(connections)\nend\n```\n\n## License\n\nApache-2.0 — See [LICENSE](LICENSE) for details.\n\n## Links\n\n- **GitHub**: https://github.com/Elentium/Wire\n- **Wally**: `elentium/wire@0.0.4`\n","readmeTruncated":false}