lenix 1.7.24 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client/_init.ts CHANGED
@@ -1,6 +1,58 @@
1
+ import { asserts, JsonValue } from '@lenix/lenix'
1
2
  import type { Request } from '../shared/types.ts'
2
3
  import { onNui } from './nui.ts'
3
4
 
5
+ type Resolve = {
6
+ success: true,
7
+ returned: JsonValue
8
+ } | {
9
+ success: false
10
+ }
11
+
12
+ const DEFAULT_TIMEOUT = 5000
13
+ const pendingResolves: Record<number, (resolve: Resolve) => void> = {}
14
+ const requests: string[] = []
15
+ let requestId = 0
16
+
17
+ onNui<Request<JsonValue, '__nuiServer', {
18
+ id: string
19
+ data: {
20
+ requestData: JsonValue
21
+ timeout?: number
22
+ }
23
+ }>>('__nuiServer', async ({ id, data }) => {
24
+ const { timeout = DEFAULT_TIMEOUT, requestData } = data
25
+
26
+ const response = await new Promise<Resolve>(resolve => {
27
+ requestId = requestId + 1
28
+ const currentRequestId = requestId
29
+ pendingResolves[currentRequestId] = resolve
30
+
31
+ if (!requests.includes(id)) {
32
+ requests.push(id)
33
+ onNet(`lenix/nui:${id}`, (selfrequestId: number, response: JsonValue) => {
34
+ if (!pendingResolves[selfrequestId]) return
35
+
36
+ pendingResolves[selfrequestId]({ success: true, returned: response })
37
+ delete pendingResolves[selfrequestId]
38
+ })
39
+ }
40
+
41
+ emitNet(`lenix/nui:${id}`, currentRequestId, requestData)
42
+
43
+ setTimeout(() => {
44
+ if (pendingResolves[currentRequestId]) {
45
+ pendingResolves[currentRequestId]({ success: false })
46
+ delete pendingResolves[currentRequestId]
47
+ }
48
+ }, timeout)
49
+ })
50
+
51
+ asserts(response.success, `server nui<${id}> timed out after ${timeout}ms, possible slow respose or request does not exist`)
52
+
53
+ return response.returned
54
+ })
55
+
4
56
  onNui<Request<true, '__nuiFocus', {
5
57
  keyboard: boolean,
6
58
  cursor: boolean
package/client/nui.ts CHANGED
@@ -1,9 +1,9 @@
1
- import type { Request } from '../shared/types.ts'
1
+ import type { NuiFetchGeneric } from '../shared/types.ts'
2
2
 
3
3
  /**
4
4
  * Sends an event from the game client to the NUI browser.
5
5
  */
6
- export const emitEvent = <T extends [string, unknown[]]>(id: T[0], ...params: T[1]): void => {
6
+ export const emitNui = <T extends [string, unknown[]]>(id: T[0], ...params: T[1]): void => {
7
7
  if (
8
8
  !SendNuiMessage(
9
9
  JSON.stringify({
@@ -19,7 +19,7 @@ export const emitEvent = <T extends [string, unknown[]]>(id: T[0], ...params: T[
19
19
  /**
20
20
  * Registers a typed NUI callback on the game client.
21
21
  */
22
- export const onNui = <T extends Request<unknown, string, object>>(
22
+ export const onNui = <T extends NuiFetchGeneric>(
23
23
  id: T[1],
24
24
  cb: (data: T[2]) => T[0] | Promise<T[0]>
25
25
  ): void => {
package/nui/fetch.ts CHANGED
@@ -1,12 +1,11 @@
1
- import { JsonValue } from '@lenix/lenix'
2
- import type { Request } from '../shared/types.ts'
1
+ import type { NuiFetchGeneric, Request } from '../shared/types.ts'
3
2
 
4
3
  declare function GetParentResourceName(): string
5
4
 
6
5
  /**
7
6
  * Fetchs a typed request from the NUI browser to the game client.
8
7
  */
9
- export const fetchNui = async <T extends Request<JsonValue, string, object>>(
8
+ export const fetchNui = async <T extends NuiFetchGeneric>(
10
9
  id: T[1],
11
10
  data: T[2]
12
11
  ): Promise<T[0]> => {
@@ -23,3 +22,22 @@ export const fetchNui = async <T extends Request<JsonValue, string, object>>(
23
22
  throw `Error occured while emiting an nui<${id}>.\n${e}`
24
23
  }
25
24
  }
25
+
26
+ export const fetchNuiServer = <T extends NuiFetchGeneric>(
27
+ id: T[1],
28
+ requestData: T[2],
29
+ timeout?: number,
30
+ ): Promise<T[0]> => fetchNui<Request<T[0], '__nuiServer', {
31
+ id: T[1]
32
+ data: {
33
+ timeout?: number
34
+ requestData: T[2]
35
+ }
36
+ }>>(
37
+ '__nuiServer', {
38
+ id,
39
+ data: {
40
+ timeout,
41
+ requestData,
42
+ }
43
+ })
package/nui/on.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import type { Event } from '../shared/types.ts'
2
2
 
3
- interface Listener<T extends unknown[]> {
3
+ interface Logger<T extends unknown[]> {
4
4
  callback: (...params: T) => void
5
5
  log?: true
6
6
  }
7
- const events = new Map<string, Set<Listener<unknown[]>>>()
7
+ const events = new Map<string, Set<Logger<unknown[]>>>()
8
8
 
9
9
  const handler = (event: MessageEvent) => {
10
10
  const { id, params } = event.data
@@ -24,34 +24,34 @@ const handler = (event: MessageEvent) => {
24
24
  /**
25
25
  * Registers a typed browser-side handler for events sent from the game client.
26
26
  */
27
- export const onEvent = <
27
+ export const onNuiEmit = <
28
28
  T extends Event<string, unknown[]>
29
29
  >(
30
30
  id: T[0],
31
31
  cb: (...params: T[1]) => void,
32
- listen?: true
32
+ log?: true
33
33
  ): () => void => {
34
34
  if (events.size === 0) {
35
35
  window.addEventListener('message', handler)
36
- listen && console.info(`Event<${id}> is the first on the window`)
36
+ log && console.info(`Event<${id}> is the first on the window`)
37
37
  }
38
38
 
39
- const callbacks = events.get(id) ?? new Set<Listener<unknown[]>>()
40
- const listenerCb = { callback: cb, log: listen }
39
+ const callbacks = events.get(id) ?? new Set<Logger<unknown[]>>()
40
+ const listenerCb = { callback: cb, log: log }
41
41
  callbacks.add(listenerCb)
42
42
  events.set(id, callbacks)
43
- listen && console.info(`Event<${id}> was registered`)
43
+ log && console.info(`Event<${id}> was registered`)
44
44
 
45
45
  return () => {
46
- listen && console.info(`Event<${id}> was unregistered`)
46
+ log && console.info(`Event<${id}> was unregistered`)
47
47
  callbacks.delete(listenerCb)
48
48
  if (callbacks.size === 0) {
49
49
  events.delete(id)
50
- listen && console.info(`Event<${id}> got no callbacks left, memory cleared successfully`)
50
+ log && console.info(`Event<${id}> got no callbacks left, memory cleared successfully`)
51
51
  }
52
52
  if (events.size === 0) {
53
53
  window.removeEventListener('message', handler)
54
- listen && console.info(`No events left, this event<${id}> was the last, opting out the listen...`)
54
+ log && console.info(`No events left, this event<${id}> was the last, opting out the listen...`)
55
55
  }
56
56
  }
57
57
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lenix",
3
- "version": "1.7.24",
3
+ "version": "1.8.0",
4
4
  "description": "Typed FiveM utilities for client, server, shared, and NUI scripts",
5
5
  "author": "Lenix",
6
6
  "license": "MIT",
package/server/index.ts CHANGED
@@ -5,4 +5,5 @@
5
5
  */
6
6
 
7
7
  export * from './server'
8
- export * from '../shared/api'
8
+ export * from '../shared/api'
9
+ export * from './nui'
package/server/nui.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { asserts } from "@lenix/lenix";
2
+ import { NuiFetchGeneric } from "../shared";
3
+
4
+ const clientRequests: string[] = []
5
+
6
+ export const onNuiServer = <T extends NuiFetchGeneric>(
7
+ id: T[1],
8
+ cb: (client: number, data: T[2]) => T[0] | Promise<T[0]>
9
+ ) => {
10
+ asserts(!clientRequests.includes(id), `server nui<${id}> is already defined`)
11
+
12
+ clientRequests.push(id)
13
+
14
+ onNet(`lenix/nui:${id}`, async(requestId: number, parameters: Parameters<typeof cb>[1]) => {
15
+ const clientSource = source
16
+
17
+ try {
18
+ const result = await cb(clientSource, parameters)
19
+ emitNet(`lenix/nui:${id}`, clientSource, requestId, result)
20
+ } catch (error) {
21
+ emitNet(`lenix/nui:${id}`, clientSource, requestId)
22
+ throw error
23
+ }
24
+ })
25
+ }
package/shared/types.ts CHANGED
@@ -18,9 +18,14 @@ export type Event<Id extends string, Params extends unknown[] = never> = [Id, Pa
18
18
  /**
19
19
  * Typed request tuple containing a response type, request id, and object payload.
20
20
  */
21
+ interface JsonObject {
22
+ [key: string]: JsonValue
23
+ }
21
24
  export type Request<
22
25
  Response extends JsonValue,
23
26
  Id extends string,
24
- Params extends object = { [key: string]: unknown }
27
+ Params extends JsonObject = JsonObject
25
28
  > = Params extends readonly unknown[] ? never
26
29
  : [Response, Id, Params]
30
+
31
+ export type NuiFetchGeneric = Request<JsonValue, string, JsonObject>