-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy patherrors.js
More file actions
79 lines (74 loc) · 3 KB
/
Copy patherrors.js
File metadata and controls
79 lines (74 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
* Typed errors for OSLC HTTP operations.
*
* The axios client uses validateStatus: 401 || < 400, so non-401 error
* statuses surface as axios rejections carrying error.response. oslcErrorFrom
* accepts either that rejection shape or a resolved response object and maps
* it to the appropriate subclass so callers can switch on error type.
*/
export class OSLCError extends Error {
constructor(message, { status = null, statusText = null, serverMessage = null, url = null, cause = null } = {}) {
super(message, cause ? { cause } : undefined);
this.name = 'OSLCError';
this.status = status;
this.statusText = statusText;
this.serverMessage = serverMessage;
this.url = url;
}
}
export class PreconditionFailedError extends OSLCError {
constructor(message, options = {}) {
super(message, options);
this.name = 'PreconditionFailedError';
}
}
export class ConflictError extends OSLCError {
constructor(message, options = {}) {
super(message, options);
this.name = 'ConflictError';
}
}
/**
* The host supplied a credential and the server rejected it.
*
* Distinct from AUTH_EXHAUSTED, which means "none of the built-in mechanisms worked".
* This means "the credential you gave me is not accepted", which is what a host needs in
* order to prompt for a new one rather than retry blindly.
*/
export class CredentialRejectedError extends OSLCError {
constructor(message, { wwwAuthenticate = null, ...options } = {}) {
super(message, options);
this.name = 'CredentialRejectedError';
this.wwwAuthenticate = wwwAuthenticate;
}
}
/**
* Build the appropriate OSLCError subclass from an axios rejection or a
* resolved response object.
*
* @param {Error|Object} errorOrResponse - axios error (with .response) or response-like object
* @param {string} url - the request URL, for the error message and .url field
* @param {string} defaultMessage - operation description, e.g. 'Failed to update resource'
* @returns {OSLCError}
*/
export function oslcErrorFrom(errorOrResponse, url, defaultMessage) {
if (errorOrResponse instanceof OSLCError) return errorOrResponse;
const response = errorOrResponse?.response ?? errorOrResponse;
const status = typeof response?.status === 'number' ? response.status : null;
const statusText = response?.statusText ?? null;
let serverMessage = null;
if (typeof response?.data === 'string' && response.data.length) {
serverMessage = response.data;
} else if (response?.data != null && typeof response.data === 'object') {
serverMessage = JSON.stringify(response.data);
}
const statusPart = status ? ` (${status}${statusText ? ' ' + statusText : ''})` : '';
const message = `${defaultMessage}${statusPart}: ${url}`;
const options = {
status, statusText, serverMessage, url,
cause: errorOrResponse instanceof Error ? errorOrResponse : null
};
if (status === 412) return new PreconditionFailedError(message, options);
if (status === 409) return new ConflictError(message, options);
return new OSLCError(message, options);
}