Abort()
vs new Error()
Reading Recommendation: Overview > RPC
You may wonder, why not use throw new Error()
instead of throw Abort()
?
// TodoList.telefunc.js
// Environment: server
import { getContext } from 'telefunc'
export async function getTodoList() {
const { user } = getContext()
if (!user) {
// Instead of `throw Abort()`
throw new Error()
}
// ...
}
By using throw Abort()
, we are telling Telefunc that this is an error that is expected to happen (when a third-party makes an invalid or unprivileged telefunction call). Whereas throw new Error()
is unexpected: it should never happen and, if it does happen, then it's a bug in our backend code.
For example, throw Abort()
doesn't trigger onBug()
, see Guides > Error handling > Error tracking.
Rule
The rule for a correct usage is:
- We use
throw Abort()
for errors originating from a wrong public usage of a telefunction. - We use
throw new Error()
for errors originating from a wrong internal usage of a function.
Example
// auth/getUser.ts
// Environment: server
// Note that `auth/getUser.ts` is not a `.telefunc.js` file (`getUser()` is
// not a telefunction but a so-called `getContext()` wrapper).
export { getUser }
import { Abort, getContext } from 'telefunc'
function getUser({ permission }) {
if (!permission) {
throw new Error('Wrong getUser() usage: missing permission')
}
// We avoid typos (a typo like `admni` could have dramatic consequences)
if (!['public', 'admin'].includes(permission)) {
throw new Error('Wrong getUser() usage: unknown permission ' + permission)
}
const { user } = getContext()
if (!user) {
throw Abort()
}
if (permission === 'admin') {
if (!user.isAdmin) {
throw Abort()
}
return user
}
if (permission === 'public') {
return user
}
}
Such
getContext()
wrapper is a common Telefunc technique explained at Guides > Permissions >getContext()
wrapping.
// components/Comment.telefunc.ts
// Environment: server
import { getUser } from '../auth/getUser'
export async function onCommentDelete(id: number) {
// Only admins are allowed to delete a comment
const user = getUser({ permission: 'admin' })
const comment = await Comment.findOne({ id })
await comment.delete()
}
It is expected that throw Abort()
can occur, since onCommentDelete()
is a public function anyone can call while not being an admin.
Whereas throw new Error('Wrong getUser() usage')
is expected to not occur: if we make a typo and call getUser({ permission: 'admni' })
then it's an internal bug in our backend that we should fix.