Gathering detailed insights and metrics for @open-draft/until
Gathering detailed insights and metrics for @open-draft/until
Gathering detailed insights and metrics for @open-draft/until
Gathering detailed insights and metrics for @open-draft/until
Gracefully handle Promises using async/await without try/catch.
npm install @open-draft/until
Typescript
Module System
Node Version
NPM Version
TypeScript (94.43%)
JavaScript (5.57%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
548 Stars
53 Commits
11 Forks
4 Watchers
1 Branches
8 Contributors
Updated on Jul 04, 2025
Latest Version
2.1.0
Package Id
@open-draft/until@2.1.0
Unpacked Size
9.84 kB
Size
3.94 kB
File Count
8
NPM Version
9.5.0
Node Version
18.15.0
Published on
Apr 18, 2023
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
6
until
Gracefully handle a Promise using async
/await
.
With the addition of async
/await
keywords in ECMAScript 2017 the handling of Promises became much easier. However, one must keep in mind that the await
keyword provides no standard error handling API. Consider this usage:
1function getUser(id) { 2 const data = await fetchUser(id) 3 // Work with "data"... 4}
In case fetchUser()
throws an error, the entire getUser()
function's scope will terminate. Because of this, it's recommended to implement error handling using try
/catch
block wrapping await
expressions:
1function getUser(id) 2 let data = null 3 4 try { 5 data = await asyncAction() 6 } catch (error) { 7 console.error(error) 8 } 9 10 // Work with "data"... 11}
While this is a semantically valid approach, constructing try
/catch
around each awaited operation may be tedious and get overlooked at times. Such error handling also introduces separate closures for execution and error scenarios of an asynchronous operation.
This library encapsulates the try
/catch
error handling in a utility function that does not create a separate closure and exposes a NodeJS-friendly API to work with errors and resolved data.
1npm install @open-draft/until
1import { until } from '@open-draft/until' 2 3async function(id) { 4 const { error, data } = await until(() => fetchUser(id)) 5 6 if (error) { 7 return handleError(error) 8 } 9 10 return data 11}
1import { until } from '@open-draft/until' 2 3interface User { 4 firstName: string 5 age: number 6} 7 8interface UserFetchError { 9 type: 'FORBIDDEN' | 'NOT_FOUND' 10 message?: string 11} 12 13async function(id: string) { 14 const { error, data } = await until<UserFetchError, User>(() => fetchUser(id)) 15 16 if (error) { 17 handleError(error.type, error.message) 18 } 19 20 return data.firstName 21}
until
accept a function and not a Promise
directly?This has been intentionally introduced to await a single logical unit as opposed to a single Promise
.
1// Notice how a single "until" invocation can handle 2// a rather complex piece of logic. This way any rejections 3// or exceptions happening within the given function 4// can be handled via the same "error". 5const { error, data } = until(async () => { 6 const user = await fetchUser() 7 const nextUser = normalizeUser(user) 8 const transaction = await saveModel('user', user) 9 10 invariant(transaction.status === 'OK', 'Saving user failed') 11 12 return transaction.result 13}) 14 15if (error) { 16 // Handle any exceptions happened within the function. 17}
until
return an object and not an array?The until
function used to return an array of shape [error, data]
prior to 2.0.0
. That has been changed, however, to get proper type-safety using discriminated union type.
Compare these two examples:
1const [error, data] = await until(() => action()) 2 3if (error) { 4 return null 5} 6 7// Data still has ambiguous "DataType | null" type here 8// even after you've checked and handled the "error" above. 9console.log(data)
1const result = await until(() => action()) 2 3// At this point, "data" is ambiguous "DataType | null" 4// which is correct, as you haven't checked nor handled the "error". 5 6if (result.error) { 7 return null 8} 9 10// Data is strict "DataType" since you've handled the "error" above. 11console.log(result.data)
It's crucial to keep the entire result of the
Promise
in a single variable and not destructure it. TypeScript will always keep the type oferror
anddata
as it was upon destructuring, ignoring any type guards you may perform later on.
until
API.No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
Found 5/18 approved changesets -- score normalized to 2
Reason
0 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 0
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
13 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-06-30
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More