better code: consistency on ApiError-s

Massimo Melina committed Jan 22, 2026 at 01:09 UTC 3f999033da9fdd5288f0c91d7c8cceab0dfbe77f
2 files changed +14 -14
src/api.net.ts
+3 -3
@@ -27,17 +27,17 @@ export default {
27 lookup(domain).then(x => [x.address]),
28 ])
29 if (settled[0].status === 'rejected' && settled[0].reason.code === 'ECONNREFUSED')
30 - throw new ApiError(HTTP_SERVICE_UNAVAILABLE, "cannot resolve domain")
30 + return new ApiError(HTTP_SERVICE_UNAVAILABLE, "cannot resolve domain")
31 // merge all results
32 const domainIps = _.uniq(onlyTruthy(settled.map(x => x.status === 'fulfilled' && x.value)).flat())
33 if (!domainIps.length)
34 - throw new ApiError(HTTP_FAILED_DEPENDENCY, "domain not working")
34 + return new ApiError(HTTP_FAILED_DEPENDENCY, "domain not working")
35 const publicIps = await getPublicIps() // do this before stopping the server
36 for (const v6 of [false, true]) {
37 const domainIpsThisVersion = domainIps.filter(x => isIPv6(x) === v6)
38 const ipsThisVersion = publicIps.filter(x => isIPv6(x) === v6)
39 if (domainIpsThisVersion.length && ipsThisVersion.length && !_.intersection(domainIpsThisVersion, ipsThisVersion).length)
40 - throw new ApiError(HTTP_PRECONDITION_FAILED, `configure your domain to point to ${ipsThisVersion} (currently on ${domainIpsThisVersion[0]}) – a change can take hours to be effective`)
40 + return new ApiError(HTTP_PRECONDITION_FAILED, `configure your domain to point to ${ipsThisVersion} (currently on ${domainIpsThisVersion[0]}) – a change can take hours to be effective`)
41 }
42 return {}
43 },
src/frontEndApis.ts
+11 -11
@@ -85,16 +85,16 @@ export const frontEndApis: ApiHandlers = {
85 ctx.logExtra(null, { target: decodeURI(uri), destination: decodeURI(dest) })
86 const node = await urlToNode(uri, ctx)
87 if (!node)
88 - throw new ApiError(HTTP_NOT_FOUND)
88 + return new ApiError(HTTP_NOT_FOUND)
89 if (isRoot(node) || !isValidFileName(dest))
90 - throw new ApiError(HTTP_FORBIDDEN)
90 + return new ApiError(HTTP_FORBIDDEN)
91 if (statusCodeForMissingPerm(node, 'can_delete', ctx))
92 - throw new ApiError(ctx.status)
92 + return new ApiError(ctx.status)
93 if (!node.source)
94 - throw new ApiError(HTTP_FAILED_DEPENDENCY)
94 + return new ApiError(HTTP_FAILED_DEPENDENCY)
95 const destNode = await urlToNode(dest, ctx, node.parent)
96 if (destNode && statusCodeForMissingPerm(destNode, 'can_delete', ctx)) // if destination exists, you need delete permission
97 - throw new ApiError(ctx.status)
97 + return new ApiError(ctx.status)
98 try {
99 const destSource = join(dirname(node.source), dest)
100 await rename(node.source, destSource)
@@ -106,7 +106,7 @@ export const frontEndApis: ApiHandlers = {
106 return {}
107 }
108 catch (e: any) {
109 - throw new ApiError(HTTP_SERVER_ERROR, e)
109 + return new ApiError(HTTP_SERVER_ERROR, e)
110 }
111 },
112
@@ -157,11 +157,11 @@ export const frontEndApis: ApiHandlers = {
157 ctx.logExtra(null, { target: decodeURI(uri) })
158 const node = await urlToNode(uri, ctx)
159 if (!node)
160 - throw new ApiError(HTTP_NOT_FOUND)
160 + return new ApiError(HTTP_NOT_FOUND)
161 if (!hasPermission(node, 'can_upload', ctx))
162 - throw new ApiError(HTTP_UNAUTHORIZED)
162 + return new ApiError(HTTP_UNAUTHORIZED)
163 if (!node.source)
164 - throw new ApiError(HTTP_FAILED_DEPENDENCY)
164 + return new ApiError(HTTP_FAILED_DEPENDENCY)
165 await setCommentFor(node.source, comment)
166 return {}
167 },
@@ -175,9 +175,9 @@ export const frontEndApis: ApiHandlers = {
175 apiAssertTypes({ string: { uri } })
176 const folder = await urlToNode(uri, ctx)
177 if (!folder)
178 - throw new ApiError(HTTP_NOT_FOUND)
178 + return new ApiError(HTTP_NOT_FOUND)
179 if (!nodeIsFolder(folder))
180 - throw new ApiError(HTTP_METHOD_NOT_ALLOWED)
180 + return new ApiError(HTTP_METHOD_NOT_ALLOWED)
181 if (statusCodeForMissingPerm(folder, 'can_list', ctx))
182 return new ApiError(ctx.status)
183 let bytes = 0