Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node: エラーを返すときの形式をGoと同じJSON形式にする #593

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 60 additions & 30 deletions webapp/nodejs/src/app_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
FARE_PER_DISTANCE,
getLatestRideStatus,
INITIAL_FARE,
responseError,
} from "./common.js";
import type { CountResult } from "./types/util.js";
import { requestPaymentGatewayPostPayment } from "./payment_gateway.js";
Expand All @@ -47,8 +48,11 @@ export const appPostUsers = async (ctx: Context<Environment>) => {
reqJson.lastname === "" ||
reqJson.date_of_birth === ""
) {
return ctx.text(
"required fields(username, firstname, lastname, date_of_birth) are empty",
return responseError(
ctx,
new Error(
"required fields(username, firstname, lastname, date_of_birth) are empty",
),
400,
);
}
Expand Down Expand Up @@ -86,7 +90,11 @@ export const appPostUsers = async (ctx: Context<Environment>) => {
`INV_${reqJson.invitation_code}`,
);
if (coupons.length >= 3) {
return ctx.text("この招待コードは使用できません。", 400);
return responseError(
ctx,
new Error("この招待コードは使用できません。"),
400,
);
}

// ユーザーチェック
Expand All @@ -95,7 +103,11 @@ export const appPostUsers = async (ctx: Context<Environment>) => {
[reqJson.invitation_code],
);
if (inviter.length === 0) {
return ctx.text("この招待コードは使用できません。", 400);
return responseError(
ctx,
new Error("この招待コードは使用できません。"),
400,
);
}

// 招待クーポン付与
Expand Down Expand Up @@ -124,14 +136,18 @@ export const appPostUsers = async (ctx: Context<Environment>) => {
);
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
};

export const appPostPaymentMethods = async (ctx: Context<Environment>) => {
const reqJson = await ctx.req.json<{ token: string }>();
if (reqJson.token === "") {
return ctx.text("token is required but was empty", 400);
return responseError(
ctx,
new Error("token is required but was empty"),
400,
);
}
const user = ctx.var.user;
await ctx.var.dbConn.query(
Expand Down Expand Up @@ -220,7 +236,7 @@ export const appGetRides = async (ctx: Context<Environment>) => {
);
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
};

Expand All @@ -230,8 +246,11 @@ export const appPostRides = async (ctx: Context<Environment>) => {
destination_coordinate: Coordinate;
}>();
if (!reqJson.pickup_coordinate || !reqJson.destination_coordinate) {
return ctx.text(
"required fields(pickup_coordinate, destination_coordinate) are empty",
return responseError(
ctx,
new Error(
"required fields(pickup_coordinate, destination_coordinate) are empty",
),
400,
);
}
Expand All @@ -251,7 +270,7 @@ export const appPostRides = async (ctx: Context<Environment>) => {
}
}
if (continuingRideCount > 0) {
return ctx.text("ride already exists", 409);
return responseError(ctx, new Error("ride already exists"), 409);
}
await ctx.var.dbConn.query(
"INSERT INTO rides (id, user_id, pickup_latitude, pickup_longitude, destination_latitude, destination_longitude) VALUES (?, ?, ?, ?, ?, ?)",
Expand Down Expand Up @@ -336,7 +355,7 @@ export const appPostRides = async (ctx: Context<Environment>) => {
);
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
};

Expand All @@ -346,8 +365,11 @@ export const appPostRidesEstimatedFare = async (ctx: Context<Environment>) => {
destination_coordinate: Coordinate;
}>();
if (!reqJson.pickup_coordinate || !reqJson.destination_coordinate) {
return ctx.text(
"required fields(pickup_coordinate, destination_coordinate) are empty",
return responseError(
ctx,
new Error(
"required fields(pickup_coordinate, destination_coordinate) are empty",
),
400,
);
}
Expand Down Expand Up @@ -379,15 +401,19 @@ export const appPostRidesEstimatedFare = async (ctx: Context<Environment>) => {
);
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
};

export const appPostRideEvaluatation = async (ctx: Context<Environment>) => {
const rideId = ctx.req.param("ride_id");
const reqJson = await ctx.req.json<{ evaluation: number }>();
if (reqJson.evaluation < 1 || reqJson.evaluation > 5) {
return ctx.text("evaluation must be between 1 and 5", 400);
return responseError(
ctx,
new Error("evaluation must be between 1 and 5"),
400,
);
}
await ctx.var.dbConn.beginTransaction();
try {
Expand All @@ -396,19 +422,19 @@ export const appPostRideEvaluatation = async (ctx: Context<Environment>) => {
rideId,
);
if (!ride) {
return ctx.text("ride not found", 404);
return responseError(ctx, new Error("ride not found"), 404);
}
const status = await getLatestRideStatus(ctx.var.dbConn, ride.id);
if (status !== "ARRIVED") {
return ctx.text("not arrived yet", 400);
return responseError(ctx, new Error("ride not arrived yet"), 400);
}

const [result] = await ctx.var.dbConn.query<ResultSetHeader>(
"UPDATE rides SET evaluation = ? WHERE id = ?",
[reqJson.evaluation, rideId],
);
if (result.affectedRows === 0) {
return ctx.text("ride not found", 404);
return responseError(ctx, new Error("ride not found"), 404);
}

await ctx.var.dbConn.query(
Expand All @@ -421,14 +447,14 @@ export const appPostRideEvaluatation = async (ctx: Context<Environment>) => {
rideId,
);
if (!ride) {
return ctx.text("ride not found", 404);
return responseError(ctx, new Error("ride not found"), 404);
}

const [[paymentToken]] = await ctx.var.dbConn.query<
Array<PaymentToken & RowDataPacket>
>("SELECT * FROM payment_tokens WHERE user_id = ?", [ride.user_id]);
if (!paymentToken) {
return ctx.text("payment token not registered", 400);
return responseError(ctx, new Error("payment token not registered"), 400);
}
const fare = await calculateDiscountedFare(
ctx.var.dbConn,
Expand Down Expand Up @@ -457,7 +483,7 @@ export const appPostRideEvaluatation = async (ctx: Context<Environment>) => {
},
);
if (err instanceof ErroredUpstream) {
return ctx.text(`${err}`, 502);
return responseError(ctx, err, 502);
}
await ctx.var.dbConn.commit();
return ctx.json(
Expand All @@ -466,9 +492,9 @@ export const appPostRideEvaluatation = async (ctx: Context<Environment>) => {
},
200,
);
} catch (err) {
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${err}`, 500);
return responseError(ctx, e, 500);
}
};

Expand Down Expand Up @@ -571,7 +597,7 @@ export const appGetNotification = async (ctx: Context<Environment>) => {
return ctx.json(response, 200);
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
};

Expand Down Expand Up @@ -631,23 +657,27 @@ export const appGetNearbyChairs = async (ctx: Context<Environment>) => {
const lonStr = ctx.req.query("longitude");
const distanceStr = ctx.req.query("distance");
if (!latStr || !lonStr) {
return ctx.text("latitude and longitude is empty", 400);
return responseError(
ctx,
new Error("latitude and longitude is empty"),
400,
);
}

const lat = atoi(latStr);
if (lat === false) {
return ctx.text("latitude is invalid", 400);
return responseError(ctx, new Error("latitude is invalid"), 400);
}
const lon = atoi(lonStr);
if (lon === false) {
return ctx.text("longitude is invalid", 400);
return responseError(ctx, new Error("longitude is invalid"), 400);
}

let distance: number | false = 50;
if (distanceStr) {
distance = atoi(distanceStr);
if (distance === false) {
return ctx.text("distance is invalid", 400);
return responseError(ctx, new Error("distance is invalid"), 400);
}
}

Expand Down Expand Up @@ -722,9 +752,9 @@ export const appGetNearbyChairs = async (ctx: Context<Environment>) => {
},
200,
);
} catch (err) {
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${err}`, 500);
return responseError(ctx, e, 500);
}
};

Expand Down
31 changes: 19 additions & 12 deletions webapp/nodejs/src/chair_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Context } from "hono";
import { setCookie } from "hono/cookie";
import type { RowDataPacket } from "mysql2";
import { ulid } from "ulid";
import { getLatestRideStatus } from "./common.js";
import { getLatestRideStatus, responseError } from "./common.js";
import type { Environment } from "./types/hono.js";
import type {
ChairLocation,
Expand All @@ -22,8 +22,11 @@ export const chairPostChairs = async (ctx: Context<Environment>) => {
}>();
const { name, model, chair_register_token } = reqJson;
if (!name || !model || !chair_register_token) {
return ctx.text(
"some of required fields(name, model, chair_register_token) are empty",
return responseError(
ctx,
new Error(
"some of required fields(name, model, chair_register_token) are empty",
),
400,
);
}
Expand All @@ -32,7 +35,7 @@ export const chairPostChairs = async (ctx: Context<Environment>) => {
[chair_register_token],
);
if (!owner) {
return ctx.text("invalid chair_register_token", 401);
return responseError(ctx, new Error("invalid chair_register_token"), 401);
}
const chairID = ulid();
const accessToken = secureRandomStr(32);
Expand All @@ -55,7 +58,7 @@ export const chairPostActivity = async (ctx: Context<Environment>) => {
chair.id,
]);
} catch (e) {
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
return ctx.body(null, 204);
};
Expand Down Expand Up @@ -106,7 +109,7 @@ export const chairPostCoordinate = async (ctx: Context<Environment>) => {
return ctx.json({ recorded_at: location.created_at.getTime() }, 200);
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
};

Expand Down Expand Up @@ -169,7 +172,7 @@ export const chairGetNotification = async (ctx: Context<Environment>) => {
);
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
};

Expand All @@ -184,10 +187,10 @@ export const chairPostRideStatus = async (ctx: Context<Environment>) => {
[rideID],
);
if (!ride) {
return ctx.text("ride not found", 404);
return responseError(ctx, new Error("ride not found"), 404);
}
if (ride.chair_id !== chair.id) {
return ctx.text("not assigned to this ride", 400);
return responseError(ctx, new Error("cnot assigned to this ride"), 400);
}
switch (reqJson.status) {
// Acknowledge the ride
Expand All @@ -201,7 +204,11 @@ export const chairPostRideStatus = async (ctx: Context<Environment>) => {
case "CARRYING": {
const status = await getLatestRideStatus(ctx.var.dbConn, ride.id);
if (status !== "PICKUP") {
return ctx.text("chair has not arrived yet", 400);
return responseError(
ctx,
new Error("chair has not arrived yet"),
400,
);
}
await ctx.var.dbConn.query(
"INSERT INTO ride_statuses (id, ride_id, status) VALUES (?, ?, ?)",
Expand All @@ -210,12 +217,12 @@ export const chairPostRideStatus = async (ctx: Context<Environment>) => {
break;
}
default:
return ctx.text("invalid status", 400);
return responseError(ctx, new Error("invalid status"), 400);
}
await ctx.var.dbConn.commit();
return ctx.body(null, 204);
} catch (e) {
await ctx.var.dbConn.rollback();
return ctx.text(`${e}`, 500);
return responseError(ctx, e, 500);
}
};
13 changes: 13 additions & 0 deletions webapp/nodejs/src/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { Connection, RowDataPacket } from "mysql2/promise";
import type { Ride, RideStatus } from "./types/models.js";
import type { Context } from "hono";
import type { StatusCode } from "hono/utils/http-status";

export const INITIAL_FARE = 500;
export const FARE_PER_DISTANCE = 100;
Expand Down Expand Up @@ -59,3 +61,14 @@ export class ErroredUpstream extends Error {
this.name = "ErroredUpstream";
}
}

export const responseError = (
ctx: Context,
error: unknown,
statusCode: StatusCode,
) => {
if (error instanceof Error) {
return ctx.json({ message: error.message }, statusCode);
}
throw new Error("error is not an instance of Error");
};
Loading