Skip to content

Commit 38bf039

Browse files
authored
fix: code refactor and cleanup (#13)
* docs: readme update * fix: frontend refactor & cleanup * fix: backend refactor & cleanup
1 parent 114f3ad commit 38bf039

16 files changed

+145
-200
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ Follow these steps to set up and run the application locally:
4646

4747
1. **Clone the Repository**:
4848
```
49-
git clone https://github.com/StackOneHQ/<repo-name>.git
49+
git clone https://github.com/StackOneHQ/ats-example-typescript.git
5050
```
5151
2. **Global Dependencies Setup**:
5252

53-
Navigate to the root directory of the project and install global dependencies:
53+
* Navigate to the root directory of the project and install global dependencies:
5454
```
5555
npm install
5656
```
@@ -60,17 +60,20 @@ npm install
6060
```
6161
PORT=3001
6262
STACKONE_API_KEY="<your-stackone-api-key>"
63+
ORIGIN_OWNER_ID="<ORIGIN_OWNER_ID>"
64+
ORIGIN_OWNER_NAME="<ORIGIN_OWNER_NAME>"
6365
```
6466
* Install dependencies for the backend:
6567
```
6668
npm install
6769
```
6870
4. **Frontend Setup**:
6971

70-
* Navigate to the `frontend` directory and create a `.env` file, and add the following variable:
72+
* Navigate to the `frontend` directory and create a `.env` file, and add the following variables:
7173

7274
```
73-
REACT_APP_API_BASE_URL="http://localhost:3001"
75+
REACT_APP_API_SESSION_URL="http://localhost:3001/session-token"
76+
REACT_APP_API_ATS_URL="http://localhost:3001/ats"
7477
```
7578
* Install dependencies:
7679
```
@@ -201,7 +204,4 @@ const getApplications = async (accountId: string, next: string) => {
201204
// Handle error
202205
}
203206
}
204-
```
205-
206-
207-
207+
```

backend/src/http/errorHandler.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import axios from 'axios';
2+
import {
3+
InvalidRequestError,
4+
ForbiddenRequestError,
5+
PreconditionFailedError,
6+
TooManyRequestsError,
7+
ServerError,
8+
NotImplementedError,
9+
UnhandledError
10+
} from '../errors/stackoneErrors';
11+
12+
export const AxiosError = (error: unknown) => {
13+
if (axios.isAxiosError(error)) {
14+
const errorMessage = error.response?.data?.message || 'An error occurred';
15+
switch (error.response?.status) {
16+
case 400:
17+
throw new InvalidRequestError(errorMessage);
18+
case 403:
19+
throw new ForbiddenRequestError(errorMessage);
20+
case 412:
21+
throw new PreconditionFailedError(errorMessage);
22+
case 429:
23+
throw new TooManyRequestsError(errorMessage);
24+
case 500:
25+
throw new ServerError(errorMessage);
26+
case 501:
27+
throw new NotImplementedError(errorMessage);
28+
default:
29+
throw new UnhandledError(`Unexpected error: ${error.response?.status} - ${errorMessage}`);
30+
}
31+
} else {
32+
throw new UnhandledError(`Unexpected error: ${error}`);
33+
}
34+
};
Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import axios from "axios";
22
import config from "../config";
3-
import { InvalidRequestError, ForbiddenRequestError, TooManyRequestsError, ServerError, NotImplementedError, UnhandledError } from '../errors/stackoneErrors';
3+
import { AxiosError } from "./errorHandler";
44

55
export const getAllAccounts = async () => {
66

@@ -12,27 +12,8 @@ export const getAllAccounts = async () => {
1212
'authorization': `Basic ${config.STACKONE_API_KEY}`,
1313
},
1414
});
15-
1615
return response.data;
1716
} catch (error) {
18-
if (axios.isAxiosError(error)) {
19-
const errorMessage = error.response?.data?.message || 'An error occurred';
20-
switch (error.response?.status) {
21-
case 400:
22-
throw new InvalidRequestError(errorMessage);
23-
case 403:
24-
throw new ForbiddenRequestError(errorMessage);
25-
case 429:
26-
throw new TooManyRequestsError(errorMessage);
27-
case 500:
28-
throw new ServerError(errorMessage);
29-
case 501:
30-
throw new NotImplementedError(errorMessage);
31-
default:
32-
throw new UnhandledError(`Unexpected error: ${error.response?.status} - ${errorMessage}`);
33-
}
34-
} else {
35-
throw new UnhandledError(`Unexpected error: ${error}`);
36-
}
17+
AxiosError(error)
3718
}
3819
}

backend/src/http/stackOneAts.ts

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import axios from "axios";
22
import config from '../config';
3-
import { InvalidRequestError, ForbiddenRequestError, PreconditionFailedError, TooManyRequestsError, ServerError, NotImplementedError, UnhandledError } from '../errors/stackoneErrors';
3+
import { AxiosError } from "./errorHandler";
44

55
export const getJobs = async (accountId: string, next: string) => {
66

@@ -20,27 +20,7 @@ export const getJobs = async (accountId: string, next: string) => {
2020
});
2121
return response.data;
2222
} catch (error) {
23-
if (axios.isAxiosError(error)) {
24-
const errorMessage = error.response?.data?.message || 'An error occurred';
25-
switch (error.response?.status) {
26-
case 400:
27-
throw new InvalidRequestError(errorMessage);
28-
case 403:
29-
throw new ForbiddenRequestError(errorMessage);
30-
case 412:
31-
throw new PreconditionFailedError(errorMessage);
32-
case 429:
33-
throw new TooManyRequestsError(errorMessage);
34-
case 500:
35-
throw new ServerError(errorMessage);
36-
case 501:
37-
throw new NotImplementedError(errorMessage);
38-
default:
39-
throw new UnhandledError(`Unexpected error: ${error.response?.status} - ${errorMessage}`);
40-
}
41-
} else {
42-
throw new UnhandledError(`Unexpected error: ${error}`);
43-
}
23+
AxiosError(error);
4424
}
4525
}
4626

@@ -61,26 +41,6 @@ export const getApplications = async (accountId: string, next: string) => {
6141
});
6242
return response.data;
6343
} catch (error) {
64-
if (axios.isAxiosError(error)) {
65-
const errorMessage = error.response?.data?.message || 'An error occurred';
66-
switch (error.response?.status) {
67-
case 400:
68-
throw new InvalidRequestError(errorMessage);
69-
case 403:
70-
throw new ForbiddenRequestError(errorMessage);
71-
case 412:
72-
throw new PreconditionFailedError(errorMessage);
73-
case 429:
74-
throw new TooManyRequestsError(errorMessage);
75-
case 500:
76-
throw new ServerError(errorMessage);
77-
case 501:
78-
throw new NotImplementedError(errorMessage);
79-
default:
80-
throw new UnhandledError(`Unexpected error: ${error.response?.status} - ${errorMessage}`);
81-
}
82-
} else {
83-
throw new UnhandledError(`Unexpected error: ${error}`);
84-
}
44+
AxiosError(error);
8545
}
8646
}
Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import axios from "axios";
22
import config from "../config";
3-
import { InvalidRequestError, ForbiddenRequestError, TooManyRequestsError, ServerError, NotImplementedError, UnhandledError } from '../errors/stackoneErrors';
3+
import { AxiosError } from "./errorHandler";
44

55
export const getSessionToken = async () => {
66

@@ -20,27 +20,8 @@ export const getSessionToken = async () => {
2020
'authorization': `Basic ${config.STACKONE_API_KEY}`,
2121
},
2222
});
23-
2423
return response.data;
2524
} catch (error) {
26-
if (axios.isAxiosError(error)) {
27-
const errorMessage = error.response?.data?.message || 'An error occurred';
28-
switch (error.response?.status) {
29-
case 400:
30-
throw new InvalidRequestError(errorMessage);
31-
case 403:
32-
throw new ForbiddenRequestError(errorMessage);
33-
case 429:
34-
throw new TooManyRequestsError(errorMessage);
35-
case 500:
36-
throw new ServerError(errorMessage);
37-
case 501:
38-
throw new NotImplementedError(errorMessage);
39-
default:
40-
throw new UnhandledError(`Unexpected error: ${error.response?.status} - ${errorMessage}`);
41-
}
42-
} else {
43-
throw new UnhandledError(`Unexpected error: ${error}`);
44-
}
25+
AxiosError(error);
4526
}
4627
}

backend/src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ const port = config.PORT;
1111

1212
app.use(cors());
1313
app.use(bodyParser.json());
14-
app.use('/stackone', stackoneAtsRoutes);
15-
app.use('/stackone', stackoneSessionRoute);
16-
app.use('/stackone', stackoneAccountRoute);
14+
app.use('/ats', stackoneAtsRoutes);
15+
app.use('/session-token', stackoneSessionRoute);
16+
app.use('/ats', stackoneAccountRoute);
1717

1818
app.listen(port, () => {
1919
console.log(`Server is running on http://localhost:${port}`);

backend/src/routes/accountsRoute.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,16 @@
11
import express from 'express';
22
import { Request, Response } from 'express';
3-
import { InvalidRequestError, ForbiddenRequestError, TooManyRequestsError, ServerError, NotImplementedError, UnhandledError } from '../errors/stackoneErrors';
43
import { listAllAccounts } from '../service/accountsService';
4+
import { handleErrorResponse } from './routesErrorHandler';
55

66
const router = express.Router();
7-
const isKnownError = (error: unknown): error is InvalidRequestError | ForbiddenRequestError | TooManyRequestsError | ServerError | NotImplementedError | UnhandledError => {
8-
return error instanceof InvalidRequestError ||
9-
error instanceof ForbiddenRequestError ||
10-
error instanceof TooManyRequestsError ||
11-
error instanceof ServerError ||
12-
error instanceof NotImplementedError ||
13-
error instanceof UnhandledError;
14-
};
157

168
router.get('/accounts', async (req: Request, res: Response) => {
17-
189
try {
1910
const accounts = await listAllAccounts();
2011
res.status(200).send(accounts);
2112
} catch (error: unknown) {
22-
if (isKnownError(error)) {
23-
res.status(error.status).json({ code: error.code, message: error.message });
24-
} else {
25-
res.status(500).json({ message: 'An unexpected error occurred.' });
26-
}
13+
handleErrorResponse(error, res);
2714
}
2815
});
2916

backend/src/routes/atsRoutes.ts

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
11
import express from 'express';
2-
import { InvalidRequestError, ForbiddenRequestError, PreconditionFailedError, TooManyRequestsError, ServerError, NotImplementedError, UnhandledError } from '../errors/stackoneErrors';
32
import { listAllApplications, listAllJobs } from '../service/atsService';
43
import { Request, Response } from 'express';
4+
import { handleErrorResponse } from './routesErrorHandler';
55

66
const router = express.Router();
77

8-
const isKnownError = (error: unknown): error is InvalidRequestError | ForbiddenRequestError | PreconditionFailedError | TooManyRequestsError | ServerError | NotImplementedError | UnhandledError => {
9-
return error instanceof InvalidRequestError ||
10-
error instanceof ForbiddenRequestError ||
11-
error instanceof PreconditionFailedError ||
12-
error instanceof TooManyRequestsError ||
13-
error instanceof ServerError ||
14-
error instanceof NotImplementedError ||
15-
error instanceof UnhandledError;
16-
};
17-
188
router.get('/jobs', async (req: Request, res: Response) => {
199
const { query, headers } = req;
2010
const next: string = query.next as string;
@@ -24,11 +14,7 @@ router.get('/jobs', async (req: Request, res: Response) => {
2414
const jobs = await listAllJobs(accountId, next);
2515
res.status(200).send(jobs);
2616
} catch (error: unknown) {
27-
if (isKnownError(error)) {
28-
res.status(error.status).json({ code: error.code, message: error.message });
29-
} else {
30-
res.status(500).json({ message: 'An unexpected error occurred.' });
31-
}
17+
handleErrorResponse(error, res);
3218
}
3319
});
3420

@@ -41,11 +27,7 @@ router.get('/applications', async (req: Request, res: Response) => {
4127
const applications = await listAllApplications(accountId, next);
4228
res.status(200).send(applications);
4329
} catch (error: unknown) {
44-
if (isKnownError(error)) {
45-
res.status(error.status).json({ code: error.code, message: error.message });
46-
} else {
47-
res.status(500).json({ message: 'An unexpected error occurred.' });
48-
}
30+
handleErrorResponse(error, res);
4931
}
5032
});
5133

backend/src/routes/connectRoute.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,17 @@
11
import express from 'express';
22
import { Request, Response } from 'express';
3-
import { InvalidRequestError, ForbiddenRequestError, TooManyRequestsError, ServerError, NotImplementedError, UnhandledError } from '../errors/stackoneErrors';
43
import { connectStackOneSession } from '../service/sessionTokenService';
4+
import { handleErrorResponse } from './routesErrorHandler';
55

66
const router = express.Router();
7-
const isKnownError = (error: unknown): error is InvalidRequestError | ForbiddenRequestError | TooManyRequestsError | ServerError | NotImplementedError | UnhandledError => {
8-
return error instanceof InvalidRequestError ||
9-
error instanceof ForbiddenRequestError ||
10-
error instanceof TooManyRequestsError ||
11-
error instanceof ServerError ||
12-
error instanceof NotImplementedError ||
13-
error instanceof UnhandledError;
14-
};
157

168
router.post('/connect-session', async (req: Request, res: Response) => {
17-
189
try {
1910
const sessionToken = await connectStackOneSession();
2011
res.status(200).send(sessionToken);
2112
} catch (error: unknown) {
22-
if (isKnownError(error)) {
23-
res.status(error.status).json({ code: error.code, message: error.message });
24-
} else {
25-
res.status(500).json({ message: 'An unexpected error occurred.' });
26-
}
13+
handleErrorResponse(error, res);
2714
}
2815
});
2916

30-
export default router;
17+
export default router;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { InvalidRequestError, ForbiddenRequestError, PreconditionFailedError, TooManyRequestsError, ServerError, NotImplementedError, UnhandledError } from '../errors/stackoneErrors';
2+
import { Response } from 'express';
3+
4+
export const isKnownError = (
5+
error: unknown
6+
): error is InvalidRequestError | ForbiddenRequestError | PreconditionFailedError | TooManyRequestsError | ServerError | NotImplementedError | UnhandledError => {
7+
return (
8+
error instanceof InvalidRequestError ||
9+
error instanceof ForbiddenRequestError ||
10+
error instanceof PreconditionFailedError ||
11+
error instanceof TooManyRequestsError ||
12+
error instanceof ServerError ||
13+
error instanceof NotImplementedError ||
14+
error instanceof UnhandledError
15+
);
16+
};
17+
18+
export const handleErrorResponse = (error: unknown, res: Response) => {
19+
if (isKnownError(error)) {
20+
res.status(error.status).json({ code: error.code, message: error.message });
21+
} else {
22+
res.status(500).json({ message: 'An unexpected error occurred.' });
23+
}
24+
};

0 commit comments

Comments
 (0)