diff --git a/README.md b/README.md index cf8f3fc..be040a6 100644 --- a/README.md +++ b/README.md @@ -162,15 +162,15 @@ In Luau, for full type-checking in your editor, you will need to define a separa - `ServerToClient`: A remote event that is fired by the server and processed by the client. -- `ClientToServerAsync`: A remote function that is invoked by the client and processed by the server. +- `ServerAsync`: A remote function that is invoked by the client and processed by the server. -- ~~`ServerToClientAsync`~~: A remote function that is invoked by the server and processed by the client. Not recommended, as requesting values from the client is unsafe. +- ~~`ClientAsync`~~: A remote function that is invoked by the server and processed by the client. Not recommended, as requesting values from the client is unsafe. ```lua type Remotes = { client: Remo.ServerToClient, server: Remo.ClientToServer, - serverAsync: Remo.ClientToServerAsync, + serverAsync: Remo.ServerAsync<(number), (string)>, namespace: { client: Remo.ServerToClient, server: Remo.ClientToServer, diff --git a/src/Promise.lua b/src/Promise.lua index e880e93..6002132 100644 --- a/src/Promise.lua +++ b/src/Promise.lua @@ -1,4 +1,3 @@ ---!nonstrict local ReplicatedStorage = game:GetService("ReplicatedStorage") local include = script:FindFirstAncestor("rbxts_include") @@ -54,22 +53,22 @@ export type _Promise = { now: (self: _Promise, rejectionValue: unknown) -> _Promise, } -export type Promise = { - timeout: (self: Promise, seconds: number, rejectionValue: unknown) -> Promise, - getStatus: (self: Promise) -> PromiseStatus, - andThen: (self: Promise, successHandler: (T) -> (), failureHandler: ((...any) -> ())?) -> _Promise, - catch: (self: Promise, failureHandler: (any) -> ()) -> Promise, - tap: (self: Promise, successHandler: (T) -> ()) -> Promise, - andThenCall: (self: Promise, successHandler: (U...) -> (), U...) -> Promise, - andThenReturn: (self: Promise, value: any) -> _Promise, - cancel: (self: Promise) -> (), - finally: (self: Promise, callback: (status: PromiseStatus) -> ()) -> _Promise, - finallyCall: (self: Promise, callback: (U...) -> (), U...) -> _Promise, - finallyReturn: (self: Promise, value: any) -> _Promise, - awaitStatus: (self: Promise) -> (PromiseStatus, T), - await: (self: Promise) -> (boolean, T | unknown), - expect: (self: Promise) -> T, - now: (self: Promise, rejectionValue: unknown) -> Promise, +export type Promise = { + timeout: (self: Promise, seconds: number, rejectionValue: unknown) -> Promise, + getStatus: (self: Promise) -> PromiseStatus, + andThen: (self: Promise, successHandler: (T...) -> (), failureHandler: ((...any) -> ())?) -> _Promise, + catch: (self: Promise, failureHandler: (any) -> ()) -> Promise, + tap: (self: Promise, successHandler: (T...) -> ()) -> Promise, + andThenCall: (self: Promise, successHandler: (U...) -> (), U...) -> Promise, + andThenReturn: (self: Promise, value: any) -> _Promise, + cancel: (self: Promise) -> (), + finally: (self: Promise, callback: (status: PromiseStatus) -> ()) -> _Promise, + finallyCall: (self: Promise, callback: (U...) -> (), U...) -> _Promise, + finallyReturn: (self: Promise, value: any) -> _Promise, + awaitStatus: (self: Promise) -> (PromiseStatus, T...), + await: (self: Promise) -> (boolean, T...), + expect: (self: Promise) -> T..., + now: (self: Promise, rejectionValue: unknown) -> Promise, } if include and include:FindFirstChild("Promise") then diff --git a/src/client/createAsyncRemote.lua b/src/client/createAsyncRemote.lua index 0ce0dfa..2f8010e 100644 --- a/src/client/createAsyncRemote.lua +++ b/src/client/createAsyncRemote.lua @@ -41,7 +41,7 @@ local function createAsyncRemote(name: string, builder: types.RemoteBuilder): ty end end - local asyncRemoteNotCallable: types.AsyncRemoteNotCallable = { + local api: types.AsyncRemoteApi = { name = name, type = "function" :: "function", onRequest = onRequest, @@ -49,7 +49,7 @@ local function createAsyncRemote(name: string, builder: types.RemoteBuilder): ty destroy = destroy, } - local asyncRemote = setmetatable(asyncRemoteNotCallable, { + local asyncRemote = setmetatable(api, { __call = request, }) :: types.AsyncRemote diff --git a/src/createRemotes.spec.lua b/src/createRemotes.spec.lua index eb39d7a..6597a7c 100644 --- a/src/createRemotes.spec.lua +++ b/src/createRemotes.spec.lua @@ -7,12 +7,13 @@ return function() local builder = require(script.Parent.builder) local mockRemotes = require(script.Parent.utils.mockRemotes) + -- TODO: remove 'nil' from type packs local remotes: types.Remotes<{ event: types.ClientToServer, - callback: types.ClientToServerAsync, + callback: types.ServerAsync<(string, number), (string, nil)>, namespace: { event: types.ClientToServer, - callback: types.ClientToServerAsync, + callback: types.ServerAsync<(string, number), (string, nil)>, }, }> diff --git a/src/init.lua b/src/init.lua index ee6878a..667b4ea 100644 --- a/src/init.lua +++ b/src/init.lua @@ -1,3 +1,4 @@ +local Promise = require(script.Promise) local types = require(script.types) local createRemotes = require(script.createRemotes) local builder = require(script.builder) @@ -5,12 +6,10 @@ local getSender = require(script.getSender) local loggerMiddleware = require(script.middleware.loggerMiddleware) local throttleMiddleware = require(script.middleware.throttleMiddleware) -export type Promise = types.Promise -export type PromiseConstructor = types.PromiseConstructor -export type Validator = types.Validator +export type Promise = Promise.Promise +export type PromiseConstructor = Promise.PromiseConstructor export type Middleware = types.Middleware -export type MiddlewareContext = types.MiddlewareContext export type RemoteBuilder = types.RemoteBuilder export type RemoteBuilderMetadata = types.RemoteBuilderMetadata @@ -24,9 +23,15 @@ export type Remote = types.Remote export type ClientToServer = types.ClientToServer export type ServerToClient = types.ServerToClient -export type AsyncRemote = types.AsyncRemote -export type ClientToServerAsync = types.ClientToServerAsync -export type ServerToClientAsync = types.ServerToClientAsync +export type AsyncRemote = types.AsyncRemote +export type ServerAsync = types.ServerAsync +export type ClientAsync = types.ClientAsync + +--- TODO: remove 'nil' from type packs +--- @deprecated 1.2, use `ServerAsync` instead. +export type ClientToServerAsync = types.ServerAsync +--- @deprecated 1.2, use `ClientAsync` instead. +export type ServerToClientAsync = types.ClientAsync return { remote = builder.remote, diff --git a/src/middleware/throttleMiddleware.spec.lua b/src/middleware/throttleMiddleware.spec.lua index 0c5e054..07dc043 100644 --- a/src/middleware/throttleMiddleware.spec.lua +++ b/src/middleware/throttleMiddleware.spec.lua @@ -24,7 +24,7 @@ return function() end describe("event throttle", function() - local remotes, remote: types.ServerToClient, instance: RemoteEvent + local remotes, remote: types.ClientToServer, instance: RemoteEvent local function create(options: throttleMiddleware.ThrottleMiddlewareOptions) remotes = createRemotes({ remote = builder.remote() }, throttleMiddleware(options)) @@ -144,7 +144,7 @@ return function() end) describe("async throttle", function() - local remotes, remote: types.ServerToClientAsync, instance: RemoteFunction + local remotes, remote: types.ServerAsync, instance: RemoteFunction local function create(options: throttleMiddleware.ThrottleMiddlewareOptions) remotes = createRemotes({ remote = builder.remote().returns() }, throttleMiddleware(options)) diff --git a/src/server/createAsyncRemote.lua b/src/server/createAsyncRemote.lua index 45ff21a..911f533 100644 --- a/src/server/createAsyncRemote.lua +++ b/src/server/createAsyncRemote.lua @@ -11,7 +11,7 @@ local function createAsyncRemote(name: string, builder: types.RemoteBuilder): ty local instance = instances.createRemoteFunction(name) local connected = true - local function handler(...): any + local function handler(...): ...any return end @@ -43,7 +43,7 @@ local function createAsyncRemote(name: string, builder: types.RemoteBuilder): ty end end - local asyncRemoteNotCallable: types.AsyncRemoteNotCallable = { + local api: types.AsyncRemoteApi = { name = name, type = "function" :: "function", onRequest = onRequest, @@ -51,7 +51,7 @@ local function createAsyncRemote(name: string, builder: types.RemoteBuilder): ty destroy = destroy, } - local asyncRemote = setmetatable(asyncRemoteNotCallable, { + local asyncRemote = setmetatable(api, { __call = request, }) :: types.AsyncRemote diff --git a/src/types.lua b/src/types.lua index cb7e75f..96f33f4 100644 --- a/src/types.lua +++ b/src/types.lua @@ -1,19 +1,13 @@ local Promise = require(script.Parent.Promise) -export type Promise = Promise.Promise +type Cleanup = () -> () -export type PromiseConstructor = Promise.PromiseConstructor +type Promise = Promise.Promise export type Validator = any -export type Cleanup = () -> () - export type Middleware = (next: (...any) -> ...any, remote: AnyRemote) -> (...any) -> ...any -export type MiddlewareContext = { - player: Player, -} - export type RemoteBuilder = { type: RemoteType, metadata: RemoteBuilderMetadata, @@ -42,6 +36,14 @@ export type AnyRemote = Remote | AsyncRemote export type Remote = ClientToServer & ServerToClient +export type Remotes = Map & { + destroy: (self: Remotes) -> (), +} + +export type RemoteMap = { + [string]: AnyRemote | RemoteMap, +} + export type ClientToServer = { name: string, type: "event", @@ -61,50 +63,42 @@ export type ServerToClient = { destroy: (self: ServerToClient) -> (), } -export type AsyncRemote = - ClientToServerAsync - & ServerToClientAsync +export type AsyncRemote = + ServerAsync + & ClientAsync -export type ServerToClientAsync = - ((player: Player, Args...) -> Promise) - & ServerToClientAsyncNotCallable +export type ServerAsync = + ((Args...) -> Promise) + & ServerAsyncApi -export type ClientToServerAsync = - ((Args...) -> Promise) - & ClientToServerAsyncNotCallable +export type ClientAsync = + ((player: Player, Args...) -> Promise) + & ClientAsyncApi -export type AsyncRemoteNotCallable = - ServerToClientAsyncNotCallable - & ClientToServerAsyncNotCallable +export type AsyncRemoteApi = + ServerAsyncApi + & ClientAsyncApi -type ServerToClientAsyncNotCallable = { +export type ServerAsyncApi = { name: string, type: "function", onRequest: ( - self: ServerToClientAsyncNotCallable, - callback: (Args...) -> Returns | Promise + self: ServerAsyncApi, + callback: ((player: Player, Args...) -> Returns...) | (player: Player, Args...) -> Promise ) -> (), - request: (self: ServerToClientAsyncNotCallable, player: Player, Args...) -> Promise, - destroy: (self: ServerToClientAsyncNotCallable) -> (), + request: (self: ServerAsyncApi, Args...) -> Promise, + destroy: (self: ServerAsyncApi) -> (), } -type ClientToServerAsyncNotCallable = { +export type ClientAsyncApi = { name: string, type: "function", onRequest: ( - self: ClientToServerAsyncNotCallable, - callback: (player: Player, Args...) -> Returns | Promise + self: ClientAsyncApi, + callback: ((Args...) -> Returns...) | (Args...) -> Promise ) -> (), - request: (self: ClientToServerAsyncNotCallable, Args...) -> Promise, - destroy: (self: ClientToServerAsyncNotCallable) -> (), -} - -export type Remotes = Map & { - destroy: (self: Remotes) -> (), -} - -export type RemoteMap = { - [string]: AnyRemote | RemoteMap, + request: (self: ClientAsyncApi, Args...) -> Promise, + destroy: (self: ClientAsyncApi) -> (), } return nil