@jahands/notion-client
Version:
A simple and easy to use client for the Notion API
194 lines • 6.43 kB
JavaScript
import { isObject } from './utils';
/**
* Error codes returned in responses from the API.
*/
export var APIErrorCode;
(function (APIErrorCode) {
APIErrorCode["Unauthorized"] = "unauthorized";
APIErrorCode["RestrictedResource"] = "restricted_resource";
APIErrorCode["ObjectNotFound"] = "object_not_found";
APIErrorCode["RateLimited"] = "rate_limited";
APIErrorCode["InvalidJSON"] = "invalid_json";
APIErrorCode["InvalidRequestURL"] = "invalid_request_url";
APIErrorCode["InvalidRequest"] = "invalid_request";
APIErrorCode["ValidationError"] = "validation_error";
APIErrorCode["ConflictError"] = "conflict_error";
APIErrorCode["InternalServerError"] = "internal_server_error";
APIErrorCode["ServiceUnavailable"] = "service_unavailable";
})(APIErrorCode || (APIErrorCode = {}));
/**
* Error codes generated for client errors.
*/
export var ClientErrorCode;
(function (ClientErrorCode) {
ClientErrorCode["RequestTimeout"] = "notionhq_client_request_timeout";
ClientErrorCode["ResponseError"] = "notionhq_client_response_error";
})(ClientErrorCode || (ClientErrorCode = {}));
/**
* Base error type.
*/
class NotionClientErrorBase extends Error {
}
/**
* @param error any value, usually a caught error.
* @returns `true` if error is a `NotionClientError`.
*/
export function isNotionClientError(error) {
return isObject(error) && error instanceof NotionClientErrorBase;
}
/**
* Narrows down the types of a NotionClientError.
* @param error any value, usually a caught error.
* @param codes an object mapping from possible error codes to `true`
* @returns `true` if error is a `NotionClientError` with a code in `codes`.
*/
function isNotionClientErrorWithCode(error, codes) {
return isNotionClientError(error) && error.code in codes;
}
/**
* Error thrown by the client if a request times out.
*/
export class RequestTimeoutError extends NotionClientErrorBase {
code = ClientErrorCode.RequestTimeout;
name = 'RequestTimeoutError';
constructor(message = 'Request to Notion API has timed out') {
super(message);
}
static isRequestTimeoutError(error) {
return isNotionClientErrorWithCode(error, {
[ClientErrorCode.RequestTimeout]: true,
});
}
static rejectAfterTimeout(promise, timeoutMS) {
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
reject(new RequestTimeoutError());
}, timeoutMS);
void promise
.then(resolve)
.catch(reject)
.then(() => clearTimeout(timeoutId));
});
}
}
class HTTPResponseError extends NotionClientErrorBase {
name = 'HTTPResponseError';
code;
status;
headers;
body;
constructor(args) {
super(args.message);
const { code, status, headers, rawBodyText } = args;
this.code = code;
this.status = status;
this.headers = headers;
this.body = rawBodyText;
}
}
const httpResponseErrorCodes = {
[ClientErrorCode.ResponseError]: true,
[APIErrorCode.Unauthorized]: true,
[APIErrorCode.RestrictedResource]: true,
[APIErrorCode.ObjectNotFound]: true,
[APIErrorCode.RateLimited]: true,
[APIErrorCode.InvalidJSON]: true,
[APIErrorCode.InvalidRequestURL]: true,
[APIErrorCode.InvalidRequest]: true,
[APIErrorCode.ValidationError]: true,
[APIErrorCode.ConflictError]: true,
[APIErrorCode.InternalServerError]: true,
[APIErrorCode.ServiceUnavailable]: true,
};
export function isHTTPResponseError(error) {
if (!isNotionClientErrorWithCode(error, httpResponseErrorCodes)) {
return false;
}
return true;
}
/**
* Error thrown if an API call responds with an unknown error code, or does not respond with
* a property-formatted error.
*/
export class UnknownHTTPResponseError extends HTTPResponseError {
name = 'UnknownHTTPResponseError';
constructor(args) {
super({
...args,
code: ClientErrorCode.ResponseError,
message: args.message ?? `Request to Notion API failed with status: ${args.status}`,
});
}
static isUnknownHTTPResponseError(error) {
return isNotionClientErrorWithCode(error, {
[ClientErrorCode.ResponseError]: true,
});
}
}
const apiErrorCodes = {
[APIErrorCode.Unauthorized]: true,
[APIErrorCode.RestrictedResource]: true,
[APIErrorCode.ObjectNotFound]: true,
[APIErrorCode.RateLimited]: true,
[APIErrorCode.InvalidJSON]: true,
[APIErrorCode.InvalidRequestURL]: true,
[APIErrorCode.InvalidRequest]: true,
[APIErrorCode.ValidationError]: true,
[APIErrorCode.ConflictError]: true,
[APIErrorCode.InternalServerError]: true,
[APIErrorCode.ServiceUnavailable]: true,
};
/**
* A response from the API indicating a problem.
* Use the `code` property to handle various kinds of errors. All its possible values are in `APIErrorCode`.
*/
export class APIResponseError extends HTTPResponseError {
name = 'APIResponseError';
static isAPIResponseError(error) {
return isNotionClientErrorWithCode(error, apiErrorCodes);
}
}
export function buildRequestError(response, bodyText) {
const apiErrorResponseBody = parseAPIErrorResponseBody(bodyText);
if (apiErrorResponseBody !== undefined) {
return new APIResponseError({
code: apiErrorResponseBody.code,
message: apiErrorResponseBody.message,
headers: response.headers,
status: response.status,
rawBodyText: bodyText,
});
}
return new UnknownHTTPResponseError({
message: undefined,
headers: response.headers,
status: response.status,
rawBodyText: bodyText,
});
}
function parseAPIErrorResponseBody(body) {
if (typeof body !== 'string') {
return;
}
let parsed;
try {
parsed = JSON.parse(body);
}
catch (parseError) {
return;
}
if (!isObject(parsed) ||
typeof parsed['message'] !== 'string' ||
!isAPIErrorCode(parsed['code'])) {
return;
}
return {
...parsed,
code: parsed['code'],
message: parsed['message'],
};
}
function isAPIErrorCode(code) {
return typeof code === 'string' && code in apiErrorCodes;
}
//# sourceMappingURL=errors.js.map