Skip to content

Commit e2dae27

Browse files
committed
REFACTOR/api encapsulated
1 parent 7923641 commit e2dae27

37 files changed

+174
-130
lines changed

apps/api/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
"version": "0.0.1",
44
"private": true,
55
"type": "module",
6-
"types": "./dist/index.d.ts",
6+
"exports": {
7+
".": {
8+
"types": "./dist/client.d.ts",
9+
"import": "./dist/client.js"
10+
}
11+
},
712
"scripts": {
813
"dev": "tsx watch ./src/index.ts",
914
"build": "tsup",

apps/api/src/client.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { DetailedError, hc, parseResponse } from "hono/client";
2+
import { z } from "zod";
3+
import { constant } from "@gym-graphs/constants";
4+
import type { Api } from "~/index";
5+
import type {
6+
ClientRequestOptions,
7+
ClientResponse,
8+
InferRequestType,
9+
} from "hono/client";
10+
11+
export const api = (options: ClientRequestOptions) => {
12+
return hc<Api>(constant.url.api, options).api;
13+
};
14+
15+
export type ApiReqOption = Parameters<typeof api>[0];
16+
17+
export type InferApiReqInput<T> = InferRequestType<T>;
18+
19+
export const parseJsonResponse = async <T extends ClientResponse<any>>(
20+
req: T | Promise<T>,
21+
): ApiResponse<T> => {
22+
try {
23+
return await parseResponse(req);
24+
} catch (e) {
25+
if (e instanceof DetailedError) {
26+
const msg = detailsErrorSchema.catch(e.message).parse(e.detail);
27+
28+
throw new Error(msg, { cause: e });
29+
}
30+
31+
throw e;
32+
}
33+
};
34+
35+
const detailsErrorSchema = z
36+
.object({
37+
data: z.object({
38+
message: z.string(),
39+
}),
40+
})
41+
.transform((err) => err.data.message);
42+
43+
//forcing tsup to bundle the return type of parseResponse as hono does not export it
44+
type ApiResponse<T extends ClientResponse<any>> = ReturnType<
45+
typeof parseResponse<T>
46+
>;

apps/web/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"dependencies": {
1616
"@dnd-kit/core": "^6.3.1",
1717
"@dnd-kit/sortable": "^10.0.0",
18+
"@gym-graphs/api": "workspace:*",
1819
"@gym-graphs/constants": "workspace:*",
1920
"@gym-graphs/schemas": "workspace:*",
2021
"@hookform/resolvers": "^5.2.2",
@@ -50,7 +51,6 @@
5051
"@visx/vendor": "^3.12.0",
5152
"class-variance-authority": "^0.7.1",
5253
"clsx": "^2.1.1",
53-
"hono": "^4.9.11",
5454
"input-otp": "^1.4.2",
5555
"nitro": "3.0.1-alpha.0",
5656
"react": "^19.0.0",
@@ -62,7 +62,6 @@
6262
"zod": "^4.1.12"
6363
},
6464
"devDependencies": {
65-
"@gym-graphs/api": "workspace:*",
6665
"@gym-graphs/db": "workspace:*",
6766
"@tanstack/react-query-devtools": "^5.62.11",
6867
"@tanstack/react-router-devtools": "^1.133.3",

apps/web/src/domains/dashboard/components/dashboard.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import {
3030
} from "~/domains/dashboard/components/trending-view-tile";
3131
import { useUser } from "~/domains/user/hooks/use-user";
3232
import { tileQueries } from "~/domains/tile/tile.queries";
33-
import { api, parseJsonResponse } from "~/libs/api";
33+
import { api } from "~/libs/api";
34+
import { parseJsonResponse } from "@gym-graphs/api";
3435
import type {
3536
ComponentProps,
3637
CSSProperties,
@@ -44,7 +45,7 @@ import type {
4445
ScreenReaderInstructions,
4546
UniqueIdentifier,
4647
} from "@dnd-kit/core";
47-
import type { InferRequestType } from "hono";
48+
import type { InferApiReqInput } from "@gym-graphs/api";
4849

4950
export const Dashboard = () => {
5051
return (
@@ -377,7 +378,7 @@ const useReorderTiles = () => {
377378
const req = api().tiles.reorder.$put;
378379

379380
return useMutation({
380-
mutationFn: async (input: InferRequestType<typeof req>) => {
381+
mutationFn: async (input: InferApiReqInput<typeof req>) => {
381382
return parseJsonResponse(req(input));
382383
},
383384
});

apps/web/src/domains/dashboard/components/view-toggle.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { userSchema } from "@gym-graphs/schemas/user";
44
import { useUser } from "~/domains/user/hooks/use-user";
55
import { useMutation } from "@tanstack/react-query";
66
import { userQueries } from "~/domains/user/user.queries";
7-
import { api, parseJsonResponse } from "~/libs/api";
8-
import type { InferRequestType } from "hono";
7+
import { api } from "~/libs/api";
8+
import { parseJsonResponse } from "@gym-graphs/api";
9+
import type { InferApiReqInput } from "@gym-graphs/api";
910

1011
const useUpdateDashboadView = () => {
1112
const req = api().users.me.$patch;
@@ -15,7 +16,7 @@ const useUpdateDashboadView = () => {
1516
};
1617

1718
return useMutation({
18-
mutationFn: async (input: InferRequestType<typeof req>) => {
19+
mutationFn: async (input: InferApiReqInput<typeof req>) => {
1920
return parseJsonResponse(req(input));
2021
},
2122
onMutate: async (variables, ctx) => {

apps/web/src/domains/exercise/exercise.queries.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { queryOptions } from "@tanstack/react-query";
2+
import { api } from "~/libs/api";
3+
import { parseJsonResponse } from "@gym-graphs/api";
24
import type { Exercise } from "@gym-graphs/db/schemas";
3-
import { api, parseJsonResponse } from "~/libs/api";
45

56
const get = (exerciseId: Exercise["id"]) => {
67
return queryOptions({

apps/web/src/domains/oauth/components/github-sign-in.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { useTransition } from "react";
55
import { getRouteApi } from "@tanstack/react-router";
66
import { Alert, AlertDescription, AlertTitle } from "~/ui/alert";
77
import { AlertCircleIcon, GithubIcon } from "~/ui/icons";
8-
import { api, parseJsonResponse } from "~/libs/api";
9-
import type { InferRequestType } from "hono";
8+
import { api } from "~/libs/api";
9+
import { parseJsonResponse } from "@gym-graphs/api";
10+
import type { InferApiReqInput } from "@gym-graphs/api";
1011

1112
const routeApi = getRouteApi("/(auth)/_layout");
1213

@@ -43,7 +44,7 @@ const useGithubSignIn = () => {
4344
const req = api().oauth.github.$post;
4445

4546
const githubSignIn = useMutation({
46-
mutationFn: async (query: InferRequestType<typeof req>["query"]) => {
47+
mutationFn: async (query: InferApiReqInput<typeof req>["query"]) => {
4748
return parseJsonResponse(req({ query }));
4849
},
4950
onSuccess: (url) => {

apps/web/src/domains/session/hooks/use-sign-out.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useMutation, useQueryClient } from "@tanstack/react-query";
22
import { useNavigate } from "@tanstack/react-router";
33
import { useTransition } from "react";
4-
import { api, parseJsonResponse } from "~/libs/api";
4+
import { api } from "~/libs/api";
5+
import { parseJsonResponse } from "@gym-graphs/api";
56

67
export const useSignOut = () => {
78
const [isRedirectPending, startRedirectTransition] = useTransition();

apps/web/src/domains/session/session.queries.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { queryOptions } from "@tanstack/react-query";
2-
import { parseResponse } from "hono/client";
2+
import { parseJsonResponse } from "@gym-graphs/api";
33
import { api } from "~/libs/api";
44

55
const get = queryOptions({
66
queryKey: ["session"],
77
queryFn: async ({ signal }) => {
88
const req = api().sessions.me.$get(undefined, { init: { signal } });
99

10-
return parseResponse(req);
10+
return parseJsonResponse(req);
1111
},
1212
});
1313

apps/web/src/domains/set/components/create-set-form.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ import { getRouteApi } from "@tanstack/react-router";
1111
import { CounterInput } from "~/ui/counter-input";
1212
import { useLastSet } from "~/domains/set/hooks/use-last-set";
1313
import { WeightUnit } from "~/domains/user/components/weight-unit";
14-
import { api, parseJsonResponse } from "~/libs/api";
14+
import { api } from "~/libs/api";
15+
import { parseJsonResponse } from "@gym-graphs/api";
1516
import { tileQueries } from "~/domains/tile/tile.queries";
1617
import { Field, FieldError, FieldGroup, FieldLabel } from "~/ui/field";
1718
import { Alert, AlertDescription, AlertTitle } from "~/ui/alert";
1819
import { AlertCircleIcon } from "~/ui/icons";
19-
import type { InferRequestType } from "hono";
20+
import type { InferApiReqInput } from "@gym-graphs/api";
2021

2122
export const CreateSetForm = (props: Props) => {
2223
const form = useCreateExerciseSetForm();
@@ -158,7 +159,7 @@ const useCreateSet = () => {
158159
};
159160

160161
return useMutation({
161-
mutationFn: async (input: InferRequestType<typeof req>) => {
162+
mutationFn: async (input: InferApiReqInput<typeof req>) => {
162163
return parseJsonResponse(req(input));
163164
},
164165
onMutate: async (variables, ctx) => {

0 commit comments

Comments
 (0)