import { NetGlobalMiddleware } from "../middleware" ; import { $dbg , $nameof , $print } from "rbxts-transform-debug" ; import ServerAsyncFunction from "../server/ServerAsyncFunction" ; import ServerEvent from "../server/ServerEvent" ; import ServerFunction from "../server/ServerFunction" ; import { AsyncServerFunctionDeclaration , BidirectionalEventDeclaration , ClientToServerEventDeclaration , DeclarationsOf , FilterDeclarations , FilterGroups , NamespaceDeclaration , InferGroupDeclaration , InferServerCallback , InferServerConnect , InferServerRemote , RemoteDeclarations , DeclarationLike , } from "./Types" ; import { TagId } from "../internal" ; import { InferDefinition } from "./NamespaceBuilder" ; const CollectionService = game . GetService ( "CollectionService" ) ; type ServerEventDeclarationKeys < T extends RemoteDeclarations > = keyof DeclarationsOf < FilterDeclarations < T > , ClientToServerEventDeclaration < any > | BidirectionalEventDeclaration < any , any > > & string ; type ServerEventConnectFunction < T extends RemoteDeclarations , K extends keyof T > = InferServerConnect < Extract < T [ K ] , ClientToServerEventDeclaration < any > | BidirectionalEventDeclaration < any , any > > > ; type ServerFunctionDeclarationKeys < T extends RemoteDeclarations > = keyof DeclarationsOf < FilterDeclarations < T > , AsyncServerFunctionDeclaration < any , any > > & string ; type ServerFunctionCallbackFunction < T extends RemoteDeclarations , K extends keyof T > = InferServerCallback < Extract < T [ K ] , AsyncServerFunctionDeclaration < any , any > > > ; const declarationMap = new WeakMap < ServerDefinitionBuilder < RemoteDeclarations > , RemoteDeclarations > ( ) ; const remoteEventCache = new Map < string , ServerEvent > ( ) ; const remoteAsyncFunctionCache = new Map < string , ServerAsyncFunction > ( ) ; const remoteFunctionCache = new Map < string , ServerFunction > ( ) ; export class ServerDefinitionBuilder < T extends RemoteDeclarations > { public constructor ( declarations , private globalMiddleware ? , private namespace = "" ) { declarationMap . set ( this , declarations ) ; $dbg ( declarations , ( value , source ) => { print ( `[${ source . file }:${ source . lineNumber }]` , "== Server Declarations ==" ) ; for ( const [ name , va ] of pairs ( value ) ) { print ( `[${ source . file }:${ source . lineNumber }]` , name , va . Type ) ; } } ) ; } internal public toString ( ) { return `[${ $nameof ( ServerDefinitionBuilder ) }]` ; } param name param fn public OnEvent < K extends ServerEventDeclarationKeys < T > > ( name , fn ) { const result = this . Create ( name ) as InferServerRemote < ClientToServerEventDeclaration < any > | BidirectionalEventDeclaration < any , any > > ; result . Connect ( fn ) ; } param groupId public GetNamespace < K extends keyof FilterGroups < T > & string > ( groupId ) { const group = declarationMap . get ( this ) ! [ groupId ] as NamespaceDeclaration < RemoteDeclarations > ; assert ( group . Type === "Namespace" ) ; $print ( `Fetch Group` , groupId ) ; return group . Definitions . _buildServerDefinition ( this . globalMiddleware , this . namespace !== "" ? [ this . namespace , groupId ] . join ( ":" ) : groupId ) ; } param remoteId public Create < K extends keyof FilterDeclarations < T > & string > ( remoteId ) { const item = declarationMap . get ( this ) ! [ remoteId ] ; remoteId = this . namespace !== "" ? ( [ this . namespace , remoteId ] . join ( ":" ) as K ) : remoteId ; assert ( item && item . Type , `'${ remoteId }' is not defined in this definition.` ) ; if ( item . Type === "Function" ) { let func ; if ( remoteFunctionCache . has ( remoteId ) ) { $print ( `Fetch cached copy of ${ remoteId }` ) ; return remoteFunctionCache . get ( remoteId ) ! as InferServerRemote < T [ K ] > ; } else { if ( item . ServerMiddleware ) { func = new ServerFunction ( remoteId , item . ServerMiddleware ) ; } else { func = new ServerFunction ( remoteId ) ; } CollectionService . AddTag ( func . GetInstance ( ) , TagId . DefinitionManaged ) ; remoteFunctionCache . set ( remoteId , func ) ; } this . globalMiddleware ?. forEach ( ( mw ) => func . _use ( mw ) ) ; return func as InferServerRemote < T [ K ] > ; } else if ( item . Type === "AsyncFunction" ) { let asyncFunction ; if ( remoteAsyncFunctionCache . has ( remoteId ) ) { $print ( `Fetch cached copy of ${ remoteId }` ) ; return remoteAsyncFunctionCache . get ( remoteId ) ! as InferServerRemote < T [ K ] > ; } else { if ( item . ServerMiddleware ) { asyncFunction = new ServerAsyncFunction ( remoteId , item . ServerMiddleware ) ; } else { asyncFunction = new ServerAsyncFunction ( remoteId ) ; } CollectionService . AddTag ( asyncFunction . GetInstance ( ) , TagId . DefinitionManaged ) ; remoteAsyncFunctionCache . set ( remoteId , asyncFunction ) ; } this . globalMiddleware ?. forEach ( ( mw ) => asyncFunction . _use ( mw ) ) ; return asyncFunction as InferServerRemote < T [ K ] > ; } else if ( item . Type === "Event" ) { let event ; if ( remoteEventCache . has ( remoteId ) ) { $print ( `Fetch cached copy of ${ remoteId }` ) ; return remoteEventCache . get ( remoteId ) ! as InferServerRemote < T [ K ] > ; } else { if ( item . ServerMiddleware ) { event = new ServerEvent ( remoteId , item . ServerMiddleware ) ; } else { event = new ServerEvent ( remoteId ) ; } CollectionService . AddTag ( event . GetInstance ( ) , TagId . DefinitionManaged ) ; remoteEventCache . set ( remoteId , event ) ; } this . globalMiddleware ?. forEach ( ( mw ) => event . _use ( mw ) ) ; return event as InferServerRemote < T [ K ] > ; } throw `Invalid Type` ; } param name param fn public OnFunction < K extends ServerFunctionDeclarationKeys < T > > ( name , fn ) { const result = this . Create ( name ) as InferServerRemote < AsyncServerFunctionDeclaration < any , any > > ; result . SetCallback ( fn ) ; } }