Skip to content

Commit 67fc4ee

Browse files
rexxarsbjoerge
authored andcommitted
[client] Include error message in stack (#129)
1 parent e083695 commit 67fc4ee

File tree

4 files changed

+74
-39
lines changed

4 files changed

+74
-39
lines changed

packages/@sanity/client/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
"dependencies": {
2020
"@sanity/eventsource": "^0.108.0",
2121
"@sanity/observable": "^0.108.0",
22-
"create-error-class": "^3.0.2",
2322
"deep-assign": "^2.0.0",
2423
"get-it": "^2.0.2",
2524
"in-publish": "^2.0.0",
25+
"make-error": "^1.3.0",
2626
"object-assign": "^4.1.1"
2727
},
2828
"devDependencies": {
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const makeError = require('make-error')
2+
const assign = require('object-assign')
3+
4+
function ClientError(res) {
5+
const props = extractErrorProps(res)
6+
ClientError.super.call(this, props.message)
7+
assign(this, props)
8+
}
9+
10+
function ServerError(res) {
11+
const props = extractErrorProps(res)
12+
ServerError.super.call(this, props.message)
13+
assign(this, props)
14+
}
15+
16+
function extractErrorProps(res) {
17+
const body = res.body
18+
const props = {
19+
response: res,
20+
statusCode: res.statusCode,
21+
responseBody: stringifyBody(body, res),
22+
}
23+
24+
// API/Boom style errors ({statusCode, error, message})
25+
if (body.error && body.message) {
26+
props.message = `${body.error} - ${body.message}`
27+
return props
28+
}
29+
30+
// Query/database errors ({error: {description, other, arb, props}})
31+
if (body.error && body.error.description) {
32+
props.message = body.error.description
33+
props.details = body.error
34+
return props
35+
}
36+
37+
// Other, more arbitrary errors
38+
props.message = body.error || body.message || httpErrorMessage(res)
39+
return props
40+
}
41+
42+
function httpErrorMessage(res) {
43+
const statusMessage = res.statusMessage ? ` ${res.statusMessage}` : ''
44+
return `${res.method}-request to ${res.url} resulted in HTTP ${res.statusCode}${statusMessage}`
45+
}
46+
47+
function stringifyBody(body, res) {
48+
const contentType = (res.headers['content-type'] || '').toLowerCase()
49+
const isJson = contentType.indexOf('application/json') !== -1
50+
return isJson ? JSON.stringify(body, null, 2) : body
51+
}
52+
53+
makeError(ClientError)
54+
makeError(ServerError)
55+
56+
exports.ClientError = ClientError
57+
exports.ServerError = ServerError

packages/@sanity/client/src/http/request.js

+1-38
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
/* eslint-disable no-empty-function, no-process-env */
22
const getIt = require('get-it')
33
const assign = require('object-assign')
4-
const createErrorClass = require('create-error-class')
54
const observable = require('get-it/lib/middleware/observable')
65
const jsonRequest = require('get-it/lib/middleware/jsonRequest')
76
const jsonResponse = require('get-it/lib/middleware/jsonResponse')
87
const SanityObservable = require('@sanity/observable/minimal')
98
const progress = require('get-it/lib/middleware/progress')
10-
11-
const ClientError = createErrorClass('ClientError', extractError)
12-
const ServerError = createErrorClass('ServerError', extractError)
9+
const {ClientError, ServerError} = require('./errors')
1310

1411
const httpError = ({
1512
onResponse: res => {
@@ -23,40 +20,6 @@ const httpError = ({
2320
}
2421
})
2522

26-
function extractError(res) {
27-
const body = res.body
28-
this.response = res
29-
this.statusCode = res.statusCode
30-
this.responseBody = stringifyBody(body, res)
31-
32-
// API/Boom style errors ({statusCode, error, message})
33-
if (body.error && body.message) {
34-
this.message = `${body.error} - ${body.message}`
35-
return
36-
}
37-
38-
// Query/database errors ({error: {description, other, arb, props}})
39-
if (body.error && body.error.description) {
40-
this.message = body.error.description
41-
this.details = body.error
42-
return
43-
}
44-
45-
// Other, more arbitrary errors
46-
this.message = body.error || body.message || httpErrorMessage(res)
47-
}
48-
49-
function httpErrorMessage(res) {
50-
const statusMessage = res.statusMessage ? ` ${res.statusMessage}` : ''
51-
return `${res.method}-request to ${res.url} resulted in HTTP ${res.statusCode}${statusMessage}`
52-
}
53-
54-
function stringifyBody(body, res) {
55-
const contentType = (res.headers['content-type'] || '').toLowerCase()
56-
const isJson = contentType.indexOf('application/json') !== -1
57-
return isJson ? JSON.stringify(body, null, 2) : body
58-
}
59-
6023
const middleware = [
6124
jsonRequest(),
6225
jsonResponse(),

packages/@sanity/client/test/client.test.js

+15
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,21 @@ test('can use alternative http requester', t => {
12921292
})
12931293
})
12941294

1295+
test('ClientError includes message in stack', t => {
1296+
const body = {error: {description: 'Invalid query'}}
1297+
const error = new SanityClient.ClientError({statusCode: 400, headers: {}, body})
1298+
t.ok(error.stack.includes(body.error.description))
1299+
t.end()
1300+
})
1301+
1302+
test('ServerError includes message in stack', t => {
1303+
const body = {error: 'Gateway Time-Out', message: 'The upstream service did not respond in time'}
1304+
const error = new SanityClient.ClientError({statusCode: 504, headers: {}, body})
1305+
t.ok(error.stack.includes(body.error))
1306+
t.ok(error.stack.includes(body.message))
1307+
t.end()
1308+
})
1309+
12951310
test('exposes ClientError', t => {
12961311
t.equal(typeof sanityClient.ClientError, 'function')
12971312
const error = new SanityClient.ClientError({statusCode: 400, headers: {}, body: {}})

0 commit comments

Comments
 (0)