@flex-development/when 1.0.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/CHANGELOG.md +73 -0
- package/LICENSE.md +28 -0
- package/README.md +558 -0
- package/dist/index.d.mts +196 -0
- package/dist/index.mjs +6 -0
- package/dist/lib/index.mjs +6 -0
- package/dist/lib/is-thenable.mjs +25 -0
- package/dist/lib/when.mjs +62 -0
- package/package.json +161 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
## 1.0.0 (2026-02-18)
|
|
2
|
+
|
|
3
|
+
### :package: Build
|
|
4
|
+
|
|
5
|
+
- [[`89747c3`](https://github.com/flex-development/when/commit/89747c317883b749a9f9ef20702c7a0847db291b)] **ts:** fix dts bundle
|
|
6
|
+
|
|
7
|
+
### :robot: Continuous Integration
|
|
8
|
+
|
|
9
|
+
- [[`8472f72`](https://github.com/flex-development/when/commit/8472f7299ee70065318b2b925fccb926e62ef46d)] **deps:** Bump actions/cache from 5.0.1 to 5.0.3 ([#2](https://github.com/flex-development/when/issues/2))
|
|
10
|
+
- [[`a490ffe`](https://github.com/flex-development/when/commit/a490ffea18095d99f07edba0608c5f517e1e60db)] **deps:** Bump actions/checkout from 6.0.1 to 6.0.2 ([#4](https://github.com/flex-development/when/issues/4))
|
|
11
|
+
- [[`cebe06a`](https://github.com/flex-development/when/commit/cebe06ae414c0bde9b126574cdf40bf5a6ba9311)] **deps:** Bump actions/setup-node from 6.1.0 to 6.2.0 ([#3](https://github.com/flex-development/when/issues/3))
|
|
12
|
+
- [[`34b0da9`](https://github.com/flex-development/when/commit/34b0da9ab276073eaa2675ca2072af7183fff021)] **deps:** Bump streetsidesoftware/cspell-action from 8.1.2 to 8.2.0 ([#1](https://github.com/flex-development/when/issues/1))
|
|
13
|
+
|
|
14
|
+
### :pencil: Documentation
|
|
15
|
+
|
|
16
|
+
- [[`b69462f`](https://github.com/flex-development/when/commit/b69462f9f82ac07ae96920af0f22d57f06567e9f)] use
|
|
17
|
+
- [[`0f9a427`](https://github.com/flex-development/when/commit/0f9a4272e75ef01441e2bf4e5eecc450f0092d2b)] what is this?
|
|
18
|
+
- [[`8391dab`](https://github.com/flex-development/when/commit/8391dabf2049d8eebd9319234ca54e90287e4701)] why not `Promise.resolve`?
|
|
19
|
+
|
|
20
|
+
### :sparkles: Features
|
|
21
|
+
|
|
22
|
+
- [[`0bdbc47`](https://github.com/flex-development/when/commit/0bdbc4740d57624a8f5ec7a33289c7ba5e96a5c5)] `when`
|
|
23
|
+
- [[`aa84d47`](https://github.com/flex-development/when/commit/aa84d47f2d16b53826c936443799af42a74959db)] **lib:** `isPromiseLike`
|
|
24
|
+
- [[`4fab731`](https://github.com/flex-development/when/commit/4fab7311e0fd2e0a909d0d1ce74a1ab478968ec8)] **lib:** `isThenable`
|
|
25
|
+
- [[`507ad2b`](https://github.com/flex-development/when/commit/507ad2b3cdc8577b4e8c8b0cf5e2adbc7641a4a6)] **types:** `Awaitable`
|
|
26
|
+
|
|
27
|
+
### :bug: Fixes
|
|
28
|
+
|
|
29
|
+
- [[`5ef99bb`](https://github.com/flex-development/when/commit/5ef99bb77f0b35c3670d72ddba4f77a4bb506235)] **pkg:** default export
|
|
30
|
+
- [[`21ec642`](https://github.com/flex-development/when/commit/21ec642d83071e1d965a23dec609c4d1c662dd84)] **pkg:** library exports
|
|
31
|
+
|
|
32
|
+
### :house_with_garden: Housekeeping
|
|
33
|
+
|
|
34
|
+
- [[`4cca93d`](https://github.com/flex-development/when/commit/4cca93dda1fbc6dbd863405ecfe88259087c2463)] fix release workflow
|
|
35
|
+
- [[`a5418df`](https://github.com/flex-development/when/commit/a5418dfc0cae7c2ca231e735665d76b625615edc)] initial commit
|
|
36
|
+
|
|
37
|
+
## 1.0.0 (2026-02-18)
|
|
38
|
+
|
|
39
|
+
### :package: Build
|
|
40
|
+
|
|
41
|
+
- [[`89747c3`](https://github.com/flex-development/when/commit/89747c317883b749a9f9ef20702c7a0847db291b)] **ts:** fix dts bundle
|
|
42
|
+
|
|
43
|
+
### :robot: Continuous Integration
|
|
44
|
+
|
|
45
|
+
- [[`8472f72`](https://github.com/flex-development/when/commit/8472f7299ee70065318b2b925fccb926e62ef46d)] **deps:** Bump actions/cache from 5.0.1 to 5.0.3 ([#2](https://github.com/flex-development/when/issues/2))
|
|
46
|
+
- [[`a490ffe`](https://github.com/flex-development/when/commit/a490ffea18095d99f07edba0608c5f517e1e60db)] **deps:** Bump actions/checkout from 6.0.1 to 6.0.2 ([#4](https://github.com/flex-development/when/issues/4))
|
|
47
|
+
- [[`cebe06a`](https://github.com/flex-development/when/commit/cebe06ae414c0bde9b126574cdf40bf5a6ba9311)] **deps:** Bump actions/setup-node from 6.1.0 to 6.2.0 ([#3](https://github.com/flex-development/when/issues/3))
|
|
48
|
+
- [[`34b0da9`](https://github.com/flex-development/when/commit/34b0da9ab276073eaa2675ca2072af7183fff021)] **deps:** Bump streetsidesoftware/cspell-action from 8.1.2 to 8.2.0 ([#1](https://github.com/flex-development/when/issues/1))
|
|
49
|
+
|
|
50
|
+
### :pencil: Documentation
|
|
51
|
+
|
|
52
|
+
- [[`b69462f`](https://github.com/flex-development/when/commit/b69462f9f82ac07ae96920af0f22d57f06567e9f)] use
|
|
53
|
+
- [[`0f9a427`](https://github.com/flex-development/when/commit/0f9a4272e75ef01441e2bf4e5eecc450f0092d2b)] what is this?
|
|
54
|
+
- [[`8391dab`](https://github.com/flex-development/when/commit/8391dabf2049d8eebd9319234ca54e90287e4701)] why not `Promise.resolve`?
|
|
55
|
+
|
|
56
|
+
### :sparkles: Features
|
|
57
|
+
|
|
58
|
+
- [[`0bdbc47`](https://github.com/flex-development/when/commit/0bdbc4740d57624a8f5ec7a33289c7ba5e96a5c5)] `when`
|
|
59
|
+
- [[`aa84d47`](https://github.com/flex-development/when/commit/aa84d47f2d16b53826c936443799af42a74959db)] **lib:** `isPromiseLike`
|
|
60
|
+
- [[`4fab731`](https://github.com/flex-development/when/commit/4fab7311e0fd2e0a909d0d1ce74a1ab478968ec8)] **lib:** `isThenable`
|
|
61
|
+
- [[`507ad2b`](https://github.com/flex-development/when/commit/507ad2b3cdc8577b4e8c8b0cf5e2adbc7641a4a6)] **types:** `Awaitable`
|
|
62
|
+
|
|
63
|
+
### :bug: Fixes
|
|
64
|
+
|
|
65
|
+
- [[`5ef99bb`](https://github.com/flex-development/when/commit/5ef99bb77f0b35c3670d72ddba4f77a4bb506235)] **pkg:** default export
|
|
66
|
+
- [[`21ec642`](https://github.com/flex-development/when/commit/21ec642d83071e1d965a23dec609c4d1c662dd84)] **pkg:** library exports
|
|
67
|
+
|
|
68
|
+
### :house_with_garden: Housekeeping
|
|
69
|
+
|
|
70
|
+
- [[`a5418df`](https://github.com/flex-development/when/commit/a5418dfc0cae7c2ca231e735665d76b625615edc)] initial commit
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022, Flex Development, LLC All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
6
|
+
are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its contributors
|
|
16
|
+
may be used to endorse or promote products derived from this software without
|
|
17
|
+
specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
20
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
21
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
23
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
24
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
25
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
26
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
28
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
# \:timer\_clock: when
|
|
2
|
+
|
|
3
|
+
[](https://github.com/flex-development/when/releases/latest)
|
|
4
|
+
[](https://npmjs.com/package/@flex-development/when)
|
|
5
|
+
[](https://www.npmcharts.com/compare/@flex-development/when?interval=30)
|
|
6
|
+
[](https://packagephobia.now.sh/result?p=@flex-development/when)
|
|
7
|
+
[](https://codecov.io/github/flex-development/when)
|
|
8
|
+
[](https://github.com/voxpelli/badges-cjs-esm)
|
|
9
|
+
[](LICENSE.md)
|
|
10
|
+
[](https://conventionalcommits.org)
|
|
11
|
+
[](https://typescriptlang.org)
|
|
12
|
+
[](https://vitest.dev)
|
|
13
|
+
[](https://yarnpkg.com)
|
|
14
|
+
|
|
15
|
+
like `.then`, but for synchronous values *and* thenables.
|
|
16
|
+
|
|
17
|
+
## Contents
|
|
18
|
+
|
|
19
|
+
- [What is this?](#what-is-this)
|
|
20
|
+
- [Why not `Promise.resolve`?](#why-not-promiseresolve)
|
|
21
|
+
- [Install](#install)
|
|
22
|
+
- [Use](#use)
|
|
23
|
+
- [Chain a synchronous value](#chain-a-synchronous-value)
|
|
24
|
+
- [Chain a *thenable*](#chain-a-thenable)
|
|
25
|
+
- [Pass arguments to the chain callback](#pass-arguments-to-the-chain-callback)
|
|
26
|
+
- [Handle rejections / thrown errors](#handle-rejections--thrown-errors)
|
|
27
|
+
- [Bind `this` context](#bind-this-context)
|
|
28
|
+
- [Use an options object](#use-an-options-object)
|
|
29
|
+
- [API](#api)
|
|
30
|
+
- [`isThenable<T>(value)`][isthenable]
|
|
31
|
+
- [`when<[T][, Next][, Args][, Self]>(value, chain[, reject][, context][, ...args])`][when]
|
|
32
|
+
- [Types](#types)
|
|
33
|
+
- [`Awaitable<T>`][awaitable]
|
|
34
|
+
- [`Chain<[T][, Next][, Args][, Self]>`][chain]
|
|
35
|
+
- [`Options<[T][, Next][, Args][, Self]>`][options]
|
|
36
|
+
- [`Reject<[Next][, Fail][, Self]>`][reject]
|
|
37
|
+
- [Glossary](#glossary)
|
|
38
|
+
- [Project](#project)
|
|
39
|
+
- [Version](#version)
|
|
40
|
+
- [Contribute](#contribute)
|
|
41
|
+
|
|
42
|
+
## What is this?
|
|
43
|
+
|
|
44
|
+
`when` is a small, but useful package for chaining a callback
|
|
45
|
+
onto an [awaitable][] (a value or a [*thenable*][thenable]).
|
|
46
|
+
|
|
47
|
+
For thenable values, `.then` is used to invoke the callback after resolution.
|
|
48
|
+
Otherwise, the callback is called immediately.
|
|
49
|
+
This makes it easy to write one code path that supports both synchronous and asynchronous values.
|
|
50
|
+
|
|
51
|
+
`when` is especially useful in libraries supporting awaitable APIs or libraries that accept user-provided hooks,
|
|
52
|
+
loaders, or resolvers that may or may not return promises.
|
|
53
|
+
|
|
54
|
+
### Why not `Promise.resolve`?
|
|
55
|
+
|
|
56
|
+
`when` preserves synchronous values when possible, thus avoiding microtask scheduling and needless promise-allocation
|
|
57
|
+
for these values, as well as making it a great choice for libraries offering API flexibility.
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
This package is [ESM only][esm].
|
|
62
|
+
|
|
63
|
+
In Node.js (version 20+) with [yarn][]:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
yarn add @flex-development/when
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
<blockquote>
|
|
70
|
+
<small>
|
|
71
|
+
See <a href='https://yarnpkg.com/protocol/git'>Git - Protocols | Yarn</a>
|
|
72
|
+
for details regarding installing from Git.
|
|
73
|
+
</small>
|
|
74
|
+
</blockquote>
|
|
75
|
+
|
|
76
|
+
In Deno with [`esm.sh`][esmsh]:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { when } from 'https://esm.sh/@flex-development/when'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
In browsers with [`esm.sh`][esmsh]:
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<script type="module">
|
|
86
|
+
import { when } from 'https://esm.sh/@flex-development/when'
|
|
87
|
+
</script>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Use
|
|
91
|
+
|
|
92
|
+
### Chain a synchronous value
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { isThenable, when, type Awaitable } from '@flex-development/when'
|
|
96
|
+
import { ok } from 'devlop'
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The result.
|
|
100
|
+
*
|
|
101
|
+
* @const {Awaitable<number>} result
|
|
102
|
+
*/
|
|
103
|
+
const result: Awaitable<number> = when(0, n => n + 1)
|
|
104
|
+
|
|
105
|
+
ok(!isThenable(result), 'expected `result` to not be thenable')
|
|
106
|
+
console.dir(result) // 1
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Chain a [*thenable*][thenable]
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { isThenable, when, type Awaitable } from '@flex-development/when'
|
|
113
|
+
import { ok } from 'devlop'
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The result.
|
|
117
|
+
*
|
|
118
|
+
* @const {Awaitable<number>} result
|
|
119
|
+
*/
|
|
120
|
+
const result: Awaitable<number> = when(Promise.resolve(2), n => n + 1)
|
|
121
|
+
|
|
122
|
+
ok(isThenable(result), 'expected `result` to be thenable')
|
|
123
|
+
console.dir(await result) // 3
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Pass arguments to the chain callback
|
|
127
|
+
|
|
128
|
+
Arguments are passed first, and the resolved value is passed last.
|
|
129
|
+
|
|
130
|
+
When the `value` passed to `when` is not [*thenable*][thenable], the resolved value is the same `value`.
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import when, { type Awaitable } from '@flex-development/when'
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The result.
|
|
137
|
+
*
|
|
138
|
+
* @const {Awaitable<number>} result
|
|
139
|
+
*/
|
|
140
|
+
const result: Awaitable<number> = when(1, Math.min, null, undefined, 2, 3, 4)
|
|
141
|
+
|
|
142
|
+
console.dir(result) // 1
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Handle rejections / thrown errors
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import when, { type Awaitable } from '@flex-development/when'
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The thenable value.
|
|
152
|
+
*
|
|
153
|
+
* @const {PromiseLike<never>} value
|
|
154
|
+
*/
|
|
155
|
+
const value: PromiseLike<never> = new Promise((resolve, reject) => {
|
|
156
|
+
return void reject(new Error('nope', { cause: { url: import.meta.url } }))
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The result.
|
|
161
|
+
*
|
|
162
|
+
* @const {Awaitable<boolean>} result
|
|
163
|
+
*/
|
|
164
|
+
const result: Awaitable<boolean> = when(value, chain, reject)
|
|
165
|
+
|
|
166
|
+
console.dir(await result) // false
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @this {void}
|
|
170
|
+
*
|
|
171
|
+
* @return {true}
|
|
172
|
+
* The success result
|
|
173
|
+
*/
|
|
174
|
+
function chain(this: void): true {
|
|
175
|
+
return true
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @this {void}
|
|
180
|
+
*
|
|
181
|
+
* @param {Error} e
|
|
182
|
+
* The error to handle
|
|
183
|
+
* @return {false}
|
|
184
|
+
* The failure result
|
|
185
|
+
*/
|
|
186
|
+
function reject(this: void, e: Error): false {
|
|
187
|
+
return console.dir(e), false
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Bind `this` context
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
import when, { type Awaitable } from '@flex-development/when'
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The `this` context.
|
|
198
|
+
*/
|
|
199
|
+
type Context = { prefix: string }
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* The result.
|
|
203
|
+
*
|
|
204
|
+
* @const {Awaitable<string>} result
|
|
205
|
+
*/
|
|
206
|
+
const result: Awaitable<string> = when(13, id, null, { prefix: 'id:' })
|
|
207
|
+
|
|
208
|
+
console.log(result) // 'id:13'
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @this {Context}
|
|
212
|
+
*
|
|
213
|
+
* @param {number | string} num
|
|
214
|
+
* The id number
|
|
215
|
+
* @return {string}
|
|
216
|
+
* The id string
|
|
217
|
+
*/
|
|
218
|
+
function id(this: Context, num: number | string): string {
|
|
219
|
+
return this.prefix + num
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Use an options object
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
import when, { type Awaitable } from '@flex-development/when'
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* The `this` context.
|
|
230
|
+
*/
|
|
231
|
+
type Context = { errors: Error[] }
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* The thenable value.
|
|
235
|
+
*
|
|
236
|
+
* @const {Promise<number>} value
|
|
237
|
+
*/
|
|
238
|
+
const value: Promise<number> = new Promise(resolve => resolve(3))
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The result.
|
|
242
|
+
*
|
|
243
|
+
* @const {Awaitable<number | undefined>} result
|
|
244
|
+
*/
|
|
245
|
+
const result: Awaitable<number | undefined> = when(value, {
|
|
246
|
+
args: [39],
|
|
247
|
+
chain: divide,
|
|
248
|
+
context: { errors: [] },
|
|
249
|
+
reject
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
console.dir(await result) // 13
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @this {void}
|
|
256
|
+
*
|
|
257
|
+
* @param {number} dividend
|
|
258
|
+
* The number to divide
|
|
259
|
+
* @param {number} divisor
|
|
260
|
+
* The number to divide by
|
|
261
|
+
* @return {number}
|
|
262
|
+
* The quotient
|
|
263
|
+
*/
|
|
264
|
+
function divide(this: void, dividend: number, divisor: number): number {
|
|
265
|
+
return dividend / divisor
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @this {Context}
|
|
270
|
+
*
|
|
271
|
+
* @param {Error} e
|
|
272
|
+
* The error to handle
|
|
273
|
+
* @return {undefined}
|
|
274
|
+
*/
|
|
275
|
+
function reject(this: Context, e: Error): undefined {
|
|
276
|
+
return void this.errors.push(e)
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## API
|
|
281
|
+
|
|
282
|
+
`when` exports the identifiers listed below.
|
|
283
|
+
|
|
284
|
+
The default export is [`when`][when].
|
|
285
|
+
|
|
286
|
+
### `isThenable<T>(value)`
|
|
287
|
+
|
|
288
|
+
Check if `value` looks like a [*thenable*][thenable].
|
|
289
|
+
|
|
290
|
+
> 👉 **Note**: Also exported as `isPromiseLike`.
|
|
291
|
+
|
|
292
|
+
#### Type Parameters
|
|
293
|
+
|
|
294
|
+
- `T` (`any`)
|
|
295
|
+
— the resolved value
|
|
296
|
+
|
|
297
|
+
#### Parameters
|
|
298
|
+
|
|
299
|
+
- `value` (`unknown`)
|
|
300
|
+
— the thing to check
|
|
301
|
+
|
|
302
|
+
#### Returns
|
|
303
|
+
|
|
304
|
+
(`value is PromiseLike<T>`) `true` if `value` is a thenable, `false` otherwise
|
|
305
|
+
|
|
306
|
+
<!--lint disable-->
|
|
307
|
+
|
|
308
|
+
### `when<[T][, Next][, Args][, Self]>(value, chain[, reject][, context][, ...args])`
|
|
309
|
+
|
|
310
|
+
<!--lint enable-->
|
|
311
|
+
|
|
312
|
+
Chain a callback, calling the function after `value` is resolved, or immediately if `value` is not thenable.
|
|
313
|
+
|
|
314
|
+
#### Overloads
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
function when<
|
|
318
|
+
T,
|
|
319
|
+
Next = any,
|
|
320
|
+
Args extends any[] = any[],
|
|
321
|
+
Self = unknown
|
|
322
|
+
>(
|
|
323
|
+
this: void,
|
|
324
|
+
value: Awaitable<T>,
|
|
325
|
+
chain: Chain<T, Next, Args, Self>,
|
|
326
|
+
reject?: Reject<Next, any, Self> | null | undefined,
|
|
327
|
+
context?: Self | null | undefined,
|
|
328
|
+
...args: Args
|
|
329
|
+
): Awaitable<Next>
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
```ts
|
|
333
|
+
function when<
|
|
334
|
+
T,
|
|
335
|
+
Next = any,
|
|
336
|
+
Args extends any[] = any[],
|
|
337
|
+
Self = unknown
|
|
338
|
+
>(
|
|
339
|
+
this: void,
|
|
340
|
+
value: Awaitable<T>,
|
|
341
|
+
chain: Options<T, Next, Args, Self>
|
|
342
|
+
): Awaitable<Next>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### Type Parameters
|
|
346
|
+
|
|
347
|
+
- `T` (`any`)
|
|
348
|
+
— the previously resolved value
|
|
349
|
+
- `Next` (`any`, optional)
|
|
350
|
+
— the next resolved value
|
|
351
|
+
- **default**: `any`
|
|
352
|
+
- `Args` (`readonly any[]`, optional)
|
|
353
|
+
— the function arguments
|
|
354
|
+
- **default**: `any[]`
|
|
355
|
+
- `Self` (`any`, optional)
|
|
356
|
+
— the `this` context
|
|
357
|
+
- **default**: `unknown`
|
|
358
|
+
|
|
359
|
+
#### Parameters
|
|
360
|
+
|
|
361
|
+
- `value` ([`Awaitable<T>`][awaitable])
|
|
362
|
+
— the promise or the resolved value
|
|
363
|
+
- `chain` ([`Chain<T, Next, Args, Self>`][chain] | [`Options<T, Next, Args, Self>`][options])
|
|
364
|
+
— the chain callback or options for chaining
|
|
365
|
+
- `reject` ([`Reject<Next, any, Self>`][reject] | `null` | `undefined`)
|
|
366
|
+
— the callback to fire when a promise is rejected or an error is thrown
|
|
367
|
+
- `context` (`Self` | `null` | `undefined`)
|
|
368
|
+
— the `this` context of the chain and error callbacks
|
|
369
|
+
- `...args` (`Args`)
|
|
370
|
+
— the arguments to pass to the chain callback
|
|
371
|
+
|
|
372
|
+
#### Returns
|
|
373
|
+
|
|
374
|
+
([`Awaitable<Next>`][awaitable]) The next promise or value
|
|
375
|
+
|
|
376
|
+
## Types
|
|
377
|
+
|
|
378
|
+
This package is fully typed with [TypeScript][].
|
|
379
|
+
|
|
380
|
+
### `Awaitable<T>`
|
|
381
|
+
|
|
382
|
+
A synchronous or [*thenable*][thenable] value (`type`).
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
type Awaitable<T> = PromiseLike<T> | T
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### Type Parameters
|
|
389
|
+
|
|
390
|
+
- `T` (`any`)
|
|
391
|
+
— the resolved value
|
|
392
|
+
|
|
393
|
+
### `Chain<[T][, Next][, Args][, Self]>`
|
|
394
|
+
|
|
395
|
+
A chain callback (`type`).
|
|
396
|
+
|
|
397
|
+
```ts
|
|
398
|
+
type Chain<
|
|
399
|
+
T = any,
|
|
400
|
+
Next = any,
|
|
401
|
+
Args extends readonly any[] = any[],
|
|
402
|
+
Self = unknown
|
|
403
|
+
> = (this: Self, ...params: [...Args, T]) => Awaitable<Next>
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
#### Type Parameters
|
|
407
|
+
|
|
408
|
+
- `T` (`any`, optional)
|
|
409
|
+
— the previously resolved value
|
|
410
|
+
- **default**: `any`
|
|
411
|
+
- `Next` (`any`, optional)
|
|
412
|
+
— the next resolved value
|
|
413
|
+
- **default**: `any`
|
|
414
|
+
- `Args` (`readonly any[]`, optional)
|
|
415
|
+
— the function arguments
|
|
416
|
+
- **default**: `any[]`
|
|
417
|
+
- `Self` (`any`, optional)
|
|
418
|
+
— the `this` context
|
|
419
|
+
- **default**: `unknown`
|
|
420
|
+
|
|
421
|
+
#### Parameters
|
|
422
|
+
|
|
423
|
+
- **`this`** (`Self`)
|
|
424
|
+
- `...params` (`[...Args, T]`)
|
|
425
|
+
— the function parameters, with the last being the previously resolved value.
|
|
426
|
+
in cases where a promise is not being resolved, this is the same `value` passed to `when`
|
|
427
|
+
|
|
428
|
+
#### Returns
|
|
429
|
+
|
|
430
|
+
([`Awaitable<Next>`][awaitable]) The next promise or value
|
|
431
|
+
|
|
432
|
+
### `Options<[T][, Next][, Args][, Self]>`
|
|
433
|
+
|
|
434
|
+
Options for chaining (`interface`).
|
|
435
|
+
|
|
436
|
+
```ts
|
|
437
|
+
interface Options<
|
|
438
|
+
T = any,
|
|
439
|
+
Next = any,
|
|
440
|
+
Args extends readonly any[] = any[],
|
|
441
|
+
Self = any
|
|
442
|
+
> { /* ... */ }
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
#### Type Parameters
|
|
446
|
+
|
|
447
|
+
- `T` (`any`, optional)
|
|
448
|
+
— the previously resolved value
|
|
449
|
+
- **default**: `any`
|
|
450
|
+
- `Next` (`any`, optional)
|
|
451
|
+
— the next resolved value
|
|
452
|
+
- **default**: `any`
|
|
453
|
+
- `Args` (`readonly any[]`, optional)
|
|
454
|
+
— the chain function arguments
|
|
455
|
+
- **default**: `any[]`
|
|
456
|
+
- `Self` (`any`, optional)
|
|
457
|
+
— the `this` context
|
|
458
|
+
- **default**: `any`
|
|
459
|
+
|
|
460
|
+
#### Properties
|
|
461
|
+
|
|
462
|
+
- `args?` (`Args` | `null` | `undefined`)
|
|
463
|
+
— the arguments to pass to the `chain` callback
|
|
464
|
+
- `chain` ([`Chain<T, Next, Args, Self>`][chain])
|
|
465
|
+
— the chain callback
|
|
466
|
+
- `context?` (`Self` | `null` | `undefined`)
|
|
467
|
+
— the `this` context of the `chain` and `reject` callbacks
|
|
468
|
+
- `reject?` ([`Reject<Next, any, Self>`][reject] | `null` | `undefined`)
|
|
469
|
+
— the callback to fire when a promise is rejected or an error is thrown
|
|
470
|
+
|
|
471
|
+
### `Reject<[Next][, Fail][, Self]>`
|
|
472
|
+
|
|
473
|
+
The callback to fire when a promise is rejected or an error is thrown from a synchronous function (`type`).
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
type Reject<
|
|
477
|
+
Next = any,
|
|
478
|
+
Fail = any,
|
|
479
|
+
Self = unknown
|
|
480
|
+
> = (this: Self, e: Fail) => Awaitable<Next>
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
#### Type Parameters
|
|
484
|
+
|
|
485
|
+
- `Next` (`any`, optional)
|
|
486
|
+
— the next resolved value
|
|
487
|
+
- **default**: `any`
|
|
488
|
+
- `Fail` (`any`, optional)
|
|
489
|
+
— the error to handle
|
|
490
|
+
- **default**: `any`
|
|
491
|
+
- `Self` (`any`, optional)
|
|
492
|
+
— the `this` context
|
|
493
|
+
- **default**: `unknown`
|
|
494
|
+
|
|
495
|
+
#### Parameters
|
|
496
|
+
|
|
497
|
+
- **`this`** (`Self`)
|
|
498
|
+
- `e` (`Fail`)
|
|
499
|
+
— the error
|
|
500
|
+
|
|
501
|
+
#### Returns
|
|
502
|
+
|
|
503
|
+
([`Awaitable<Next>`][awaitable]) The next promise or value
|
|
504
|
+
|
|
505
|
+
## Glossary
|
|
506
|
+
|
|
507
|
+
### *awaitable*
|
|
508
|
+
|
|
509
|
+
A synchronous or [*thenable*][thenable] value.
|
|
510
|
+
|
|
511
|
+
### *thenable*
|
|
512
|
+
|
|
513
|
+
An object or function with a `.then` method.
|
|
514
|
+
|
|
515
|
+
JavaScript engines use duck-typing for promises.
|
|
516
|
+
Structures with a `.then` method will be treated as promise-like objects, and work with built-in mechanisms
|
|
517
|
+
like [`Promise.resolve`][promise-resolve] and the [`await` keyword][await] like native promises.
|
|
518
|
+
|
|
519
|
+
## Project
|
|
520
|
+
|
|
521
|
+
### Version
|
|
522
|
+
|
|
523
|
+
when adheres to [semver][].
|
|
524
|
+
|
|
525
|
+
### Contribute
|
|
526
|
+
|
|
527
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
528
|
+
|
|
529
|
+
This project has a [code of conduct](./CODE_OF_CONDUCT.md).
|
|
530
|
+
By interacting with this repository, organization, or community you agree to abide by its terms.
|
|
531
|
+
|
|
532
|
+
[await]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/await
|
|
533
|
+
|
|
534
|
+
[awaitable]: #awaitablet
|
|
535
|
+
|
|
536
|
+
[chain]: #chaint-next-args-self
|
|
537
|
+
|
|
538
|
+
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
|
|
539
|
+
|
|
540
|
+
[esmsh]: https://esm.sh
|
|
541
|
+
|
|
542
|
+
[isthenable]: #isthenabletvalue
|
|
543
|
+
|
|
544
|
+
[options]: #optionst-next-args-self
|
|
545
|
+
|
|
546
|
+
[promise-resolve]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve
|
|
547
|
+
|
|
548
|
+
[reject]: #rejectnext-fail-self
|
|
549
|
+
|
|
550
|
+
[semver]: https://semver.org
|
|
551
|
+
|
|
552
|
+
[thenable]: #thenable
|
|
553
|
+
|
|
554
|
+
[typescript]: https://www.typescriptlang.org
|
|
555
|
+
|
|
556
|
+
[when]: #whent-next-args-selfvalue-chain-reject-context-args
|
|
557
|
+
|
|
558
|
+
[yarn]: https://yarnpkg.com
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Interfaces - Options
|
|
3
|
+
* @module when/interfaces/Options
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Options for chaining.
|
|
8
|
+
*
|
|
9
|
+
* @template {any} [T=any]
|
|
10
|
+
* The previously resolved value
|
|
11
|
+
* @template {any} [Next=any]
|
|
12
|
+
* The next resolved value
|
|
13
|
+
* @template {ReadonlyArray<any>} [Args=any[]]
|
|
14
|
+
* The chain function arguments
|
|
15
|
+
* @template {any} [Self=any]
|
|
16
|
+
* The `this` context
|
|
17
|
+
*/
|
|
18
|
+
interface Options<T = any, Next = any, Args extends readonly any[] = any[], Self = any> {
|
|
19
|
+
/**
|
|
20
|
+
* The arguments to pass to the {@linkcode chain} callback.
|
|
21
|
+
*/
|
|
22
|
+
args?: Args | null | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The chain callback.
|
|
25
|
+
*
|
|
26
|
+
* @see {@linkcode Chain}
|
|
27
|
+
*/
|
|
28
|
+
chain: Chain<T, Next, Args, Self>;
|
|
29
|
+
/**
|
|
30
|
+
* The `this` context of the {@linkcode chain}
|
|
31
|
+
* and {@linkcode reject} callbacks.
|
|
32
|
+
*/
|
|
33
|
+
context?: Self | null | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* The callback to fire when a promise is rejected or an error is thrown.
|
|
36
|
+
*
|
|
37
|
+
* @see {@linkcode Reject}
|
|
38
|
+
*/
|
|
39
|
+
reject?: Reject<Next, any, Self> | null | undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @file isThenable
|
|
44
|
+
* @module when/lib/isThenable
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* Check if `value` looks like a thenable.
|
|
48
|
+
*
|
|
49
|
+
* @template {any} T
|
|
50
|
+
* The resolved value
|
|
51
|
+
*
|
|
52
|
+
* @this {void}
|
|
53
|
+
*
|
|
54
|
+
* @param {unknown} value
|
|
55
|
+
* The thing to check
|
|
56
|
+
* @return {value is PromiseLike<T>}
|
|
57
|
+
* `true` if `value` is a thenable, `false` otherwise
|
|
58
|
+
*/
|
|
59
|
+
declare function isThenable<T>(this: void, value: unknown): value is PromiseLike<T>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @file when
|
|
63
|
+
* @module when/lib/when
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Chain a callback, calling the function after `value` is resolved,
|
|
68
|
+
* or immediately if `value` is not thenable.
|
|
69
|
+
*
|
|
70
|
+
* @see {@linkcode Awaitable}
|
|
71
|
+
* @see {@linkcode Chain}
|
|
72
|
+
* @see {@linkcode Reject}
|
|
73
|
+
*
|
|
74
|
+
* @template {any} T
|
|
75
|
+
* The previously resolved value
|
|
76
|
+
* @template {any} [Next=any]
|
|
77
|
+
* The next resolved value
|
|
78
|
+
* @template {ReadonlyArray<any>} [Args=any[]]
|
|
79
|
+
* The chain function arguments
|
|
80
|
+
* @template {any} [Self=any]
|
|
81
|
+
* The `this` context
|
|
82
|
+
*
|
|
83
|
+
* @this {void}
|
|
84
|
+
*
|
|
85
|
+
* @param {Awaitable<T>} value
|
|
86
|
+
* The promise or the resolved value
|
|
87
|
+
* @param {Chain<T, Next, Args, Self>} chain
|
|
88
|
+
* The chain callback
|
|
89
|
+
* @param {Reject<Next, any, Self>} [reject]
|
|
90
|
+
* The callback to fire when a promise is rejected or an error is thrown
|
|
91
|
+
* @param {Self | null | undefined} [context]
|
|
92
|
+
* The `this` context of the chain and error callbacks
|
|
93
|
+
* @param {Args} args
|
|
94
|
+
* The arguments to pass to the chain callback
|
|
95
|
+
* @return {Awaitable<Next>}
|
|
96
|
+
* The next promise or value
|
|
97
|
+
*/
|
|
98
|
+
declare function when<T, Next = any, Args extends any[] = any[], Self = unknown>(this: void, value: Awaitable<T>, chain: Chain<T, Next, Args, Self>, reject?: Reject<Next, any, Self> | null | undefined, context?: Self | null | undefined, ...args: Args): Awaitable<Next>;
|
|
99
|
+
/**
|
|
100
|
+
* Chain a callback, calling the function after `value` is resolved,
|
|
101
|
+
* or immediately if `value` is not thenable.
|
|
102
|
+
*
|
|
103
|
+
* @see {@linkcode Awaitable}
|
|
104
|
+
* @see {@linkcode Options}
|
|
105
|
+
*
|
|
106
|
+
* @template {any} T
|
|
107
|
+
* The previously resolved value
|
|
108
|
+
* @template {any} [Next=any]
|
|
109
|
+
* The next resolved value
|
|
110
|
+
* @template {ReadonlyArray<any>} [Args=any[]]
|
|
111
|
+
* The chain function arguments
|
|
112
|
+
* @template {any} [Self=unknown]
|
|
113
|
+
* The `this` context
|
|
114
|
+
*
|
|
115
|
+
* @this {void}
|
|
116
|
+
*
|
|
117
|
+
* @param {Awaitable<T>} value
|
|
118
|
+
* The promise or the resolved value
|
|
119
|
+
* @param {Options<T, Next, Args, Self>} chain
|
|
120
|
+
* Options for chaining
|
|
121
|
+
* @return {Awaitable<Next>}
|
|
122
|
+
* The next promise or value
|
|
123
|
+
*/
|
|
124
|
+
declare function when<T, Next = any, Args extends any[] = any[], Self = unknown>(this: void, value: Awaitable<T>, chain: Options<T, Next, Args, Self>): Awaitable<Next>;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @file Type Aliases - Awaitable
|
|
128
|
+
* @module when/types/Awaitable
|
|
129
|
+
*/
|
|
130
|
+
/**
|
|
131
|
+
* A synchronous or thenable value.
|
|
132
|
+
*
|
|
133
|
+
* @template {any} T
|
|
134
|
+
* The resolved value
|
|
135
|
+
*/
|
|
136
|
+
type Awaitable<T> = PromiseLike<T> | T;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @file Type Aliases - Chain
|
|
140
|
+
* @module when/types/Chain
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* A chain callback.
|
|
145
|
+
*
|
|
146
|
+
* @see {@linkcode Awaitable}
|
|
147
|
+
*
|
|
148
|
+
* @template {any} [T=any]
|
|
149
|
+
* The previously resolved value
|
|
150
|
+
* @template {any} [Next=any]
|
|
151
|
+
* The next resolved value
|
|
152
|
+
* @template {ReadonlyArray<any>} [Args=any[]]
|
|
153
|
+
* The function arguments
|
|
154
|
+
* @template {any} [Self=unknown]
|
|
155
|
+
* The `this` context
|
|
156
|
+
*
|
|
157
|
+
* @this {Self}
|
|
158
|
+
*
|
|
159
|
+
* @param {[...Args, T]} params
|
|
160
|
+
* The function parameters, with the last being the previously resolved value.\
|
|
161
|
+
* In cases where a promise is not being resolved,
|
|
162
|
+
* this is the same `value` passed to `when`
|
|
163
|
+
* @return {Awaitable<Next>}
|
|
164
|
+
* The next promise or value
|
|
165
|
+
*/
|
|
166
|
+
type Chain<T = any, Next = any, Args extends readonly any[] = any[], Self = unknown> = (this: Self, ...params: [...Args, T]) => Awaitable<Next>;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @file Type Aliases - Reject
|
|
170
|
+
* @module when/types/Reject
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* The callback to fire when a promise is rejected
|
|
175
|
+
* or an error is thrown from a synchronous function.
|
|
176
|
+
*
|
|
177
|
+
* @see {@linkcode Awaitable}
|
|
178
|
+
*
|
|
179
|
+
* @template {any} [Next=any]
|
|
180
|
+
* The next resolved value
|
|
181
|
+
* @template {any} [Fail=any]
|
|
182
|
+
* The error to handle
|
|
183
|
+
* @template {any} [Self=unknown]
|
|
184
|
+
* The `this` context
|
|
185
|
+
*
|
|
186
|
+
* @this {Self}
|
|
187
|
+
*
|
|
188
|
+
* @param {unknown} e
|
|
189
|
+
* The error
|
|
190
|
+
* @return {Awaitable<Next>}
|
|
191
|
+
* The next promise or value
|
|
192
|
+
*/
|
|
193
|
+
type Reject<Next = any, Fail = any, Self = unknown> = (this: Self, e: Fail) => Awaitable<Next>;
|
|
194
|
+
|
|
195
|
+
export { when as default, isThenable as isPromiseLike, isThenable, when };
|
|
196
|
+
export type { Awaitable, Chain, Options, Reject };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file isThenable
|
|
3
|
+
* @module when/lib/isThenable
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Check if `value` looks like a thenable.
|
|
7
|
+
*
|
|
8
|
+
* @template {any} T
|
|
9
|
+
* The resolved value
|
|
10
|
+
*
|
|
11
|
+
* @this {void}
|
|
12
|
+
*
|
|
13
|
+
* @param {unknown} value
|
|
14
|
+
* The thing to check
|
|
15
|
+
* @return {value is PromiseLike<T>}
|
|
16
|
+
* `true` if `value` is a thenable, `false` otherwise
|
|
17
|
+
*/
|
|
18
|
+
function isThenable(value) {
|
|
19
|
+
return (!Array.isArray(value) &&
|
|
20
|
+
typeof value === 'object' &&
|
|
21
|
+
value !== null &&
|
|
22
|
+
'then' in value &&
|
|
23
|
+
typeof value.then === 'function');
|
|
24
|
+
}
|
|
25
|
+
export default isThenable;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file when
|
|
3
|
+
* @module when/lib/when
|
|
4
|
+
*/
|
|
5
|
+
import isThenable from '#lib/is-thenable';
|
|
6
|
+
export default when;
|
|
7
|
+
/**
|
|
8
|
+
* Chain a callback, calling the function after `value` is resolved,
|
|
9
|
+
* or immediately if `value` is not thenable.
|
|
10
|
+
*
|
|
11
|
+
* @see {@linkcode Chain}
|
|
12
|
+
* @see {@linkcode Options}
|
|
13
|
+
* @see {@linkcode Reject}
|
|
14
|
+
*
|
|
15
|
+
* @this {void}
|
|
16
|
+
*
|
|
17
|
+
* @param {unknown} value
|
|
18
|
+
* The promise or the resolved value
|
|
19
|
+
* @param {Chain<any, unknown> | Options} chain
|
|
20
|
+
* The chain callback or options for chaining
|
|
21
|
+
* @param {Reject | null | undefined} [reject]
|
|
22
|
+
* The callback to fire when a promise is rejected or an error is thrown
|
|
23
|
+
* @param {unknown} [context]
|
|
24
|
+
* The `this` context of the chain and error callbacks
|
|
25
|
+
* @param {unknown[]} args
|
|
26
|
+
* The arguments to pass to the chain callback
|
|
27
|
+
* @return {unknown}
|
|
28
|
+
* The next promise or value
|
|
29
|
+
*/
|
|
30
|
+
function when(value, chain, reject, context, ...args) {
|
|
31
|
+
if (typeof chain === 'object') {
|
|
32
|
+
reject = chain.reject;
|
|
33
|
+
context = chain.context;
|
|
34
|
+
args = chain.args ?? [];
|
|
35
|
+
chain = chain.chain;
|
|
36
|
+
}
|
|
37
|
+
// no promise, call chain function immediately.
|
|
38
|
+
if (!isThenable(value)) {
|
|
39
|
+
try {
|
|
40
|
+
return chain.call(context, ...args, value);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
return fail(e);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// already have a promise, chain callback.
|
|
47
|
+
return value.then(resolved => chain.call(context, ...args, resolved), fail);
|
|
48
|
+
/**
|
|
49
|
+
* @this {void}
|
|
50
|
+
*
|
|
51
|
+
* @param {unknown} e
|
|
52
|
+
* The error to handle
|
|
53
|
+
* @return {unknown}
|
|
54
|
+
* The rejection result
|
|
55
|
+
* @throws {unknown}
|
|
56
|
+
*/
|
|
57
|
+
function fail(e) {
|
|
58
|
+
if (typeof reject !== 'function')
|
|
59
|
+
throw e;
|
|
60
|
+
return reject.call(context, e);
|
|
61
|
+
}
|
|
62
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flex-development/when",
|
|
3
|
+
"description": "Like .then, but for synchronous values and thenables",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"async",
|
|
7
|
+
"await",
|
|
8
|
+
"awaitable",
|
|
9
|
+
"callback",
|
|
10
|
+
"chain",
|
|
11
|
+
"promise",
|
|
12
|
+
"sync",
|
|
13
|
+
"synchronous",
|
|
14
|
+
"then",
|
|
15
|
+
"thenable",
|
|
16
|
+
"typescript"
|
|
17
|
+
],
|
|
18
|
+
"license": "BSD-3-Clause",
|
|
19
|
+
"homepage": "https://github.com/flex-development/when",
|
|
20
|
+
"repository": "https://github.com/flex-development/when.git",
|
|
21
|
+
"bugs": "https://github.com/flex-development/when/issues",
|
|
22
|
+
"author": {
|
|
23
|
+
"name": "Lexus Drumgold",
|
|
24
|
+
"url": "https://github.com/unicornware"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public",
|
|
28
|
+
"diff-dst-prefix": "when",
|
|
29
|
+
"diff-src-prefix": "when",
|
|
30
|
+
"directory": "./",
|
|
31
|
+
"executableFiles": [],
|
|
32
|
+
"node-options": null,
|
|
33
|
+
"pack-destination": ".",
|
|
34
|
+
"parseable": true,
|
|
35
|
+
"prefer-dedupe": true,
|
|
36
|
+
"provenance": true,
|
|
37
|
+
"tag-version-prefix": ""
|
|
38
|
+
},
|
|
39
|
+
"type": "module",
|
|
40
|
+
"files": [
|
|
41
|
+
"CHANGELOG.md",
|
|
42
|
+
"LICENSE.md",
|
|
43
|
+
"README.md",
|
|
44
|
+
"dist"
|
|
45
|
+
],
|
|
46
|
+
"exports": {
|
|
47
|
+
".": {
|
|
48
|
+
"when": "./src/index.mts",
|
|
49
|
+
"default": "./dist/index.mjs"
|
|
50
|
+
},
|
|
51
|
+
"./package.json": "./package.json"
|
|
52
|
+
},
|
|
53
|
+
"imports": {
|
|
54
|
+
"#fixtures/*": "./__fixtures__/*.mts",
|
|
55
|
+
"#interfaces/*": {
|
|
56
|
+
"when": "./src/interfaces/*.mts",
|
|
57
|
+
"default": "./dist/interfaces/*.d.mts"
|
|
58
|
+
},
|
|
59
|
+
"#lib/*": {
|
|
60
|
+
"when": "./src/lib/*.mts",
|
|
61
|
+
"default": "./dist/lib/*.mjs"
|
|
62
|
+
},
|
|
63
|
+
"#tests/*": "./__tests__/*.mts",
|
|
64
|
+
"#types/*": {
|
|
65
|
+
"when": "./src/types/*.mts",
|
|
66
|
+
"default": "./dist/types/*.d.mts"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"module": "./dist/index.mjs",
|
|
70
|
+
"types": "./dist/index.d.mts",
|
|
71
|
+
"remarkConfig": {
|
|
72
|
+
"plugins": [
|
|
73
|
+
"@flex-development/remark-preset"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
"scripts": {
|
|
77
|
+
"build": "yarn clean:build && tsc -p tsconfig.build.json --noEmit false && yarn bundle:dts",
|
|
78
|
+
"bundle:dts": "rollup --config=rollup.config.mts && trash dist/{interfaces,types} && trash dist/{internal,lib}/*.d.mts",
|
|
79
|
+
"check:ci": "yarn dedupe --check && yarn check:format && yarn check:lint && yarn check:spelling && yarn typecheck && yarn check:types && yarn test:cov && yarn pack && yarn check:types:build && attw package.tgz && yarn clean:pack",
|
|
80
|
+
"check:format": "dprint check --incremental=false",
|
|
81
|
+
"check:lint": "eslint --exit-on-fatal-error --max-warnings 0 .",
|
|
82
|
+
"check:spelling": "cspell lint --color --no-progress --relative $@ \"**\"",
|
|
83
|
+
"check:types": "tsc -p tsconfig.json",
|
|
84
|
+
"check:types:attw": "yarn pack && attw package.tgz; yarn clean:pack",
|
|
85
|
+
"check:types:build": "tsc -p tsconfig.build.json",
|
|
86
|
+
"check:upgrades": "yarn upgrade-interactive",
|
|
87
|
+
"clean:build": "trash \"./{dist,*.tgz}\" || exit 0",
|
|
88
|
+
"clean:modules": "trash ./.yarn/{cache,*.gz} ./node_modules",
|
|
89
|
+
"clean:pack": "trash \"./*.tgz\"",
|
|
90
|
+
"clean:test": "trash ./coverage && trash __tests__/reports",
|
|
91
|
+
"codecov": "yarn test:cov && yarn test:cov:upload",
|
|
92
|
+
"codecov:validate": "cat .codecov.yml | curl --data-binary @- https://codecov.io/validate",
|
|
93
|
+
"commitlint": "commitlint -V",
|
|
94
|
+
"fix:cg": "yarn fix:format && yarn fix:lint",
|
|
95
|
+
"fix:dedupe": "yarn dedupe --strategy=highest",
|
|
96
|
+
"fix:format": "dprint fmt",
|
|
97
|
+
"fix:lint": "yarn check:lint --cache --fix",
|
|
98
|
+
"_postinstall": "[ -f ./.git ] && [ -f ./node_modules/.bin/husky ] && chmod +x .husky/_/* && husky || exit 0",
|
|
99
|
+
"postpack": "toggle-scripts +postinstall",
|
|
100
|
+
"postpublish": "toggle-scripts +prepack",
|
|
101
|
+
"prepack": "toggle-scripts -postinstall && yarn build",
|
|
102
|
+
"prepublishOnly": "toggle-scripts -prepack",
|
|
103
|
+
"release": "bash ./scripts/release.sh",
|
|
104
|
+
"remark": "remark .",
|
|
105
|
+
"test": "yarn clean:build; vitest run",
|
|
106
|
+
"test:cov": "yarn test --coverage",
|
|
107
|
+
"test:cov:reports": "yarn test:cov --merge-reports --mode=reports",
|
|
108
|
+
"test:cov:ui": "yarn test:ui --coverage",
|
|
109
|
+
"test:cov:upload": "./codecov -t $CODECOV_TOKEN -f ./coverage/lcov.info",
|
|
110
|
+
"test:reports": "yarn test --merge-reports --mode=reports",
|
|
111
|
+
"test:ui": "cross-env VITEST_UI=1 vitest --ui",
|
|
112
|
+
"typecheck": "yarn test --typecheck --mode=typecheck",
|
|
113
|
+
"typecheck:ui": "yarn test:ui --typecheck --mode=typecheck"
|
|
114
|
+
},
|
|
115
|
+
"devDependencies": {
|
|
116
|
+
"@arethetypeswrong/cli": "0.18.2",
|
|
117
|
+
"@commitlint/cli": "20.4.1",
|
|
118
|
+
"@commitlint/types": "20.4.0",
|
|
119
|
+
"@edge-runtime/vm": "5.0.0",
|
|
120
|
+
"@flex-development/commitlint-config": "1.0.1",
|
|
121
|
+
"@flex-development/eslint-config": "1.1.1",
|
|
122
|
+
"@flex-development/grease": "3.0.0-alpha.9",
|
|
123
|
+
"@flex-development/pathe": "4.0.2",
|
|
124
|
+
"@flex-development/remark-preset": "1.0.0",
|
|
125
|
+
"@flex-development/tutils": "6.0.0-alpha.25",
|
|
126
|
+
"@rollup/plugin-node-resolve": "16.0.3",
|
|
127
|
+
"@tsconfig/strictest": "2.0.8",
|
|
128
|
+
"@types/concat-stream": "2.0.3",
|
|
129
|
+
"@types/is-ci": "3.0.4",
|
|
130
|
+
"@types/node-notifier": "8.0.5",
|
|
131
|
+
"@types/rollup": "0.54.0",
|
|
132
|
+
"@vates/toggle-scripts": "1.0.0",
|
|
133
|
+
"@vitest/coverage-v8": "4.0.18",
|
|
134
|
+
"@vitest/ui": "4.0.18",
|
|
135
|
+
"concat-stream": "2.0.0",
|
|
136
|
+
"cross-env": "10.1.0",
|
|
137
|
+
"cspell": "9.6.4",
|
|
138
|
+
"devlop": "1.1.0",
|
|
139
|
+
"dprint": "0.51.1",
|
|
140
|
+
"editorconfig": "3.0.1",
|
|
141
|
+
"eslint": "9.39.2",
|
|
142
|
+
"growl": "1.10.5",
|
|
143
|
+
"happy-dom": "20.6.2",
|
|
144
|
+
"husky": "9.1.7",
|
|
145
|
+
"is-ci": "4.1.0",
|
|
146
|
+
"node-notifier": "10.0.1",
|
|
147
|
+
"pkg-size": "2.4.0",
|
|
148
|
+
"remark": "15.0.1",
|
|
149
|
+
"remark-cli": "12.0.1",
|
|
150
|
+
"rollup": "4.57.1",
|
|
151
|
+
"rollup-plugin-dts": "6.3.0",
|
|
152
|
+
"sh-syntax": "0.5.8",
|
|
153
|
+
"trash-cli": "7.2.0",
|
|
154
|
+
"typescript": "5.9.3",
|
|
155
|
+
"unified": "11.0.5",
|
|
156
|
+
"vfile": "6.0.3",
|
|
157
|
+
"vitest": "4.0.18"
|
|
158
|
+
},
|
|
159
|
+
"packageManager": "yarn@4.12.0",
|
|
160
|
+
"sideEffects": false
|
|
161
|
+
}
|