{"id":"molyidev/butler","name":"butler","scope":"molyidev","platform":"roblox","description":"Memory management library.","version":"1.2.2","latest":"1.2.2","versions":["1.2.0","1.2.1","1.2.2"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"c8dd98a5473d2da339c636c1d3ad0571ca64dcb43def666b4e01324d74e6f4cc","likes":0,"downloads":0,"install":"forest install molyidev/butler","url":"https://forest.dev/p/roblox/molyidev/butler","files":"https://api.forest.dev/ai/package/roblox/molyidev/butler/files","readme":"# Butler\n\n## Installation\n\n### Pesde\n\n```bash\npesde add molyidev/butler\n```\n\n### Wally\n\n```toml\nButler = \"molyidev/butler@^1.2.2\"\n```\n\n## Why use Butler?\n\n* **Fully Typed:** Designed to work with the new Luau type solver.\n* **Performance:** Uses a **Doubly Linked List** for O(1) Removal and **LIFO** cleanup structure.\n\n## Usage\n\n### Basics\n\n```lua\nlocal Butler = require(path.to.Butler)\n\n-- Create a butler.\nlocal butler = Butler.new()\n\n-- Clean up an instance\nlocal part = Instance.new(\"Part\")\nbutler:Add(part, \"Destroy\")\n\n-- Clean up a connection\nbutler:Connect(workspace.ChildAdded, function(child)\n    print(child.Name)\nend)\n\n-- Run a function on cleanup\nbutler:Add(function()\n    print(\"Cleanup started\")\nend, true)\n\n-- Cleans everything\nbutler:Clean()\n```\n\n### Signals\n\n```lua\n-- Standard\nbutler:Connect(RunService.Heartbeat, function(dt)\n    print(\"Frame\")\nend)\n\n-- Once\nbutler:Once(humanoid.Died, function()\n    print(\"skill issue\")\nend)\n\n-- Parallel\nbutler:ConnectParallel(part.Touched, function(hit)\n    print(\"Touched in parallel\")\nend)\n\n-- Disconnects automatically when butler is cleaned\nlocal cn = butler:Connect(part.Touched, print)\n-- Or you can disconnect manually:\nbutler:Remove(cn)\n-- Maybe without cleaning (Without disconnecting)\nbutler:RemoveNoClean(cn)\n```\n\n### RenderStep\n\n```lua\n-- Binds and automatically unbinds on cleanup\nlocal bind = butler:BindToRenderStep(\"Lag\", Enum.RenderPriority.Camera.Value, function(dt)\n    -- do something unoptimized to lag the game\nend)\n\n-- You can unbind by removing it from the butler or using butler:Clean()\nbutler:Remove(bind)\n```\n\n### Instance Linking\n\n```lua\nlocal randomPart = workspace.Part\nlocal cn = butler:AttachToInstance(randomPart)\n-- If randomPart is destroyed, butler:Destroy() is called.\n\n-- You can undo this link by removing the connection:\nbutler:Remove(cn)\n```\n\n### Nesting\n\n```lua\nlocal mainButler = Butler.new()\nlocal otherButler = mainButler:Extend()\n\notherButler:Connect(workspace.ChildAdded, print)\n\n-- Cleaning 'mainButler' will also destroy 'otherButler'\nmainButler:Clean()\n```\n\n## API\n\n### Butler Static\n\n| Method | Description |\n| --- | --- |\n| `.new()` | Creates a new Butler instance. |\n| `.CleanupMethods` | An enum of valid cleanup methods: `\"Function\"`, `\"Thread\"`, `\"Disconnect\"`, `\"Destroy\"`. |\n| `.IsButler(obj)` | Returns `true` if `obj` is a Butler instance. |\n\n### Butler\n\n| Method | Description |\n| --- | --- |\n| `.CurrentlyCleaning` | `boolean` — `true` if the Butler is currently iterating through its cleanup tasks. |\n| `:Add(object, cleanupMethod?)` | Adds `object` to the cleanup list. Returns the `object`. |\n| `:Connect(signal, fn)` | Connects `fn` to `signal` and adds the connection to the Butler. Returns the `Connection`. |\n| `:ConnectParallel(signal, fn)` | Connects `fn` to `signal` in parallel and adds the connection to the Butler. Returns the `Connection`. |\n| `:Once(signal, fn)` | Connects `fn` to `signal` once. The connection is automatically removed from the Butler when fired. Returns the `Connection` |\n| `:BindToRenderStep(name, priority, fn)` | Wraps `RunService:BindToRenderStep`. Returns the unbinding function. |\n| `:Extend()` | Creates and returns a new \"child\" Butler. If the parent is cleaned/destroyed, the child is destroyed too. |\n| `:AttachToInstance(instance)` | Listens for `instance.Destroying` and calls `:Destroy()` on the Butler automatically. Returns the `Connection`. |\n| `:Remove(object)` | Removes `object` from the Butler and **immediately** cleans it (calls Destroy/Disconnect etc). Returns itself. |\n| `:RemoveNoClean(object)` | Removes `object` from the Butler **without** cleaning it. Returns the `Butler` itself. |\n| `:RemoveList(...objects)` | Calls `:Remove()` on all provided objects. Returns the `Butler` itself. |\n| `:RemoveListNoClean(...objects)` | Calls `:RemoveNoClean()` on all provided objects. Returns the `Butler` itself. |\n| `:Clean()` | Cleans all added objects in order. Returns the `Butler` itself. |\n| `:Destroy()` | Calls `:Clean()` and renders the Butler unusable. |\n\n## Inspiration\n\n**Butler** takes inspiration from **[Trove](https://github.com/Sleitnick/RbxUtil/tree/main/modules/trove)** and **[Janitor](https://github.com/howmanysmall/Janitor)**.\nIf you do not want to use **Butler** and would prefer another option, I highly recommend either of them. However, if I had to choose between the two, I would recommend **Trove**.\n","readmeTruncated":false}