@quenty/promise 10.10.1 → 10.10.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/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [10.10.2](https://github.com/Quenty/NevermoreEngine/compare/@quenty/promise@10.10.1...@quenty/promise@10.10.2) (2025-04-05)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Add types to packages ([2374fb2](https://github.com/Quenty/NevermoreEngine/commit/2374fb2b043cfbe0e9b507b3316eec46a4e353a0))
12
+
13
+
14
+
15
+
16
+
6
17
  ## [10.10.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/promise@10.10.0...@quenty/promise@10.10.1) (2025-03-21)
7
18
 
8
19
  **Note:** Version bump only for package @quenty/promise
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/promise",
3
- "version": "10.10.1",
3
+ "version": "10.10.2",
4
4
  "description": "Promise implementation for Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -25,13 +25,13 @@
25
25
  "Quenty"
26
26
  ],
27
27
  "dependencies": {
28
- "@quenty/deferred": "^2.2.0",
29
- "@quenty/loader": "^10.8.0",
30
- "@quenty/maid": "^3.4.0",
31
- "@quenty/math": "^2.7.1"
28
+ "@quenty/deferred": "^2.2.1",
29
+ "@quenty/loader": "^10.8.1",
30
+ "@quenty/maid": "^3.4.1",
31
+ "@quenty/math": "^2.7.2"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public"
35
35
  },
36
- "gitHead": "6b7c3e15e60cdb185986207b574e2b5591261e7a"
36
+ "gitHead": "78c3ac0ab08dd18085b6e6e6e4f745e76ed99f68"
37
37
  }
@@ -1,3 +1,4 @@
1
+ --!nocheck
1
2
  --[=[
2
3
  Promises, but without error handling as this screws with stack traces, using Roblox signals
3
4
 
@@ -12,19 +13,34 @@ local HttpService = game:GetService("HttpService")
12
13
  local ENABLE_TRACEBACK = false
13
14
  local _emptyRejectedPromise = nil
14
15
  local _emptyFulfilledPromise = nil
15
- local EMPTY_PACKED_TUPLE = table.freeze({ n = 0; })
16
+ local EMPTY_PACKED_TUPLE = table.freeze({ n = 0 })
16
17
 
17
18
  local Promise = {}
18
19
  Promise.ClassName = "Promise"
19
20
  Promise.__index = Promise
20
21
 
22
+ export type Resolve<T...> = (T...) -> ()
23
+ export type Reject = (...any) -> ()
24
+ export type ResolveReject<T...> = (Resolve<T...>, Reject) -> ()
25
+
26
+ export type Promise<T...> = typeof(setmetatable(
27
+ {} :: {
28
+ _fulfilled: any?,
29
+ _rejected: any?,
30
+ _unconsumedException: boolean,
31
+ _pendingExecuteList: { any }?,
32
+ _source: string,
33
+ },
34
+ Promise
35
+ ))
36
+
21
37
  --[=[
22
38
  Determines whether a value is a promise or not.
23
39
 
24
40
  @param value any
25
41
  @return boolean
26
42
  ]=]
27
- function Promise.isPromise(value)
43
+ function Promise.isPromise(value: any): boolean
28
44
  return type(value) == "table" and value.ClassName == "Promise"
29
45
  end
30
46
 
@@ -37,13 +53,13 @@ end
37
53
  ::
38
54
 
39
55
  @param func (resolve: (...) -> (), reject: (...) -> ()) -> ()?
40
- @return Promise<T>
56
+ @return Promise<T...>
41
57
  ]=]
42
- function Promise.new(func)
58
+ function Promise.new<T...>(func: ResolveReject<T...>?): Promise<T...>
43
59
  local self = setmetatable({
44
- _pendingExecuteList = {};
45
- _unconsumedException = true;
46
- _source = ENABLE_TRACEBACK and debug.traceback("Promise.new()", 2) or "";
60
+ _pendingExecuteList = {},
61
+ _unconsumedException = true,
62
+ _source = ENABLE_TRACEBACK and debug.traceback("Promise.new()", 2) or "",
47
63
  }, Promise)
48
64
 
49
65
  if type(func) == "function" then
@@ -57,9 +73,9 @@ end
57
73
  Initializes a new promise with the given function in a spawn wrapper.
58
74
 
59
75
  @param func (resolve: (...) -> (), reject: (...) -> ()) -> ()?
60
- @return Promise<T>
76
+ @return Promise<T...>
61
77
  ]=]
62
- function Promise.spawn(func)
78
+ function Promise.spawn<T...>(func: ResolveReject<T...>): Promise<T...>
63
79
  local self = Promise.new()
64
80
 
65
81
  task.spawn(func, self:_getResolveReject())
@@ -72,9 +88,9 @@ end
72
88
 
73
89
  @param seconds number
74
90
  @param func (resolve: (...) -> (), reject: (...) -> ()) -> ()?
75
- @return Promise<T>
91
+ @return Promise<T...>
76
92
  ]=]
77
- function Promise.delay(seconds, func)
93
+ function Promise.delay<T...>(seconds: number, func: ResolveReject<T...>): Promise<T...>
78
94
  assert(type(seconds) == "number", "Bad seconds")
79
95
  assert(type(func) == "function", "Bad func")
80
96
 
@@ -89,9 +105,9 @@ end
89
105
  Initializes a new promise with the given function in a deferred wrapper.
90
106
 
91
107
  @param func (resolve: (...) -> (), reject: (...) -> ()) -> ()?
92
- @return Promise<T>
108
+ @return Promise<T...>
93
109
  ]=]
94
- function Promise.defer(func)
110
+ function Promise.defer<T...>(func: ResolveReject<T...>): Promise<T...>
95
111
  local self = Promise.new()
96
112
 
97
113
  -- Just the function part of the resolve/reject protocol!
@@ -104,9 +120,9 @@ end
104
120
  Returns a resolved promise with the following values
105
121
 
106
122
  @param ... Values to resolve to
107
- @return Promise<T>
123
+ @return Promise<T...>
108
124
  ]=]
109
- function Promise.resolved(...)
125
+ function Promise.resolved<T...>(...: T...): Promise<T...>
110
126
  local n = select("#", ...)
111
127
  if n == 0 then
112
128
  -- Reuse promise here to save on calls to Promise.resolved()
@@ -129,9 +145,9 @@ end
129
145
  Returns a rejected promise with the following values
130
146
 
131
147
  @param ... Values to reject to
132
- @return Promise<T>
148
+ @return Promise<T...>
133
149
  ]=]
134
- function Promise.rejected(...)
150
+ function Promise.rejected<T...>(...): Promise<()>
135
151
  local n = select("#", ...)
136
152
  if n == 0 then
137
153
  -- Reuse promise here to save on calls to Promise.rejected()
@@ -148,7 +164,7 @@ end
148
164
 
149
165
  @return bool -- True if pending, false otherwise
150
166
  ]=]
151
- function Promise:IsPending()
167
+ function Promise.IsPending<T...>(self: Promise<T...>): boolean
152
168
  return self._pendingExecuteList ~= nil
153
169
  end
154
170
 
@@ -157,7 +173,7 @@ end
157
173
 
158
174
  @return bool -- True if fulfilled
159
175
  ]=]
160
- function Promise:IsFulfilled()
176
+ function Promise.IsFulfilled<T...>(self: Promise<T...>): boolean
161
177
  return self._fulfilled ~= nil
162
178
  end
163
179
 
@@ -166,7 +182,7 @@ end
166
182
 
167
183
  @return bool -- True if rejected
168
184
  ]=]
169
- function Promise:IsRejected()
185
+ function Promise.IsRejected<T...>(self: Promise<T...>): boolean
170
186
  return self._rejected ~= nil
171
187
  end
172
188
 
@@ -177,11 +193,11 @@ end
177
193
  @yields
178
194
  @return T
179
195
  ]=]
180
- function Promise:Wait()
196
+ function Promise.Wait<T...>(self: Promise<T...>): T...
181
197
  if self._fulfilled then
182
198
  return table.unpack(self._fulfilled, 1, self._fulfilled.n)
183
199
  elseif self._rejected then
184
- return error(tostring(self._rejected[1]), 2)
200
+ error(tostring(self._rejected[1]), 2)
185
201
  else
186
202
  local waitingCoroutine = coroutine.running()
187
203
 
@@ -194,14 +210,15 @@ function Promise:Wait()
194
210
  coroutine.yield()
195
211
 
196
212
  if self._rejected then
197
- return error(tostring(self._rejected[1]), 2)
198
- else
213
+ error(tostring(self._rejected[1]), 2)
214
+ elseif self._fulfilled then
199
215
  return table.unpack(self._fulfilled, 1, self._fulfilled.n)
216
+ else
217
+ error("Bad state")
200
218
  end
201
219
  end
202
220
  end
203
221
 
204
-
205
222
  --[=[
206
223
  Yields until the promise is complete, then returns a boolean indicating
207
224
  the result, followed by the values from the promise.
@@ -209,7 +226,7 @@ end
209
226
  @yields
210
227
  @return boolean, T
211
228
  ]=]
212
- function Promise:Yield()
229
+ function Promise.Yield<T...>(self: Promise<T...>): (boolean, T...)
213
230
  if self._fulfilled then
214
231
  return true, table.unpack(self._fulfilled, 1, self._fulfilled.n)
215
232
  elseif self._rejected then
@@ -235,13 +252,12 @@ function Promise:Yield()
235
252
  end
236
253
  end
237
254
 
238
-
239
255
  --[=[
240
256
  Promise resolution procedure, resolves the given values
241
257
 
242
258
  @param ... T
243
259
  ]=]
244
- function Promise:Resolve(...)
260
+ function Promise:Resolve<T...>(...: T...)
245
261
  if not self._pendingExecuteList then
246
262
  return
247
263
  end
@@ -253,7 +269,8 @@ function Promise:Resolve(...)
253
269
  self:Reject("TypeError: Resolved to self")
254
270
  elseif Promise.isPromise(...) then
255
271
  if len > 1 then
256
- local message = string.format("When resolving a promise, extra arguments are discarded! See:\n\n%s", self._source)
272
+ local message =
273
+ string.format("When resolving a promise, extra arguments are discarded! See:\n\n%s", self._source)
257
274
  warn(message)
258
275
  end
259
276
 
@@ -270,7 +287,6 @@ function Promise:Resolve(...)
270
287
  self:_reject(table.pack(...))
271
288
  end
272
289
  end,
273
- nil
274
290
  }
275
291
  elseif promise2._rejected then -- rejected
276
292
  promise2._unconsumedException = false
@@ -282,7 +298,8 @@ function Promise:Resolve(...)
282
298
  end
283
299
  elseif type(...) == "function" then
284
300
  if len > 1 then
285
- local message = string.format("When resolving a function, extra arguments are discarded! See:\n\n%s", self._source)
301
+ local message =
302
+ string.format("When resolving a function, extra arguments are discarded! See:\n\n%s", self._source)
286
303
  warn(message)
287
304
  end
288
305
 
@@ -301,7 +318,7 @@ end
301
318
  @param values { T } -- Params to fulfil with
302
319
  @private
303
320
  ]]
304
- function Promise:_fulfill(values)
321
+ function Promise._fulfill<T...>(self: Promise<T...>, values)
305
322
  if not self._pendingExecuteList then
306
323
  return
307
324
  end
@@ -310,7 +327,7 @@ function Promise:_fulfill(values)
310
327
 
311
328
  local list = self._pendingExecuteList
312
329
  self._pendingExecuteList = nil
313
- for _, data in pairs(list) do
330
+ for _, data in list do
314
331
  self:_executeThen(unpack(data))
315
332
  end
316
333
  end
@@ -319,11 +336,11 @@ end
319
336
  Rejects the promise with the values given
320
337
  @param ... T -- Params to reject with
321
338
  ]=]
322
- function Promise:Reject(...)
339
+ function Promise.Reject<T...>(self: Promise<T...>, ...)
323
340
  self:_reject(table.pack(...))
324
341
  end
325
342
 
326
- function Promise:_reject(values)
343
+ function Promise._reject<T...>(self: Promise<T...>, values)
327
344
  if not self._pendingExecuteList then
328
345
  return
329
346
  end
@@ -332,7 +349,7 @@ function Promise:_reject(values)
332
349
 
333
350
  local list = self._pendingExecuteList
334
351
  self._pendingExecuteList = nil
335
- for _, data in pairs(list) do
352
+ for _, data in list do
336
353
  self:_executeThen(unpack(data))
337
354
  end
338
355
 
@@ -342,10 +359,12 @@ function Promise:_reject(values)
342
359
  -- Yield to end of frame, giving control back to Roblox.
343
360
  -- This is the equivalent of giving something back to a task manager.
344
361
  if self._unconsumedException then
345
- local errOutput = self:_toHumanReadable(self._rejected[1])
362
+ local errOutput = self:_toHumanReadable(values[1])
346
363
 
347
364
  if ENABLE_TRACEBACK then
348
- warn(string.format("[Promise] - Uncaught exception in promise\n\n%q\n\n%s", errOutput, self._source))
365
+ warn(
366
+ string.format("[Promise] - Uncaught exception in promise\n\n%q\n\n%s", errOutput, self._source)
367
+ )
349
368
  else
350
369
  warn(string.format("[Promise] - Uncaught exception in promise: %q", errOutput))
351
370
  end
@@ -354,7 +373,7 @@ function Promise:_reject(values)
354
373
  end
355
374
  end
356
375
 
357
- function Promise:_toHumanReadable(data)
376
+ function Promise._toHumanReadable<T...>(_self: Promise<T...>, data: any): string
358
377
  if type(data) == "table" then
359
378
  local errOutput
360
379
  local ok = pcall(function()
@@ -387,9 +406,9 @@ end
387
406
 
388
407
  @param onFulfilled function -- Called if/when fulfilled with parameters
389
408
  @param onRejected function -- Called if/when rejected with parameters
390
- @return Promise<T>
409
+ @return Promise<T...>
391
410
  ]=]
392
- function Promise:Then(onFulfilled, onRejected)
411
+ function Promise.Then<T...>(self: Promise<T...>, onFulfilled, onRejected)
393
412
  if type(onRejected) == "function" then
394
413
  self._unconsumedException = false
395
414
  end
@@ -411,9 +430,9 @@ end
411
430
 
412
431
  @param onFulfilled function
413
432
  @param onRejected function
414
- @return Promise<T> -- Returns self
433
+ @return Promise<T...> -- Returns self
415
434
  ]=]
416
- function Promise:Tap(onFulfilled, onRejected)
435
+ function Promise.Tap<T...>(self: Promise<T...>, onFulfilled, onRejected)
417
436
  -- Run immediately like then, but we return something safer!
418
437
  local result = self:Then(onFulfilled, onRejected)
419
438
  if result == self then
@@ -443,9 +462,9 @@ end
443
462
  Executes upon pending stop
444
463
 
445
464
  @param func function
446
- @return Promise<T>
465
+ @return Promise<T...>
447
466
  ]=]
448
- function Promise:Finally(func)
467
+ function Promise.Finally<T...>(self: Promise<T...>, func)
449
468
  return self:Then(func, func)
450
469
  end
451
470
 
@@ -453,17 +472,16 @@ end
453
472
  Catch errors from the promise
454
473
 
455
474
  @param onRejected function
456
- @return Promise<T>
475
+ @return Promise<T...>
457
476
  ]=]
458
- function Promise:Catch(onRejected)
477
+ function Promise.Catch<T...>(self: Promise<T...>, onRejected)
459
478
  return self:Then(nil, onRejected)
460
479
  end
461
480
 
462
-
463
481
  --[=[
464
482
  Rejects the current promise. Utility left for Maid task
465
483
  ]=]
466
- function Promise:Destroy()
484
+ function Promise.Destroy<T...>(self: Promise<T...>)
467
485
  self:_reject(EMPTY_PACKED_TUPLE)
468
486
  end
469
487
 
@@ -477,7 +495,7 @@ end
477
495
  @return boolean -- true if resolved, false otherwise.
478
496
  @return any
479
497
  ]=]
480
- function Promise:GetResults()
498
+ function Promise.GetResults<T...>(self: Promise<T...>): (boolean, T...)
481
499
  if self._rejected then
482
500
  return false, table.unpack(self._rejected, 1, self._rejected.n)
483
501
  elseif self._fulfilled then
@@ -487,7 +505,7 @@ function Promise:GetResults()
487
505
  end
488
506
  end
489
507
 
490
- function Promise:_getResolveReject()
508
+ function Promise._getResolveReject<T...>(self: Promise<T...>): (Resolve<T...>, Reject)
491
509
  return function(...)
492
510
  self:Resolve(...)
493
511
  end, function(...)
@@ -500,10 +518,10 @@ end
500
518
 
501
519
  @param onFulfilled function?
502
520
  @param onRejected function?
503
- @param promise2 Promise<T>? -- May be nil. If it is, then we have the option to return self
521
+ @param promise2 Promise<T...>? -- May be nil. If it is, then we have the option to return self
504
522
  @return Promise
505
523
  ]=]
506
- function Promise:_executeThen(onFulfilled, onRejected, promise2)
524
+ function Promise._executeThen<T...>(self: Promise<T...>, onFulfilled, onRejected, promise2)
507
525
  if self._fulfilled then
508
526
  if type(onFulfilled) == "function" then
509
527
  -- If either onFulfilled or onRejected returns a value x, run
@@ -579,4 +597,4 @@ _emptyFulfilledPromise:_fulfill(EMPTY_PACKED_TUPLE)
579
597
  _emptyRejectedPromise = Promise.new()
580
598
  _emptyRejectedPromise:_reject(EMPTY_PACKED_TUPLE)
581
599
 
582
- return Promise
600
+ return Promise
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  @class PromiseRetryUtils
3
4
  ]=]
@@ -9,7 +10,21 @@ local Math = require("Math")
9
10
 
10
11
  local PromiseRetryUtils = {}
11
12
 
12
- function PromiseRetryUtils.retry(callback, options)
13
+ export type RetryOptions = {
14
+ initialWaitTime: number,
15
+ maxAttempts: number,
16
+ printWarning: boolean,
17
+ }
18
+
19
+ --[=[
20
+ Returns a promise that will retry the given callback until it succeeds or the max attempts
21
+ is reached.
22
+
23
+ @param callback function -- Callback that returns a promise
24
+ @param options RetryOptions -- Options for retrying
25
+ @return Promise<T>
26
+ ]=]
27
+ function PromiseRetryUtils.retry<T...>(callback: () -> Promise.Promise<T...>, options: RetryOptions): Promise.Promise<T...>
13
28
  assert(type(options.initialWaitTime) == "number", "Bad initialWaitTime")
14
29
  assert(type(options.maxAttempts) == "number", "Bad maxAttempts")
15
30
  assert(type(options.printWarning) == "boolean", "Bad printWarning")
@@ -39,7 +54,11 @@ function PromiseRetryUtils.retry(callback, options)
39
54
  end
40
55
 
41
56
  isLoopResolved = true
42
- local errorMessage = string.format("Attempted request %d times before failing with error", tostring(lastResults[2]))
57
+ local errorMessage = string.format(
58
+ "Attempted request %d times before failing with error %s",
59
+ options.maxAttempts,
60
+ tostring(lastResults[2])
61
+ )
43
62
  promise:Reject(errorMessage, table.unpack(lastResults, 3, lastResults.n))
44
63
  end)
45
64
 
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Utility methods for promise
3
4
  @class PromiseUtils
@@ -6,6 +7,7 @@
6
7
  local require = require(script.Parent.loader).load(script)
7
8
 
8
9
  local Promise = require("Promise")
10
+ local _Signal = require("Signal")
9
11
 
10
12
  local PromiseUtils = {}
11
13
 
@@ -14,7 +16,7 @@ local PromiseUtils = {}
14
16
  @param promises { Promise<T> }
15
17
  @return Promise<T> -- Promise that resolves with first result
16
18
  ]=]
17
- function PromiseUtils.any(promises)
19
+ function PromiseUtils.any<T...>(promises: { Promise.Promise<T...> }): Promise.Promise<T...>
18
20
  local returnPromise = Promise.new()
19
21
 
20
22
  local function resolve(...)
@@ -25,7 +27,7 @@ function PromiseUtils.any(promises)
25
27
  returnPromise:Reject(...)
26
28
  end
27
29
 
28
- for _, promise in pairs(promises) do
30
+ for _, promise in promises do
29
31
  promise:Then(resolve, reject)
30
32
  end
31
33
 
@@ -38,7 +40,7 @@ end
38
40
  @param seconds number
39
41
  @return Promise
40
42
  ]=]
41
- function PromiseUtils.delayed(seconds)
43
+ function PromiseUtils.delayed(seconds: number): Promise.Promise<()>
42
44
  assert(type(seconds) == "number", "Bad seconds")
43
45
 
44
46
  return Promise.delay(seconds, function(resolve, _reject)
@@ -57,7 +59,7 @@ end
57
59
  @param promises { Promise<T> }
58
60
  @return Promise<T>
59
61
  ]=]
60
- function PromiseUtils.all(promises)
62
+ function PromiseUtils.all<T>(promises: { Promise.Promise<T> }): Promise.Promise<T>
61
63
  if #promises == 0 then
62
64
  return Promise.resolved()
63
65
  elseif #promises == 1 then
@@ -81,14 +83,20 @@ function PromiseUtils.all(promises)
81
83
  end
82
84
  end
83
85
 
84
- for index, promise in pairs(promises) do
86
+ for index, promise in promises do
85
87
  promise:Then(syncronize(index, true), syncronize(index, false))
86
88
  end
87
89
 
88
90
  return returnPromise
89
91
  end
90
92
 
91
- function PromiseUtils.firstSuccessOrLastFailure(promises)
93
+ --[=[
94
+ Keeps on trying promises until one of them succeeds, or reports
95
+ the last failure.
96
+
97
+ @param promises { Promise<T> }
98
+ ]=]
99
+ function PromiseUtils.firstSuccessOrLastFailure<T...>(promises: { Promise.Promise<T...> }): Promise.Promise<T...>
92
100
  if #promises == 0 then
93
101
  return Promise.resolved()
94
102
  elseif #promises == 1 then
@@ -109,10 +117,12 @@ function PromiseUtils.firstSuccessOrLastFailure(promises)
109
117
  if remainingCount == 0 then
110
118
  return returnPromise:Reject(...)
111
119
  end
120
+
121
+ return
112
122
  end
113
123
  end
114
124
 
115
- for _, promise in pairs(promises) do
125
+ for _, promise in promises do
116
126
  promise:Then(syncronize(true), syncronize(false))
117
127
  end
118
128
 
@@ -125,13 +135,13 @@ end
125
135
  @param stateTable any
126
136
  @return Promise<any>
127
137
  ]=]
128
- function PromiseUtils.combine(stateTable)
138
+ function PromiseUtils.combine(stateTable: any): Promise.Promise<any>
129
139
  assert(type(stateTable) == "table", "Bad stateTable")
130
140
 
131
141
  local remainingCount = 0
132
142
  local results = {}
133
143
 
134
- for key, value in pairs(stateTable) do
144
+ for key, value in stateTable do
135
145
  if Promise.isPromise(value) then
136
146
  remainingCount = remainingCount + 1
137
147
  else
@@ -159,7 +169,7 @@ function PromiseUtils.combine(stateTable)
159
169
  end
160
170
  end
161
171
 
162
- for key, value in pairs(stateTable) do
172
+ for key, value in stateTable do
163
173
  if Promise.isPromise(value) then
164
174
  value:Then(syncronize(key, true), syncronize(key, false))
165
175
  end
@@ -175,7 +185,7 @@ end
175
185
  @param promise Promise<T>
176
186
  @return Promise<T>
177
187
  ]=]
178
- function PromiseUtils.invert(promise)
188
+ function PromiseUtils.invert<T...>(promise: Promise.Promise<T...>): Promise.Promise<T...>
179
189
  if promise:IsPending() then
180
190
  return promise:Then(function(...)
181
191
  return Promise.rejected(...)
@@ -183,7 +193,7 @@ function PromiseUtils.invert(promise)
183
193
  return Promise.resolved(...)
184
194
  end)
185
195
  else
186
- local results = {promise:GetResults()}
196
+ local results = { promise:GetResults() }
187
197
  if results[1] then
188
198
  return Promise.rejected(unpack(results, 2))
189
199
  else
@@ -198,12 +208,14 @@ end
198
208
  @param signal Signal<T>
199
209
  @return Promise<T>
200
210
  ]=]
201
- function PromiseUtils.fromSignal(signal)
211
+ function PromiseUtils.fromSignal<T...>(signal: _Signal.Signal<T...>): Promise.Promise<T...>
202
212
  local promise = Promise.new()
203
- local conn
213
+ local conn: _Signal.Connection<T...>?
204
214
 
205
215
  promise:Finally(function()
206
- conn:Disconnect()
216
+ if conn then
217
+ conn:Disconnect()
218
+ end
207
219
  conn = nil
208
220
  end)
209
221
 
@@ -222,7 +234,7 @@ end
222
234
  @param fromPromise Promise<T>
223
235
  @return Promise<T>
224
236
  ]=]
225
- function PromiseUtils.timeout(timeoutTime, fromPromise)
237
+ function PromiseUtils.timeout<T...>(timeoutTime: number, fromPromise: Promise.Promise<T...>): Promise.Promise<T...>
226
238
  assert(type(timeoutTime) == "number", "Bad timeoutTime")
227
239
  assert(fromPromise, "Bad fromPromise")
228
240
 
@@ -1,18 +1,30 @@
1
+ --!strict
1
2
  --[=[
2
3
  Tracks pending promises
3
4
  @class PendingPromiseTracker
4
5
  ]=]
5
6
 
7
+ local require = require(script.Parent.loader).load(script)
8
+
9
+ local _Promise = require("Promise")
10
+
6
11
  local PendingPromiseTracker = {}
7
12
  PendingPromiseTracker.ClassName = "PendingPromiseTracker"
8
13
  PendingPromiseTracker.__index = PendingPromiseTracker
9
14
 
15
+ export type PendingPromiseTracker<T...> = typeof(setmetatable(
16
+ {} :: {
17
+ _pendingPromises: { [_Promise.Promise<T...>]: true },
18
+ },
19
+ PendingPromiseTracker
20
+ ))
21
+
10
22
  --[=[
11
23
  Returns a new pending promise tracker
12
24
 
13
25
  @return PendingPromiseTracker<T>
14
26
  ]=]
15
- function PendingPromiseTracker.new()
27
+ function PendingPromiseTracker.new<T...>(): PendingPromiseTracker<T...>
16
28
  local self = setmetatable({}, PendingPromiseTracker)
17
29
 
18
30
  self._pendingPromises = {}
@@ -22,10 +34,8 @@ end
22
34
 
23
35
  --[=[
24
36
  Adds a new promise to the tracker. If it's not pending it will not add.
25
-
26
- @param promise Promise<T>
27
37
  ]=]
28
- function PendingPromiseTracker:Add(promise)
38
+ function PendingPromiseTracker.Add<T...>(self: PendingPromiseTracker<T...>, promise: _Promise.Promise<T...>)
29
39
  if promise:IsPending() then
30
40
  self._pendingPromises[promise] = true
31
41
  promise:Finally(function()
@@ -36,12 +46,10 @@ end
36
46
 
37
47
  --[=[
38
48
  Gets all of the promises that are pending
39
-
40
- @return { Promise<T> }
41
49
  ]=]
42
- function PendingPromiseTracker:GetAll()
43
- local promises = {}
44
- for promise, _ in pairs(self._pendingPromises) do
50
+ function PendingPromiseTracker.GetAll<T...>(self: PendingPromiseTracker<T...>): { _Promise.Promise<T...> }
51
+ local promises: { _Promise.Promise<T...> } = {}
52
+ for promise: any, _ in self._pendingPromises do
45
53
  table.insert(promises, promise)
46
54
  end
47
55
  return promises
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  @class PromiseInstanceUtils
3
4
  ]=]
@@ -15,7 +16,7 @@ local PromiseInstanceUtils = {}
15
16
  @param instance Instance
16
17
  @return Promise
17
18
  ]=]
18
- function PromiseInstanceUtils.promiseRemoved(instance)
19
+ function PromiseInstanceUtils.promiseRemoved(instance: Instance): Promise.Promise<()>
19
20
  assert(instance:IsDescendantOf(game))
20
21
 
21
22
  local maid = Maid.new()
@@ -17,14 +17,19 @@ local Promise = require("Promise")
17
17
  @return Promise<Instance>
18
18
  @within promiseChild
19
19
  ]=]
20
- return function(parent, name, timeOut)
20
+ return function(parent: Instance, name: string, timeOut: number?): Promise.Promise<Instance>
21
21
  local result = parent:FindFirstChild(name)
22
22
  if result then
23
23
  return Promise.resolved(result)
24
24
  end
25
25
 
26
26
  return Promise.spawn(function(resolve, reject)
27
- local child = parent:WaitForChild(name, timeOut)
27
+ local child: Instance?
28
+ if timeOut then
29
+ child = parent:WaitForChild(name, timeOut)
30
+ else
31
+ child = parent:WaitForChild(name)
32
+ end
28
33
 
29
34
  if child then
30
35
  resolve(child)
@@ -20,7 +20,7 @@ local Promise = require("Promise")
20
20
  @return Promise<Instance>
21
21
  @within promisePropertyValue
22
22
  ]=]
23
- return function(instance, propertyName)
23
+ return function(instance: Instance, propertyName: string)
24
24
  assert(typeof(instance) == "Instance", "Bad instance")
25
25
  assert(type(propertyName) == "string", "Bad propertyName")
26
26
 
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Wraps the task.delay() API in a promise
3
4
 
@@ -8,7 +9,7 @@ local require = require(script.Parent.loader).load(script)
8
9
 
9
10
  local Promise = require("Promise")
10
11
 
11
- return function(time)
12
+ return function(time: number): Promise.Promise<()>
12
13
  return Promise.new(function(resolve, _)
13
14
  task.delay(time, function()
14
15
  resolve()