@bazir/utils 0.1.0 → 0.1.2
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/out/Network.d.ts +54 -0
- package/out/Network.luau +434 -0
- package/out/index.d.ts +6 -0
- package/out/init.luau +11 -0
- package/package.json +15 -12
package/out/Network.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ReactiveCache } from "@bazir/state/out/State";
|
|
2
|
+
declare const SECRET: unique symbol;
|
|
3
|
+
declare namespace NetworkSystem {
|
|
4
|
+
export function generateHash(input: string): string;
|
|
5
|
+
export function createId(stackLevel?: number): string;
|
|
6
|
+
export function createNetworkId(stackLevel?: number): string;
|
|
7
|
+
type SignalListener<T extends unknown[]> = (...args: T) => void;
|
|
8
|
+
type RemoteEvent<T extends unknown[]> = Instance & {
|
|
9
|
+
FireClient: (this: RemoteEvent<T>, player: Player, ...args: T) => void;
|
|
10
|
+
FireServer: (this: RemoteEvent<T>, ...args: T) => void;
|
|
11
|
+
FireAllClients: (this: RemoteEvent<T>, ...args: T) => void;
|
|
12
|
+
OnServerEvent: RBXScriptSignal<(player: Player, ...args: T) => void>;
|
|
13
|
+
OnClientEvent: RBXScriptSignal<(...args: T) => void>;
|
|
14
|
+
};
|
|
15
|
+
type RemoteFunction<TReq extends unknown[], TRes> = Instance & {
|
|
16
|
+
InvokeClient: (this: RemoteFunction<TReq, TRes>, player: Player, ...args: TReq) => TRes;
|
|
17
|
+
InvokeServer: (this: RemoteFunction<TReq, TRes>, ...args: TReq) => TRes;
|
|
18
|
+
OnServerInvoke: (player: Player, ...args: TReq) => TRes;
|
|
19
|
+
OnClientInvoke: (...args: TReq) => TRes;
|
|
20
|
+
};
|
|
21
|
+
type RequestHandler<TReq extends unknown[], TRes> = (...args: TReq) => TRes;
|
|
22
|
+
export function createEvent<T extends unknown[]>(level?: number, parent?: LuaSourceContainer): RemoteEvent<T>;
|
|
23
|
+
export function onServer<T extends unknown[]>(instance: RemoteEvent<T>, listener: SignalListener<[player: Player, ...T]>): void;
|
|
24
|
+
export function onClient<T extends unknown[]>(instance: RemoteEvent<T>, listener: SignalListener<T>): void;
|
|
25
|
+
export function fireServer<T extends unknown[]>(instance: RemoteEvent<T>, ...args: T): void;
|
|
26
|
+
export function fireClient<T extends unknown[]>(instance: RemoteEvent<T>, player: Player, ...args: T): void;
|
|
27
|
+
export function broadcast<T extends unknown[]>(instance: RemoteEvent<T>, ...args: T): void;
|
|
28
|
+
export function createFunction<TReq extends unknown[], TRes>(level?: number, parent?: LuaSourceContainer): RemoteFunction<TReq, TRes>;
|
|
29
|
+
export function handleServer<TReq extends unknown[], TRes>(instance: RemoteFunction<TReq, TRes>, handler: RequestHandler<[player: Player, ...TReq], TRes>): void;
|
|
30
|
+
export function handleClient<TReq extends unknown[], TRes>(instance: RemoteFunction<TReq, TRes>, handler: RequestHandler<TReq, TRes>): void;
|
|
31
|
+
export function invokeServer<TReq extends unknown[], TRes>(instance: RemoteFunction<TReq, TRes>, ...args: TReq): TRes;
|
|
32
|
+
export function invokeClient<TReq extends unknown[], TRes>(instance: RemoteFunction<TReq, TRes>, player: Player, ...args: TReq): TRes;
|
|
33
|
+
export function createReplica<T>(initialValue: T, level?: number): ReactiveCache<T>;
|
|
34
|
+
interface SecretCache<T> extends ReactiveCache<T> {
|
|
35
|
+
[SECRET]: {
|
|
36
|
+
active: Set<Player>;
|
|
37
|
+
players: Map<Player, T>;
|
|
38
|
+
event: RemoteEvent<unknown[]>;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function createSecret<T>(initialValue: T, level?: number): SecretCache<T>;
|
|
42
|
+
export function writePlayer<T>(secretCache: SecretCache<T>, player: Player, secret: T): void;
|
|
43
|
+
export function peekPlayer<T>(secretCache: SecretCache<T>, player: Player): T;
|
|
44
|
+
export function lazy<T>(importFn: () => T | Promise<T>): () => T;
|
|
45
|
+
type ActionFunction<Args extends unknown[], Return> = (...args: Args) => Promise<Return>;
|
|
46
|
+
export type ServerAction<Args extends unknown[], Return> = ActionFunction<Args, Return> & {
|
|
47
|
+
pending: ReactiveCache<boolean>;
|
|
48
|
+
error: ReactiveCache<string | undefined>;
|
|
49
|
+
};
|
|
50
|
+
export function createAction<Args extends unknown[], Return>(fn: (player: Player, ...args: Args) => Return | Promise<Return>): RemoteFunction<Args, Return>;
|
|
51
|
+
export function useAction<Args extends unknown[], Return>(actionHandler: RemoteFunction<Args, Return>): ServerAction<Args, Return>;
|
|
52
|
+
export {};
|
|
53
|
+
}
|
|
54
|
+
export = NetworkSystem;
|
package/out/Network.luau
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _Error = TS.import(script, TS.getModule(script, "@bazir", "core").out.Error)
|
|
4
|
+
local report = _Error.report
|
|
5
|
+
local createError = _Error.createError
|
|
6
|
+
local _Platform = TS.import(script, TS.getModule(script, "@bazir", "core").out.Platform)
|
|
7
|
+
local getDebugInfo = _Platform.getDebugInfo
|
|
8
|
+
local isRunningOnServer = _Platform.isRunningOnServer
|
|
9
|
+
local _State = TS.import(script, TS.getModule(script, "@bazir", "state").out.State)
|
|
10
|
+
local value = _State.value
|
|
11
|
+
local subscribe = _State.subscribe
|
|
12
|
+
local peek = _State.peek
|
|
13
|
+
local update = _State.update
|
|
14
|
+
local write = _State.write
|
|
15
|
+
local waitForOrCreate = TS.import(script, TS.getModule(script, "@bazir", "ui").out.Instance).waitForOrCreate
|
|
16
|
+
local Players = TS.import(script, TS.getModule(script, "@rbxts", "services")).Players
|
|
17
|
+
--[[
|
|
18
|
+
*
|
|
19
|
+
* Assigns a call signature to an object.
|
|
20
|
+
*
|
|
21
|
+
* @param callback The function to assign.
|
|
22
|
+
* @param object The object to assign the function to.
|
|
23
|
+
* @returns A callable object.
|
|
24
|
+
|
|
25
|
+
]]
|
|
26
|
+
local function callable(callback, object)
|
|
27
|
+
return setmetatable(object, {
|
|
28
|
+
__call = function(_, ...)
|
|
29
|
+
local args = { ... }
|
|
30
|
+
return callback(unpack(args))
|
|
31
|
+
end,
|
|
32
|
+
})
|
|
33
|
+
end
|
|
34
|
+
local SECRET = "__secret"
|
|
35
|
+
local NetworkSystem = {}
|
|
36
|
+
do
|
|
37
|
+
local _container = NetworkSystem
|
|
38
|
+
local NONE = {
|
|
39
|
+
__none = "__none",
|
|
40
|
+
}
|
|
41
|
+
local function isEmpty(state)
|
|
42
|
+
return next(state) == nil
|
|
43
|
+
end
|
|
44
|
+
local function isNone(state)
|
|
45
|
+
local _state = state
|
|
46
|
+
local _condition = type(_state) == "table"
|
|
47
|
+
if _condition then
|
|
48
|
+
_condition = state[NONE.__none] ~= nil
|
|
49
|
+
end
|
|
50
|
+
if _condition then
|
|
51
|
+
return state.__none == NONE.__none
|
|
52
|
+
end
|
|
53
|
+
return false
|
|
54
|
+
end
|
|
55
|
+
local function diff(prevState, nextState)
|
|
56
|
+
if prevState == nextState then
|
|
57
|
+
return nil
|
|
58
|
+
elseif nextState == nil then
|
|
59
|
+
return NONE
|
|
60
|
+
else
|
|
61
|
+
local _prevState = prevState
|
|
62
|
+
local _condition = not (type(_prevState) == "table")
|
|
63
|
+
if not _condition then
|
|
64
|
+
local _nextState = nextState
|
|
65
|
+
_condition = not (type(_nextState) == "table")
|
|
66
|
+
end
|
|
67
|
+
if _condition then
|
|
68
|
+
return nextState
|
|
69
|
+
elseif isEmpty(prevState) and isEmpty(nextState) then
|
|
70
|
+
return nil
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
local _object = {}
|
|
74
|
+
if nextState then
|
|
75
|
+
for _k, _v in nextState do
|
|
76
|
+
_object[_k] = _v
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
local patches = _object
|
|
80
|
+
for key, previous in pairs(prevState) do
|
|
81
|
+
patches[key] = diff(previous, nextState[key])
|
|
82
|
+
end
|
|
83
|
+
if isEmpty(patches) then
|
|
84
|
+
return nil
|
|
85
|
+
end
|
|
86
|
+
return patches
|
|
87
|
+
end
|
|
88
|
+
local function apply(state, patches)
|
|
89
|
+
if isNone(patches) then
|
|
90
|
+
return nil
|
|
91
|
+
else
|
|
92
|
+
local _state = state
|
|
93
|
+
local _condition = not (type(_state) == "table")
|
|
94
|
+
if not _condition then
|
|
95
|
+
local _patches = patches
|
|
96
|
+
_condition = not (type(_patches) == "table")
|
|
97
|
+
end
|
|
98
|
+
if _condition then
|
|
99
|
+
return patches
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
local _object = {}
|
|
103
|
+
if state then
|
|
104
|
+
for _k, _v in state do
|
|
105
|
+
_object[_k] = _v
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
local nextState = _object
|
|
109
|
+
local stateIsArray = nextState[1] ~= nil
|
|
110
|
+
-- eslint-disable-next-line prefer-const
|
|
111
|
+
for key, patch in pairs(patches) do
|
|
112
|
+
local _condition = stateIsArray
|
|
113
|
+
if _condition then
|
|
114
|
+
local _key = key
|
|
115
|
+
_condition = type(_key) == "string"
|
|
116
|
+
end
|
|
117
|
+
if _condition then
|
|
118
|
+
local _condition_1 = tonumber(key)
|
|
119
|
+
if _condition_1 == nil then
|
|
120
|
+
_condition_1 = key
|
|
121
|
+
end
|
|
122
|
+
key = _condition_1
|
|
123
|
+
end
|
|
124
|
+
nextState[key] = apply(nextState[key], patch)
|
|
125
|
+
end
|
|
126
|
+
return nextState
|
|
127
|
+
end
|
|
128
|
+
local identifierCounts = {}
|
|
129
|
+
local function getSourceLocation(level)
|
|
130
|
+
local scriptPath, lineNumber = getDebugInfo(level)
|
|
131
|
+
return `{scriptPath}:{lineNumber}`
|
|
132
|
+
end
|
|
133
|
+
local function getAndIncrementCount(location)
|
|
134
|
+
local _location = location
|
|
135
|
+
local _condition = identifierCounts[_location]
|
|
136
|
+
if _condition == nil then
|
|
137
|
+
_condition = 0
|
|
138
|
+
end
|
|
139
|
+
local currentCount = _condition
|
|
140
|
+
local _location_1 = location
|
|
141
|
+
local _arg1 = currentCount + 1
|
|
142
|
+
identifierCounts[_location_1] = _arg1
|
|
143
|
+
return currentCount
|
|
144
|
+
end
|
|
145
|
+
local function generateHash(input)
|
|
146
|
+
local hash = 0
|
|
147
|
+
for i = 0, #input - 1 do
|
|
148
|
+
local byteValue = string.byte(input, i + 1)
|
|
149
|
+
hash = (bit32.lshift(hash, 5)) - hash + byteValue
|
|
150
|
+
hash = bit32.band(hash, hash)
|
|
151
|
+
end
|
|
152
|
+
return tostring(math.abs(hash))
|
|
153
|
+
end
|
|
154
|
+
_container.generateHash = generateHash
|
|
155
|
+
local function createId(stackLevel)
|
|
156
|
+
if stackLevel == nil then
|
|
157
|
+
stackLevel = 0
|
|
158
|
+
end
|
|
159
|
+
local sourceLocation = getSourceLocation(stackLevel + 3)
|
|
160
|
+
local currentCount = getAndIncrementCount(sourceLocation)
|
|
161
|
+
return `{sourceLocation}-{currentCount}`
|
|
162
|
+
end
|
|
163
|
+
_container.createId = createId
|
|
164
|
+
local function createNetworkId(stackLevel)
|
|
165
|
+
if stackLevel == nil then
|
|
166
|
+
stackLevel = 0
|
|
167
|
+
end
|
|
168
|
+
return generateHash(createId(stackLevel + 1))
|
|
169
|
+
end
|
|
170
|
+
_container.createNetworkId = createNetworkId
|
|
171
|
+
local function createEvent(level, parent)
|
|
172
|
+
if level == nil then
|
|
173
|
+
level = 0
|
|
174
|
+
end
|
|
175
|
+
if parent == nil then
|
|
176
|
+
parent = script
|
|
177
|
+
end
|
|
178
|
+
local id = `Event@{createNetworkId(level + 1)}`
|
|
179
|
+
return waitForOrCreate("RemoteEvent", parent, id)
|
|
180
|
+
end
|
|
181
|
+
_container.createEvent = createEvent
|
|
182
|
+
local function onServer(instance, listener)
|
|
183
|
+
instance.OnServerEvent:Connect(listener)
|
|
184
|
+
end
|
|
185
|
+
_container.onServer = onServer
|
|
186
|
+
local function onClient(instance, listener)
|
|
187
|
+
instance.OnClientEvent:Connect(listener)
|
|
188
|
+
end
|
|
189
|
+
_container.onClient = onClient
|
|
190
|
+
local function fireServer(instance, ...)
|
|
191
|
+
local args = { ... }
|
|
192
|
+
instance:FireServer(unpack(args))
|
|
193
|
+
end
|
|
194
|
+
_container.fireServer = fireServer
|
|
195
|
+
local function fireClient(instance, player, ...)
|
|
196
|
+
local args = { ... }
|
|
197
|
+
instance:FireClient(player, unpack(args))
|
|
198
|
+
end
|
|
199
|
+
_container.fireClient = fireClient
|
|
200
|
+
local function broadcast(instance, ...)
|
|
201
|
+
local args = { ... }
|
|
202
|
+
instance:FireAllClients(unpack(args))
|
|
203
|
+
end
|
|
204
|
+
_container.broadcast = broadcast
|
|
205
|
+
local function createFunction(level, parent)
|
|
206
|
+
if level == nil then
|
|
207
|
+
level = 0
|
|
208
|
+
end
|
|
209
|
+
if parent == nil then
|
|
210
|
+
parent = script
|
|
211
|
+
end
|
|
212
|
+
local id = `Function@{createNetworkId(level + 1)}`
|
|
213
|
+
return waitForOrCreate("RemoteFunction", parent, id)
|
|
214
|
+
end
|
|
215
|
+
_container.createFunction = createFunction
|
|
216
|
+
local function handleServer(instance, handler)
|
|
217
|
+
instance.OnServerInvoke = handler
|
|
218
|
+
end
|
|
219
|
+
_container.handleServer = handleServer
|
|
220
|
+
local function handleClient(instance, handler)
|
|
221
|
+
instance.OnClientInvoke = handler
|
|
222
|
+
end
|
|
223
|
+
_container.handleClient = handleClient
|
|
224
|
+
local function invokeServer(instance, ...)
|
|
225
|
+
local args = { ... }
|
|
226
|
+
return instance:InvokeServer(unpack(args))
|
|
227
|
+
end
|
|
228
|
+
_container.invokeServer = invokeServer
|
|
229
|
+
local function invokeClient(instance, player, ...)
|
|
230
|
+
local args = { ... }
|
|
231
|
+
return instance:InvokeClient(player, unpack(args))
|
|
232
|
+
end
|
|
233
|
+
_container.invokeClient = invokeClient
|
|
234
|
+
local function createReplica(initialValue, level)
|
|
235
|
+
if level == nil then
|
|
236
|
+
level = 0
|
|
237
|
+
end
|
|
238
|
+
local connectPatches = createEvent(level + 1)
|
|
239
|
+
local applyPatches = createEvent(level + 1)
|
|
240
|
+
local state = value(initialValue)
|
|
241
|
+
if isRunningOnServer() then
|
|
242
|
+
local activePlayers = {}
|
|
243
|
+
Players.PlayerRemoving:Connect(function(player)
|
|
244
|
+
local _player = player
|
|
245
|
+
activePlayers[_player] = nil
|
|
246
|
+
end)
|
|
247
|
+
subscribe(state, function(newValue, prevValue)
|
|
248
|
+
local patches = diff(prevValue, newValue)
|
|
249
|
+
if patches == nil then
|
|
250
|
+
return nil
|
|
251
|
+
end
|
|
252
|
+
for player in activePlayers do
|
|
253
|
+
fireClient(applyPatches, player, patches)
|
|
254
|
+
end
|
|
255
|
+
end)
|
|
256
|
+
onServer(connectPatches, function(player)
|
|
257
|
+
local patches = diff(initialValue, peek(state))
|
|
258
|
+
if patches ~= nil then
|
|
259
|
+
fireClient(applyPatches, player, patches)
|
|
260
|
+
end
|
|
261
|
+
if player:IsDescendantOf(game) then
|
|
262
|
+
local _player = player
|
|
263
|
+
activePlayers[_player] = true
|
|
264
|
+
end
|
|
265
|
+
end)
|
|
266
|
+
else
|
|
267
|
+
onClient(applyPatches, function(patches)
|
|
268
|
+
update(state, function(current)
|
|
269
|
+
return apply(current, patches)
|
|
270
|
+
end)
|
|
271
|
+
end)
|
|
272
|
+
fireServer(connectPatches)
|
|
273
|
+
end
|
|
274
|
+
return state
|
|
275
|
+
end
|
|
276
|
+
_container.createReplica = createReplica
|
|
277
|
+
local function createSecret(initialValue, level)
|
|
278
|
+
if level == nil then
|
|
279
|
+
level = 0
|
|
280
|
+
end
|
|
281
|
+
local connectPatches = createEvent(level + 1)
|
|
282
|
+
local applyPatches = createEvent(level + 1)
|
|
283
|
+
local state = value(initialValue)
|
|
284
|
+
if isRunningOnServer() then
|
|
285
|
+
state[SECRET] = {
|
|
286
|
+
active = {},
|
|
287
|
+
players = {},
|
|
288
|
+
event = applyPatches,
|
|
289
|
+
}
|
|
290
|
+
local _binding = (state[SECRET])
|
|
291
|
+
local active = _binding.active
|
|
292
|
+
local players = _binding.players
|
|
293
|
+
Players.PlayerRemoving:Connect(function(player)
|
|
294
|
+
local _player = player
|
|
295
|
+
active[_player] = nil
|
|
296
|
+
local _player_1 = player
|
|
297
|
+
players[_player_1] = nil
|
|
298
|
+
end)
|
|
299
|
+
onServer(connectPatches, function(player)
|
|
300
|
+
local _exp = initialValue
|
|
301
|
+
local _player = player
|
|
302
|
+
local _condition = players[_player]
|
|
303
|
+
if _condition == nil then
|
|
304
|
+
_condition = peek(state)
|
|
305
|
+
end
|
|
306
|
+
local patches = diff(_exp, _condition)
|
|
307
|
+
if patches ~= nil then
|
|
308
|
+
fireClient(applyPatches, player, patches)
|
|
309
|
+
end
|
|
310
|
+
if player:IsDescendantOf(game) then
|
|
311
|
+
local _player_1 = player
|
|
312
|
+
active[_player_1] = true
|
|
313
|
+
end
|
|
314
|
+
end)
|
|
315
|
+
else
|
|
316
|
+
onClient(applyPatches, function(patches)
|
|
317
|
+
update(state, function(current)
|
|
318
|
+
return apply(current, patches)
|
|
319
|
+
end)
|
|
320
|
+
end)
|
|
321
|
+
fireServer(connectPatches)
|
|
322
|
+
end
|
|
323
|
+
return state
|
|
324
|
+
end
|
|
325
|
+
_container.createSecret = createSecret
|
|
326
|
+
local function writePlayer(secretCache, player, secret)
|
|
327
|
+
local _binding = secretCache[SECRET]
|
|
328
|
+
local active = _binding.active
|
|
329
|
+
local players = _binding.players
|
|
330
|
+
local event = _binding.event
|
|
331
|
+
local _player = player
|
|
332
|
+
if not (active[_player] ~= nil) then
|
|
333
|
+
return nil
|
|
334
|
+
end
|
|
335
|
+
local _player_1 = player
|
|
336
|
+
local _condition = players[_player_1]
|
|
337
|
+
if _condition == nil then
|
|
338
|
+
_condition = peek(secretCache)
|
|
339
|
+
end
|
|
340
|
+
local lastSecret = _condition
|
|
341
|
+
local patches = diff(lastSecret, secret)
|
|
342
|
+
if patches == nil then
|
|
343
|
+
local _player_2 = player
|
|
344
|
+
local _secret = secret
|
|
345
|
+
players[_player_2] = _secret
|
|
346
|
+
fireClient(event, player, patches)
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
_container.writePlayer = writePlayer
|
|
350
|
+
local function peekPlayer(secretCache, player)
|
|
351
|
+
local _binding = secretCache[SECRET]
|
|
352
|
+
local players = _binding.players
|
|
353
|
+
local _player = player
|
|
354
|
+
local _condition = players[_player]
|
|
355
|
+
if _condition == nil then
|
|
356
|
+
_condition = peek(secretCache)
|
|
357
|
+
end
|
|
358
|
+
return _condition
|
|
359
|
+
end
|
|
360
|
+
_container.peekPlayer = peekPlayer
|
|
361
|
+
local function lazy(importFn)
|
|
362
|
+
local cached
|
|
363
|
+
return function()
|
|
364
|
+
if not isRunningOnServer() then
|
|
365
|
+
error("lazy can only be called on the server")
|
|
366
|
+
end
|
|
367
|
+
if cached == nil then
|
|
368
|
+
local result = importFn()
|
|
369
|
+
cached = if TS.Promise.is(result) then result:expect() else result
|
|
370
|
+
end
|
|
371
|
+
return cached
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
_container.lazy = lazy
|
|
375
|
+
-- Create server action (server-side)
|
|
376
|
+
local function createAction(fn)
|
|
377
|
+
local handler = createFunction(1)
|
|
378
|
+
if isRunningOnServer() then
|
|
379
|
+
handleServer(handler, function(...)
|
|
380
|
+
local args = { ... }
|
|
381
|
+
local _exitType, _returns = TS.try(function()
|
|
382
|
+
local result = fn(unpack(args))
|
|
383
|
+
return TS.TRY_RETURN, { if TS.Promise.is(result) then result:expect() else result }
|
|
384
|
+
end, function(err)
|
|
385
|
+
report(createError(tostring(err), {
|
|
386
|
+
code = "SERVER_ACTION_FAILED",
|
|
387
|
+
context = {
|
|
388
|
+
args = args,
|
|
389
|
+
},
|
|
390
|
+
}))
|
|
391
|
+
error(err)
|
|
392
|
+
end)
|
|
393
|
+
if _exitType then
|
|
394
|
+
return unpack(_returns)
|
|
395
|
+
end
|
|
396
|
+
end)
|
|
397
|
+
end
|
|
398
|
+
return handler
|
|
399
|
+
end
|
|
400
|
+
_container.createAction = createAction
|
|
401
|
+
-- Create action caller (client-side)
|
|
402
|
+
local function useAction(actionHandler)
|
|
403
|
+
if isRunningOnServer() then
|
|
404
|
+
error("useAction can only be called on the client")
|
|
405
|
+
end
|
|
406
|
+
local pending = value(false)
|
|
407
|
+
local errorMessage = value(nil)
|
|
408
|
+
local actionCaller = TS.async(function(...)
|
|
409
|
+
local args = { ... }
|
|
410
|
+
write(pending, true)
|
|
411
|
+
write(errorMessage, nil)
|
|
412
|
+
local lastError
|
|
413
|
+
local _exitType, _returns = TS.try(function()
|
|
414
|
+
local result = invokeServer(actionHandler, unpack(args))
|
|
415
|
+
write(pending, false)
|
|
416
|
+
return TS.TRY_RETURN, { result }
|
|
417
|
+
end, function(err)
|
|
418
|
+
lastError = err
|
|
419
|
+
end)
|
|
420
|
+
if _exitType then
|
|
421
|
+
return unpack(_returns)
|
|
422
|
+
end
|
|
423
|
+
write(pending, false)
|
|
424
|
+
write(errorMessage, tostring(lastError))
|
|
425
|
+
error(lastError)
|
|
426
|
+
end)
|
|
427
|
+
return callable(actionCaller, {
|
|
428
|
+
pending = pending,
|
|
429
|
+
error = errorMessage,
|
|
430
|
+
})
|
|
431
|
+
end
|
|
432
|
+
_container.useAction = useAction
|
|
433
|
+
end
|
|
434
|
+
return NetworkSystem
|
package/out/index.d.ts
ADDED
package/out/init.luau
ADDED
package/package.json
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bazir/utils",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Utility functions for Bazir framework",
|
|
5
|
-
"main": "
|
|
6
|
-
"types": "
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsc",
|
|
9
|
-
"prepublishOnly": "npm run build"
|
|
10
|
-
},
|
|
5
|
+
"main": "out/init.lua",
|
|
6
|
+
"types": "out/index.d.ts",
|
|
11
7
|
"files": [
|
|
12
|
-
"
|
|
8
|
+
"out",
|
|
13
9
|
"!**/*.tsbuildinfo"
|
|
14
10
|
],
|
|
15
11
|
"publishConfig": {
|
|
16
|
-
"access": "public"
|
|
12
|
+
"access": "public",
|
|
13
|
+
"git-checks": false
|
|
17
14
|
},
|
|
18
15
|
"keywords": [
|
|
19
16
|
"roblox",
|
|
@@ -24,12 +21,18 @@
|
|
|
24
21
|
"author": "",
|
|
25
22
|
"license": "ISC",
|
|
26
23
|
"dependencies": {
|
|
27
|
-
"@bazir/core": "^0.1.
|
|
24
|
+
"@bazir/core": "^0.1.2",
|
|
25
|
+
"@bazir/state": "^0.1.2",
|
|
26
|
+
"@bazir/ui": "^0.1.2",
|
|
28
27
|
"@rbxts/services": "^1.5.5"
|
|
29
28
|
},
|
|
30
29
|
"devDependencies": {
|
|
31
30
|
"@rbxts/compiler-types": "3.0.0-types.0",
|
|
32
|
-
"@rbxts/types": "^1.0.
|
|
33
|
-
"typescript": "^5.
|
|
31
|
+
"@rbxts/types": "^1.0.840",
|
|
32
|
+
"typescript": "^5.8.2"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "rbxtsc",
|
|
36
|
+
"watch": "rbxtsc -w"
|
|
34
37
|
}
|
|
35
38
|
}
|