{"id":"moxxum/netkit","name":"netkit","scope":"moxxum","platform":"roblox","description":"Typed remote definitions with server-side rate limiting, payload validation, and middleware","version":"0.1.0","latest":"0.1.0","versions":["0.1.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":["The package archive does not include its license text; the license is declared in its manifest metadata."],"licenseVerified":false,"dependencies":{},"integrity":"bdd606917a28f636dfde1a48e849f410c44aea4ed5d9e85f19cefcef43e91178","likes":0,"downloads":0,"install":"forest install moxxum/netkit","url":"https://forest.dev/p/roblox/moxxum/netkit","files":"https://api.forest.dev/ai/package/roblox/moxxum/netkit/files","readme":"# netkit\n\nThe only way remotes are created. One shared module defines every remote; netkit\ncreates them on the server, resolves them on the client, and guards every incoming\nserver call with rate limiting → middleware → payload validation before the handler\nruns. **Nothing in any game creates a raw RemoteEvent.**\n\nShared realm: `NetKit = \"moxxum/netkit@0.1.0\"` under `[dependencies]`.\n\n## API\n\n```lua\nNetKit.Event({ Rate = 10?, Validate = fn? })     -- definition marker\nNetKit.Function({ Rate = 10?, Validate = fn? })  -- definition marker\nNetKit.Define(defs)      -- server: creates remotes; client: waits for them (30s)\nNetKit.Use(middleware)   -- (remoteName, player, packedArgs) -> boolean; false blocks\nNetKit.OnBlocked(cb)     -- (player, remoteName, \"rate\"|\"validate\"|\"middleware\")\n```\n\nPer-remote `Rate` is requests/second per player (token bucket, default 10).\n`Validate` receives the unpacked payload and must return `true` or the call drops.\n\nServer event wrapper: `:Connect(handler)`, `:Fire(player, ...)`, `:FireAll(...)`,\n`:FireExcept(player, ...)`. Client event wrapper: `:Fire(...)`, `:Connect(handler)`.\nFunction wrapper: server `:SetCallback(handler)`, client `:Invoke(...)` (returns nil\nwhen blocked).\n\n## Example\n\n```lua\n-- ReplicatedStorage/Shared/Remotes.luau (required by BOTH server and client)\nlocal NetKit = require(ReplicatedStorage.Packages.NetKit)\nreturn NetKit.Define({\n\tBuyItem = NetKit.Event({\n\t\tRate = 5,\n\t\tValidate = function(itemId)\n\t\t\treturn type(itemId) == \"string\"\n\t\tend,\n\t}),\n})\n\n-- server\nlocal Remotes = require(ReplicatedStorage.Shared.Remotes)\nRemotes.BuyItem:Connect(function(player, itemId)\n\t-- itemId is guaranteed to be a string and inside the rate budget\nend)\n\n-- client\nlocal Remotes = require(ReplicatedStorage.Shared.Remotes)\nRemotes.BuyItem:Fire(\"sword\")\n```\n\nThe server must require the defs module during bootstrap so remotes exist before\nclients ask for them. Wire `guard`'s flood detection with\n`NetKit.Use(Guard.NetMiddleware())`.\n\n## Test\n\n`rojo build test.project.json -o test.rbxl`, open in Studio, Play Solo. Client output\nshows pass lines; server output shows echoes plus rate/validate blocks.\n","readmeTruncated":false}