Skip to content

Commit 879d1af

Browse files
feat(close #1): Init source (#2)
* feat: Init source * refactor: Refactor * feat: update utils * feat: Update rollup.config.js * feat: remove redis, mongoose and some express middleware * ci: add github actions Co-authored-by: phatpham9 <phatpham9@gmail.com>
1 parent ca7f7b6 commit 879d1af

File tree

15 files changed

+3164
-1
lines changed

15 files changed

+3164
-1
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: create-github-release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v[0-9]+.[0-9]+.[0-9]+'
7+
8+
jobs:
9+
create-github-release:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v2
13+
- uses: actions/create-release@v1
14+
env:
15+
# This token is provided by Actions, you do not need to create your own token
16+
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
17+
with:
18+
tag_name: ${{github.ref}}
19+
release_name: Release ${{github.ref}}

.github/workflows/publish-npm.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: publish-npm
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v[0-9]+.[0-9]+.[0-9]+'
7+
8+
jobs:
9+
publish-npm:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v2
13+
- uses: actions/setup-node@v1
14+
with:
15+
node-version: 12
16+
registry-url: https://registry.npmjs.org
17+
- run: npm publish --access public
18+
env:
19+
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

.huskyrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"hooks": {
3+
"pre-commit": "yarn lint",
4+
"pre-push": "yarn build"
5+
}
6+
}

.npmignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.github
3+
.rpt2_cache

README.md

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div align="center">
22
<h1>utils</h1>
33
<p>Boring Utilities</p>
4-
4+
55
<div>
66
<a href="https://github.com/boringcodes/utils/commits" aria-label="Commitizen Friendly">
77
<img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square">
@@ -26,3 +26,72 @@
2626
</a>
2727
</div>
2828
</div>
29+
30+
## About
31+
This package implements a number of common `Boring Utilities`.
32+
33+
34+
## Installation
35+
This is a [Node.js](https://nodejs.org/en/) module available through the
36+
[npm registry](https://www.npmjs.com/).
37+
38+
Before installing, [download and install Node.js](https://nodejs.org/en/download/).
39+
Node.js 10.0 or higher is required.
40+
41+
Installation is done using the
42+
[`yarn add` command](https://classic.yarnpkg.com/en/docs/install/):
43+
44+
```bash
45+
$ yarn add @boringcodes/utils
46+
```
47+
48+
49+
## Features
50+
51+
The following modules are included:
52+
- [x] Node env detector
53+
- [x] Custom logger
54+
- [x] Custom errors classes
55+
- [x] Error handler
56+
- [x] Express middleware
57+
58+
## Usage
59+
60+
Then run the build command
61+
```bash
62+
yarn build
63+
```
64+
65+
## Directories
66+
67+
``` tree
68+
.
69+
├── CHANGELOG.md
70+
├── LICENSE
71+
├── README.md
72+
├── dist
73+
├── package.json
74+
├── rollup.config.js
75+
├── src
76+
│   ├── errorHandler.ts
77+
│   ├── error.ts
78+
│   ├── express.ts
79+
│   ├── index.ts
80+
│   ├── logger.ts
81+
├── tsconfig.json
82+
├── tslint.json
83+
```
84+
85+
## Contributing
86+
87+
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
88+
89+
Please make sure to update tests as appropriate.
90+
91+
## Authors
92+
93+
[BoringCodes](https://github.com/boringcodes)
94+
95+
## License
96+
97+
[MIT](https://github.com/boringcodes/utils/blob/master/LICENSE)

package.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "@boringcodes/utils",
3+
"version": "0.0.0",
4+
"description": "Boring Utilities",
5+
"homepage": "https://github.com/boringcodes/utils",
6+
"bugs": "https://github.com/boringcodes/utils/issues",
7+
"license": "MIT",
8+
"author": "BoringCodes <hi@boringcodes.com> (https://boringcodes.com)",
9+
"repository": "https://github.com/boringcodes/utils.git",
10+
"main": "dist/index.js",
11+
"typings": "dist/index.d.ts",
12+
"files": [
13+
"dist"
14+
],
15+
"scripts": {
16+
"clean": "rm -rf dist",
17+
"purge": "rm -rf node_modules",
18+
"dev": "rollup -cw",
19+
"prebuild": "yarn clean",
20+
"build": "rollup -c",
21+
"lint": "tslint --project tsconfig.json --config tslint.json",
22+
"release": "standard-version",
23+
"release:major": "yarn release --release-as major",
24+
"release:minor": "yarn release --release-as minor",
25+
"release:patch": "yarn release --release-as patch"
26+
},
27+
"devDependencies": {
28+
"@types/express": "^4.16.1",
29+
"@types/http-status-codes": "^1.2.0",
30+
"husky": "^2.3.0",
31+
"rollup": "^1.12.3",
32+
"rollup-plugin-async": "^1.2.0",
33+
"rollup-plugin-commonjs": "^10.0.0",
34+
"rollup-plugin-node-resolve": "^5.0.0",
35+
"rollup-plugin-sourcemaps": "^0.4.2",
36+
"rollup-plugin-typescript2": "^0.21.1",
37+
"standard-version": "^6.0.1",
38+
"tslint": "^5.16.0",
39+
"tslint-config-airbnb": "^5.11.1",
40+
"tslint-immutable": "^5.5.2",
41+
"tslint-sonarts": "^1.9.0",
42+
"typescript": "^3.4.5"
43+
},
44+
"dependencies": {
45+
"express": "^4.17.1",
46+
"http-status-codes": "^1.3.2"
47+
}
48+
}

rollup.config.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import resolve from 'rollup-plugin-node-resolve';
2+
import commonjs from 'rollup-plugin-commonjs';
3+
import typescript from 'rollup-plugin-typescript2';
4+
import async from 'rollup-plugin-async';
5+
import sourceMaps from 'rollup-plugin-sourcemaps';
6+
7+
import pkg from './package.json';
8+
9+
const common = {
10+
external: [
11+
...Object.keys(pkg.dependencies || {}),
12+
...Object.keys(pkg.peerDependencies || {}),
13+
],
14+
plugins: [
15+
resolve(),
16+
commonjs(),
17+
typescript({ useTsconfigDeclarationDir: true, rollupCommonJSResolveHack: true }),
18+
async(),
19+
sourceMaps(),
20+
],
21+
};
22+
23+
export default [
24+
{
25+
...common,
26+
input: 'src/error.ts',
27+
output: [
28+
{
29+
dir: 'dist',
30+
format: 'cjs',
31+
sourcemap: true,
32+
},
33+
],
34+
},
35+
{
36+
...common,
37+
input: 'src/errorHandler.ts',
38+
output: [
39+
{
40+
dir: 'dist',
41+
format: 'cjs',
42+
sourcemap: true,
43+
},
44+
],
45+
},
46+
{
47+
...common,
48+
input: 'src/express.ts',
49+
output: [
50+
{
51+
dir: 'dist',
52+
format: 'cjs',
53+
sourcemap: true,
54+
},
55+
],
56+
},
57+
{
58+
...common,
59+
input: 'src/index.ts',
60+
output: [
61+
{
62+
dir: 'dist',
63+
format: 'cjs',
64+
sourcemap: true,
65+
},
66+
],
67+
},
68+
{
69+
...common,
70+
input: 'src/logger.ts',
71+
output: [
72+
{
73+
dir: 'dist',
74+
format: 'cjs',
75+
sourcemap: true,
76+
},
77+
],
78+
},
79+
];

src/error.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { isDev } from '.';
2+
3+
class MyError extends Error {
4+
readonly operational?: boolean;
5+
6+
constructor(err: any, operational = false) {
7+
super();
8+
9+
this.name = err instanceof Error || typeof err === 'object' ? err.name : 'Error';
10+
this.message = err instanceof Error || typeof err === 'object' ? err.message : err;
11+
this.operational = operational;
12+
13+
// restore prototype chain
14+
Object.setPrototypeOf(this, new.target.prototype);
15+
16+
// Maintains proper stack trace for where our error was thrown (only available on V8)
17+
if (Error.captureStackTrace) {
18+
Error.captureStackTrace(this, MyError);
19+
}
20+
}
21+
}
22+
23+
/**
24+
* HttpError that takes the first parameter as an Http Status Code
25+
*/
26+
class HttpError extends MyError {
27+
readonly code: number;
28+
29+
constructor(code: number, err: any) {
30+
super(err, true);
31+
32+
this.code = code;
33+
this.name = 'HttpError';
34+
}
35+
36+
toJSON() {
37+
const content = {
38+
code: this.code,
39+
message: this.message,
40+
};
41+
42+
return !isDev() ? content : { ...content, error: this.stack };
43+
}
44+
}
45+
46+
export { MyError, HttpError };

src/errorHandler.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { MyError } from './error';
2+
import logger from './logger';
3+
4+
/**
5+
* Log error to destination then exit the process if programmer error
6+
* @param err error to be handled
7+
*/
8+
const handle = (err: MyError) => {
9+
// E.g. log to sentry
10+
// E.g. log to console
11+
logger.error(err);
12+
13+
if (!err.operational) {
14+
logger.info('> App exited!');
15+
16+
process.exit(1);
17+
}
18+
};
19+
20+
export { handle };
21+
export default { handle };

src/express.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Request, Response, NextFunction, Router } from 'express';
2+
import { NOT_FOUND, OK, INTERNAL_SERVER_ERROR, getStatusText } from 'http-status-codes';
3+
4+
import { HttpError } from './error';
5+
import errorHandler from './errorHandler';
6+
7+
// ---------------------------------------------------
8+
// -----------------Express Middleware----------------
9+
// ---------------------------------------------------
10+
11+
/**
12+
* An Express RequestHandler that handles the 404 Not Found error
13+
* @param _ Express Request object
14+
* @param __ Express Response object
15+
* @param next Express Next function
16+
*/
17+
const handleNotFound = (_: Request, __: Response, next: NextFunction) => {
18+
next(new HttpError(NOT_FOUND, 'Resource not found'));
19+
};
20+
21+
/**
22+
* An Express RequestHandler that responses error info to the client
23+
* @param err Http Error object
24+
* @param _ Express Request object
25+
* @param res Express Response object
26+
* @param __ Express Next function
27+
*/
28+
const handleErrors = (err: HttpError, _: Request, res: Response, __: NextFunction) => {
29+
errorHandler.handle(err);
30+
31+
try {
32+
// check if status code exists
33+
getStatusText(err.code);
34+
35+
res.status(err.code).send(err);
36+
} catch (error) {
37+
res.status(INTERNAL_SERVER_ERROR).send(err);
38+
}
39+
};
40+
41+
/**
42+
* An Express RequestHandler that responses OK for health checking
43+
* @param _ Express Request object
44+
* @param res Express Response object
45+
*/
46+
const handleHealthCheck = (_: Request, res: Response) => {
47+
res.status(OK).send('OK');
48+
};
49+
50+
/**
51+
* An Express Middleware mounted /health endpoint for health checking
52+
*/
53+
const health = () => {
54+
const router = Router();
55+
56+
router.get('/health', handleHealthCheck);
57+
58+
return router;
59+
};
60+
61+
export {
62+
handleNotFound,
63+
handleErrors,
64+
handleHealthCheck,
65+
66+
health,
67+
};

0 commit comments

Comments
 (0)