Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8892

Firebase の REST API 向けエラークラスが優れているので、パクった。

$
0
0
Firebase Functions の HttpsError こいつです!! こいつを、 Firebase 非依存プロジェクトでも使いたいと思ったわけです。 どうして優れているの すげー使いやすいAPIなんですよね。。。 app.get("/items/:id", async (req, res, next) => { const item = await Item.find(id); if (item == null) { // ⭐ こいつ! throw new HttpsError("not-found", "Invalid Item ID", detail); } ... }); 第1引数が 404 といったhttpエラー番号でなく、直感的なtext.もちろん型定義されているのでサジェストされる。 第2引数に概要を書くことができる 第3引数に詳細をつめることができる シンプルかつ洗練されたインターフェース。 express との連携例 こんな感じの middleware 定義して運用してるんですけどね。 middlewares.ts export class APIMiddlewares { static errorHandler( err: Error | HttpsError, req: Request, res: Response, next: NextFunction ) { // ⭐ HttpsError はサービスで想定されたエラーとして処理 if (err.constructor.name === HttpsError.name) { const httpsError = err as HttpsError; res.status(httpsError.httpErrorCode.status).send({ status: httpsError.httpErrorCode.canonicalName, msg: httpsError.message, }); ... return; } // ⭐ HttpsError でないなら想定外のエラーとして処理 res.status(500).send({ status: "INTERNAL_SERVER_ERROR" }); ... } } 想定されたものかどうか、色分けができる(そしてそれが優れたインターフェースのErrorを介してできる)だけでもめっちゃ便利。 パクってみた https://github.com/firebase/firebase-functions/blob/98bf467aa436f7e27969a8ad3887abe0345f66d3/src/providers/https.ts 冒頭にも参照したソースから丸パクリ。 MITライセンスであることに注意 http-error.ts export type FunctionsErrorCode = | "ok" | "cancelled" | "unknown" | "invalid-argument" | "deadline-exceeded" | "not-found" | "already-exists" | "permission-denied" | "resource-exhausted" | "failed-precondition" | "aborted" | "out-of-range" | "unimplemented" | "internal" | "unavailable" | "data-loss" | "unauthenticated"; /** @hidden */ export type CanonicalErrorCodeName = | "OK" | "CANCELLED" | "UNKNOWN" | "INVALID_ARGUMENT" | "DEADLINE_EXCEEDED" | "NOT_FOUND" | "ALREADY_EXISTS" | "PERMISSION_DENIED" | "UNAUTHENTICATED" | "RESOURCE_EXHAUSTED" | "FAILED_PRECONDITION" | "ABORTED" | "OUT_OF_RANGE" | "UNIMPLEMENTED" | "INTERNAL" | "UNAVAILABLE" | "DATA_LOSS"; /** @hidden */ interface HttpErrorCode { canonicalName: CanonicalErrorCodeName; status: number; } /** * Standard error codes and HTTP statuses for different ways a request can fail, * as defined by: * https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto * * This map is used primarily to convert from a client error code string to * to the HTTP format error code string and status, and make sure it's in the * supported set. */ const errorCodeMap: { [name in FunctionsErrorCode]: HttpErrorCode } = { ok: { canonicalName: "OK", status: 200 }, cancelled: { canonicalName: "CANCELLED", status: 499 }, unknown: { canonicalName: "UNKNOWN", status: 500 }, "invalid-argument": { canonicalName: "INVALID_ARGUMENT", status: 400 }, "deadline-exceeded": { canonicalName: "DEADLINE_EXCEEDED", status: 504 }, "not-found": { canonicalName: "NOT_FOUND", status: 404 }, "already-exists": { canonicalName: "ALREADY_EXISTS", status: 409 }, "permission-denied": { canonicalName: "PERMISSION_DENIED", status: 403 }, unauthenticated: { canonicalName: "UNAUTHENTICATED", status: 401 }, "resource-exhausted": { canonicalName: "RESOURCE_EXHAUSTED", status: 429 }, "failed-precondition": { canonicalName: "FAILED_PRECONDITION", status: 400 }, aborted: { canonicalName: "ABORTED", status: 409 }, "out-of-range": { canonicalName: "OUT_OF_RANGE", status: 400 }, unimplemented: { canonicalName: "UNIMPLEMENTED", status: 501 }, internal: { canonicalName: "INTERNAL", status: 500 }, unavailable: { canonicalName: "UNAVAILABLE", status: 503 }, "data-loss": { canonicalName: "DATA_LOSS", status: 500 }, }; /** @hidden */ interface HttpErrorWireFormat { details?: unknown; message: string; status: CanonicalErrorCodeName; } /** * An explicit error that can be thrown from a handler to send an error to the * client that called the function. */ export class HttpsError extends Error { /** * A standard error code that will be returned to the client. This also * determines the HTTP status code of the response, as defined in code.proto. */ public readonly code: FunctionsErrorCode; /** * Extra data to be converted to JSON and included in the error response. */ public readonly details: unknown; /** * A wire format representation of a provided error code. * * @hidden */ public readonly httpErrorCode: HttpErrorCode; constructor(code: FunctionsErrorCode, message: string, details?: unknown) { super(message); // A sanity check for non-TypeScript consumers. if (code in errorCodeMap === false) { throw new Error(`Unknown error code: ${code}.`); } this.code = code; this.details = details; this.httpErrorCode = errorCodeMap[code]; } /** @hidden */ public toJSON(): HttpErrorWireFormat { const { details, httpErrorCode: { canonicalName: status }, message, } = this; return { ...(details === undefined ? {} : { details }), message, status, }; } } ありがとう Google, ありがとう Firebase.

Viewing all articles
Browse latest Browse all 8892

Trending Articles