feat core

- server/client middlewares
This commit is contained in:
Danya H 2024-10-29 17:03:07 +00:00
parent d8df9fa7ef
commit 622676d189
13 changed files with 193 additions and 10 deletions

View File

@ -1,7 +1,6 @@
import { Rpc } from '@entityseven/rage-fw-rpc' import { Rpc } from '@entityseven/rage-fw-rpc'
export const rpc = new Rpc({ export const rpc = new Rpc({
forceBrowserDevMode: forceBrowserDevMode: process.env.RageFW_forceBrowserDevMode === 'true',
process.env.RageFW_forceBrowserDevMode === 'true' ?? false,
debugLogs: false, debugLogs: false,
}) })

View File

@ -1,16 +1,24 @@
import { rpc } from './rpc' import { rpc } from './rpc'
import { Middleware } from './middleware'
import type * as T from '../types' import type * as T from '../types'
export class Client { export class Client {
public register<EventName extends T.RageFW_ClientEvent>( public register<EventName extends T.RageFW_ClientEvent>(
eventName: EventName, eventName: EventName,
callback: T.RageFW_ClientCallback<EventName>, callback: T.RageFW_ClientCallback<EventName>,
options?: {
middlewares?: T.RageFW_MiddlewareOptions<EventName>
},
): Client { ): Client {
rpc.register< rpc.register<
Parameters<typeof callback>, Parameters<typeof callback>,
ReturnType<typeof callback>, ReturnType<typeof callback> | Promise<unknown>,
EventName EventName
>(eventName, async (...data) => await callback(...data)) >(eventName, async (...data) => {
if (!options?.middlewares) return await callback(...data)
await Middleware.process(options.middlewares, callback, data)
})
return this return this
} }

View File

@ -1,4 +1,5 @@
export * from './client' export * from './client'
export * from './logger' export * from './logger'
export * from './middleware'
export * from './player' export * from './player'
export * from './rpc' export * from './rpc'

View File

@ -0,0 +1,54 @@
import type * as T from '../types'
export class Middleware {
constructor() {}
private static async execute<EventName extends T.RageFW_ClientEvent>(
middlewares: T.RageFW_MiddlewareFunction<EventName>[],
args: T.RageFW_ClientArgs<EventName>,
): Promise<T.RageFW_MiddlewareResponseInternal> {
for (let i = 0; i < middlewares.length; i++) {
const result = await middlewares[i](...args)
if (typeof result === 'boolean' && !result)
return { success: result, id: i }
if (typeof result !== 'boolean' && !result.success)
return { ...result, id: i }
}
return {
success: true,
}
}
public static async process<EventName extends T.RageFW_ClientEvent>(
middlewareOptions: T.RageFW_MiddlewareOptions<EventName>,
callback: T.RageFW_ClientCallback<EventName>,
args: T.RageFW_ClientArgs<EventName>,
) {
if (Array.isArray(middlewareOptions)) {
const middlewaresResponse = await Middleware.execute(
middlewareOptions,
args,
)
if (middlewaresResponse.success) return await callback(...args)
} else {
const middlewaresResponse = await Middleware.execute(
middlewareOptions.executables,
args,
)
if (middlewaresResponse.success) {
return await callback(...args)
} else {
middlewareOptions.onError(
middlewaresResponse.message ??
'Middleware with id ' +
middlewaresResponse.id +
' failed',
)
}
}
}
}

View File

@ -1,5 +1,7 @@
import { Client, Logger, Player, rpc } from './core' import { Client, Logger, Player, rpc } from './core'
export type { RageFW_MiddlewareFunction } from './types'
export const fw = { export const fw = {
event: new Client(), event: new Client(),
player: new Player(), player: new Player(),

View File

@ -1,3 +1,4 @@
export * from './client'
export * from './server'
export * from './browser' export * from './browser'
export * from './client'
export * from './middleware'
export * from './server'

View File

@ -0,0 +1,26 @@
import type * as T from './client'
export type RageFW_MiddlewareResponse =
| {
success: boolean
message?: string
}
| boolean
export type RageFW_MiddlewareResponseInternal = {
success: boolean
message?: string
id?: number
}
export type RageFW_MiddlewareFunction<EventName extends T.RageFW_ClientEvent> =
(
...args: T.RageFW_ClientArgs<EventName>
) => Promise<RageFW_MiddlewareResponse>
export type RageFW_MiddlewareOptions<EventName extends T.RageFW_ClientEvent> =
| RageFW_MiddlewareFunction<EventName>[]
| {
executables: RageFW_MiddlewareFunction<EventName>[]
onError: (error: string) => unknown
}

View File

@ -1,4 +1,5 @@
export * from './logger' export * from './logger'
export * from './middleware'
export * from './player' export * from './player'
export * from './rpc' export * from './rpc'
export * from './server' export * from './server'

View File

@ -0,0 +1,54 @@
import type * as T from '../types'
export class Middleware {
constructor() {}
private static async execute<EventName extends T.RageFW_ServerEvent>(
middlewares: T.RageFW_MiddlewareFunction<EventName>[],
args: T.RageFW_ServerArgs<EventName>,
): Promise<T.RageFW_MiddlewareResponseInternal> {
for (let i = 0; i < middlewares.length; i++) {
const result = await middlewares[i](...args)
if (typeof result === 'boolean' && !result)
return { success: result, id: i }
if (typeof result !== 'boolean' && !result.success)
return { ...result, id: i }
}
return {
success: true,
}
}
public static async process<EventName extends T.RageFW_ServerEvent>(
middlewareOptions: T.RageFW_MiddlewareOptions<EventName>,
callback: T.RageFW_ServerCallback<EventName>,
args: T.RageFW_ServerArgs<EventName>,
) {
if (Array.isArray(middlewareOptions)) {
const middlewaresResponse = await Middleware.execute(
middlewareOptions,
args,
)
if (middlewaresResponse.success) return await callback(...args)
} else {
const middlewaresResponse = await Middleware.execute(
middlewareOptions.executables,
args,
)
if (middlewaresResponse.success) {
return await callback(...args)
} else {
middlewareOptions.onError(
middlewaresResponse.message ??
'Middleware with id ' +
middlewaresResponse.id +
' failed',
)
}
}
}
}

View File

@ -1,16 +1,24 @@
import { rpc } from './rpc' import { rpc } from './rpc'
import { Middleware } from './middleware'
import type * as T from '../types' import type * as T from '../types'
export class Server { export class Server {
public register<EventName extends T.RageFW_ServerEvent>( public register<EventName extends T.RageFW_ServerEvent>(
eventName: EventName, eventName: EventName,
callback: T.RageFW_ServerCallback<EventName>, callback: T.RageFW_ServerCallback<EventName>,
options?: {
middlewares?: T.RageFW_MiddlewareOptions<EventName>
},
): Server { ): Server {
rpc.register< rpc.register<
Parameters<typeof callback>, Parameters<typeof callback>,
ReturnType<typeof callback>, ReturnType<typeof callback> | Promise<unknown>,
EventName EventName
>(eventName, async (...data) => await callback(...data)) >(eventName, async (...data) => {
if (!options?.middlewares) return await callback(...data)
await Middleware.process(options.middlewares, callback, data)
})
return this return this
} }

View File

@ -1,5 +1,7 @@
import { Logger, Player, Server, rpc } from './core' import { Logger, Player, Server, rpc } from './core'
export type { RageFW_MiddlewareFunction } from './types'
export const fw = { export const fw = {
event: new Server(), event: new Server(),
player: new Player(), player: new Player(),

View File

@ -1,3 +1,4 @@
export * from './client'
export * from './server'
export * from './browser' export * from './browser'
export * from './client'
export * from './middleware'
export * from './server'

View File

@ -0,0 +1,26 @@
import type * as T from './server'
export type RageFW_MiddlewareResponse =
| {
success: boolean
message?: string
}
| boolean
export type RageFW_MiddlewareResponseInternal = {
success: boolean
message?: string
id?: number
}
export type RageFW_MiddlewareFunction<EventName extends T.RageFW_ServerEvent> =
(
...args: T.RageFW_ServerArgs<EventName>
) => Promise<RageFW_MiddlewareResponse>
export type RageFW_MiddlewareOptions<EventName extends T.RageFW_ServerEvent> =
| RageFW_MiddlewareFunction<EventName>[]
| {
executables: RageFW_MiddlewareFunction<EventName>[]
onError: (error: string) => unknown
}