@rbxts/flamework-gateways-mod

A class-based Flamework networking mod

Usage no npm install needed!

<script type="module">
  import rbxtsFlameworkGatewaysMod from 'https://cdn.skypack.dev/@rbxts/flamework-gateways-mod';
</script>

README

πŸŒ‰flamework-gateways-modπŸŒ‰

A Flamework networking mod

✨ Featuring

πŸŒ‰ Gateways - Handle remote events and functions with classes

πŸ›‘οΈ Guards - Block certain requests before they are processed

πŸ“ž Pipes - Transform and validate parameters passed to requests

🌻 Motivation

This is mainly a personal project to handle remotes with classes and decorators.

πŸ”Œ Installation

npm install @flamework/core@modding
npm install -D rbxts-transformer-flamework@modding
npm install @rbxts/flamework-gateways-mod

πŸ“š Examples

πŸ—‚οΈ Client-server connection

connectServer and connectClient should be called before igniting Flamework.

Do note that guards & pipes will not be applied to external listeners like .on, .wait, etc.!

type ServerGateway = OneGateway & AnotherGateway;

const server = connectServer<ServerGateway, ClientGateway>();

server.emit("clientEvent", players, ...args);
server.broadcast("clientEvent", ...args);
type ClientGateway = OneGateway & AnotherGateway;

const client = connectClient<ServerGateway, ClientGateway>();

client.emit("serverEvent", ...args);
client.request("serverInvoke", ...args);

πŸŒ‰ Gateway

Gateways should be added to Flamework.addPaths()

@Gateway({
  guards: [new AdminGuard(["littensy"])],
})
class AdminGateway {
  constructor(private readonly adminService: AdminService) {}

  @OnEvent()
  @UseGuards(CommandDebounceGuard)
  @UsePipes([], CommandPipe)
  async processCommand(player: Player, message: string | Array<string>) {
    this.adminService.runCommand(player, message as Array<string>);
  }

  @OnInvoke()
  async getCommands() {
    return this.adminService.getCommands();
  }
}

πŸ›‘οΈ Guard

Creatable guards

class AdminGuard implements CanActivate {
  constructor(private readonly admins: Array<string>) {}

  canActivate(context: ExecutionContext) {
    return this.admins.includes(context.getPlayer().Name);
  }
}

Singleton guards should be added to Flamework.addPaths()

@Guard()
class CommandDebounceGuard implements CanActivate {
  constructor(private readonly roduxService: RoduxService) {}

  canActivate(context: ExecutionContext) {
    const state = this.roduxService.getState();
    return time() >= state.commandDebounce;
  }
}

πŸ“ž Pipe

Creatable pipe

class CommandPipe implements PipeTransform {
  transform(value: unknown) {
    assert(typeIs(value, "string"), "(CommandPipe) Value must be a string");
    return value.split(" ");
  }
}

Singleton pipes should be added to Flamework.addPaths()

⚠️ Limitations

❌ Client-side RemoteFunctions are not supported

  • It is difficult to safely determine whether a client remote is a function or an event from the server.

❌ Some type limitations

  • Pipe transformation input/output is not type checked, use Input | Output in the parameter type to keep track (see examples).