{"id":"fewkz/fluf","name":"fluf","scope":"fewkz","platform":"roblox","description":"Lightweight service framework for Roblox games","version":"0.1.1","latest":"0.1.1","versions":["0.1.0","0.1.1"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"2c2c6a8149e24a2c97b344f4cdfd60d3692941ed555d925d13b157aa7a2d0854","likes":0,"downloads":0,"install":"forest install fewkz/fluf","url":"https://forest.dev/p/roblox/fewkz/fluf","files":"https://api.forest.dev/ai/package/roblox/fewkz/fluf/files","readme":"# fluf\nfluf is a lightweight service framework for managing services and their communication.\n\n## Adding fluf\nYou can download the latest release of fluf as a rbxm file from https://github.com/fewkz/fluf/releases.\n\nfluf can be added to your project via [Wally](https://wally.run/) by adding this line under dependencies.\n```toml\nfluf = \"fewkz/fluf@0.1.1\"\n```\n\n## How to use\n\nIn fluf, a service is any `LocalScript` or `Script`. fluf provides a\n`onDisabled` \"hook\" that can be used to run code when a service script is disabled.\n```lua\n-- MyService.server.lua\nprint(\"Service started up\")\nfluf.onDisabled(script, function()\n    print(\"Service is stopped\")\nend)\n```\n\nIn order for `onDisabled` to work, you must register a \"hook worker\" that will process these hooks in another script.\n```lua\nlocal fluf = require(path.to.fluf)\nfluf.registerHookWorker()\n```\n\nfluf provides ways to communicate with services via \"interfaces\"\nAn interface is a `ModuleScript` that returns a table of fluf events or state.\n```lua\n-- Services/BaseplateInterface.lua\nlocal fluf = require(path.to.fluf)\nlocal BaseplateInterface = {\n    changeColor = fluf.event() :: fluf.Event<Color3>,\n    instance = fluf.state() :: fluf.State<Part>,\n}\nreturn BaseplateInterface\n\n-- Services/Baseplate.server.lua\nlocal fluf = require(path.to.fluf)\nlocal BaseplateInterface = require(path.to.BaseplateInterface)\n\nlocal baseplate = Instance.new(\"Part\")\nbaseplate.Parent = workspace\n\nBaseplateInterface.instance.set(baseplate)\nBaseplateInterface.changeColor.connect(function(newColor)\n    baseplate.Color = newColor\nend)\n\nfluf.onDisabled(script, function()\n    baseplate:Destroy()\n    BaseplateInterface.instance.set(nil)\nend)\n-- some other script\nlocal BaseplateInterface = require(path.to.BaseplateInterface)\nBaseplateInterface.fire(Color3.new(1, 0, 0))\nprint(\"The baseplate's part is\", BaseplateInterface.instance.get())\n```\nfluf events and state can be optionally typed, which will have luau typecheck it's usage.\n\nfluf events are intended to always be used from outside the service, and fluf state\nis intended to only be set by the service. However, this isn't enforced and there may\nbe cases where it is useful for the service to fire an event or for an outside code to set a service's state.\n\n## Why scripts?\nBy having every service be a script, there are a variety of benefits.\n- Scripts can have side effects that will safely be cleaned up when the script is disabled.\nSince the script can't be required, you won't cause undesirable side effects when requiring a module.\n- When a script is disabled, every thread or connection made in the script will be cancelled or disconnected.\nThis means you don't have to write tedious cleanup methods for your services.\n- Starting a script by enabling it or parenting it never yields the code that started it.\nThis optimally schedules your services, ensuring they don't block the rest of your code.\n- Scripts can't be required, which means you have to structure the communication between services\nin a way that can't cause cyclic dependencies.\n\n## Parallelization\nfluf is designed to allow communication between services to work across actors. Events created by fluf will be the same across actors, and state will replicate across actors.\n\nHook workers will not work across actors, so you must register a hook worker in every actor.\n","readmeTruncated":false}