Skip to content

Commit 5858a6e

Browse files
feat(Close #1): Init source (#2)
* feat(Close #1): Init source * refactor(Close #1): Refactor * refactor: Refactor * feat(Close #1): Add release scripts * refactor(Close #1): Refactor source codes * feat(Close #1): Add back tslint * feat: remove mongoose Co-authored-by: phatpham9 <phatpham9@gmail.com>
1 parent a78fbed commit 5858a6e

File tree

17 files changed

+3129
-0
lines changed

17 files changed

+3129
-0
lines changed

README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,60 @@
2626
</a>
2727
</div>
2828
</div>
29+
30+
## Install
31+
32+
Make sure `yeoman` is installed:
33+
34+
```sh
35+
$ yarn global add yo
36+
```
37+
38+
Then install the generator
39+
40+
```sh
41+
$ yarn global add @boringcodes/create-service
42+
```
43+
44+
## Usage
45+
46+
With [yo](https://github.com/yeoman/yo):
47+
48+
```sh
49+
$ yo create-service
50+
```
51+
52+
This scaffolds out:
53+
```
54+
├── Dockerfile
55+
├── README.md
56+
├── package.json
57+
└── src
58+
├── app.ts
59+
├── components
60+
│   ├── things
61+
│   │   ├── constants.ts
62+
│   │   ├── controller.ts
63+
│   │   ├── index.ts
64+
│   │   ├── middleware.ts
65+
│   │   ├── model.ts
66+
│   │   ├── repository.ts
67+
│   │   └── type.ts
68+
│   └── types.ts
69+
├── index.ts
70+
└── routes.ts
71+
```
72+
73+
## Contributing
74+
75+
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
76+
77+
Please make sure to update tests as appropriate.
78+
79+
## Authors
80+
81+
[BoringCodes](https://github.com/boringcodes)
82+
83+
## License
84+
85+
[MIT](https://github.com/boringcodes/create-service/blob/master/LICENSE)

generators/app/index.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const Generator = require('yeoman-generator');
2+
const chalk = require("chalk");
3+
const yosay = require("yosay");
4+
const pkg = require('../../package.json');
5+
6+
module.exports = class extends Generator {
7+
async prompting() {
8+
this.log(
9+
yosay(
10+
`Welcome to the astounding ${chalk.red(pkg.name)} generator!`
11+
)
12+
);
13+
14+
const prompts = [
15+
{
16+
type: "input",
17+
name: "elementName",
18+
message: "What is the name of your service?",
19+
default: "my-awesome-service"
20+
},
21+
{
22+
type: "input",
23+
name: "elementDescription",
24+
message: "Give us some small description of your service",
25+
default: ""
26+
},
27+
{
28+
type: "input",
29+
name: "elementAuthor",
30+
message: "Who is the author of this service?",
31+
default: ""
32+
},
33+
];
34+
35+
return this.prompt(prompts).then(props => {
36+
// To access props later use this.props.someAnswer;
37+
this.props = props;
38+
});
39+
}
40+
41+
writing() {
42+
this.fs.copyTpl(
43+
[
44+
this.templatePath('**'),
45+
],
46+
this.destinationPath(),
47+
this.props,
48+
);
49+
50+
this.fs.copyTpl(
51+
this.templatePath('.env.example'),
52+
this.destinationPath('.env.example')
53+
);
54+
}
55+
56+
install () {
57+
this.installDependencies();
58+
}
59+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
NODE_ENV=development
2+
3+
HOST=localhost
4+
PORT=9000
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# dependencies
2+
node_modules
3+
package-lock.json
4+
test/node_modules
5+
6+
7+
# testing
8+
.nyc_output
9+
coverage
10+
11+
# build output
12+
build
13+
dist
14+
15+
# misc
16+
.DS_Store
17+
.env
18+
npm-debug.log*
19+
yarn-debug.log*
20+
yarn-error.log*
21+
22+
# logs & pids
23+
*.log
24+
pids
25+
.idea

generators/app/templates/.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+
}

generators/app/templates/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# <%= elementName %>
2+
3+
API Service Starter Kit
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"name": "<%= elementName %>",
3+
"description": "<%= elementDescription %>",
4+
"version": "0.0.0",
5+
"private": true,
6+
"license": "MIT",
7+
"author": "<%= elementAuthor %>",
8+
"repository": "",
9+
"bugs": "",
10+
"scripts": {
11+
"clean": "rm -rf build",
12+
"purge": "rm -rf node_modules",
13+
"dev": "backpack dev",
14+
"prebuild": "yarn clean",
15+
"build": "backpack build",
16+
"lint": "tslint --project ./node_modules/@boringcodes/backpack/config/tsconfig.json --config tslint.json",
17+
"start": "NODE_ENV=production node build/index.js",
18+
"release": "standard-version",
19+
"release:major": "yarn release --release-as major",
20+
"release:minor": "yarn release --release-as minor",
21+
"release:patch": "yarn release --release-as patch"
22+
},
23+
"dependencies": {
24+
"@boringcodes/utils": "*",
25+
"body-parser": "^1.18.3",
26+
"express": "^4.16.4",
27+
"http-status-codes": "^1.3.0",
28+
"morgan": "^1.9.1",
29+
"yup": "^0.26.6"
30+
},
31+
"devDependencies": {
32+
"@types/express": "^4.16.0",
33+
"@types/morgan": "^1.7.35",
34+
"@types/qs": "^6.5.1",
35+
"@types/yup": "^0.26.3",
36+
"husky": "^1.2.1",
37+
"standard-version": "^4.4.0",
38+
"@boringcodes/backpack": "*",
39+
"tslint": "^5.11.0",
40+
"tslint-config-airbnb": "^5.11.1",
41+
"tslint-immutable": "^5.0.0",
42+
"tslint-sonarts": "^1.8.0"
43+
}
44+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import express from 'express';
2+
import morgan from 'morgan';
3+
import bodyParser from 'body-parser';
4+
import { isDev } from '@boringcodes/utils/dist';
5+
import { health, handleNotFound, handleErrors } from '@boringcodes/utils/dist/express';
6+
7+
import routes from './routes';
8+
9+
// initialize app
10+
const app = express();
11+
const dev = isDev();
12+
13+
// plug middleware
14+
app.use(morgan(dev ? 'dev' : 'common'));
15+
app.use(bodyParser.urlencoded({ extended: true }));
16+
app.use(bodyParser.json());
17+
app.use(health());
18+
19+
// plug routes
20+
app.use(routes({ dev }));
21+
22+
// handle errors
23+
app.use(handleNotFound);
24+
app.use(handleErrors);
25+
26+
export default app;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const NAME = 'thing';
2+
const PLURAL_NAME = 'things';
3+
4+
export {
5+
NAME,
6+
PLURAL_NAME,
7+
};
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { Request as ExpressRequest, Response, NextFunction } from 'express';
2+
import { BAD_REQUEST, NOT_FOUND, INTERNAL_SERVER_ERROR } from 'http-status-codes';
3+
import { HttpError } from '@boringcodes/utils/dist/error';
4+
5+
import { NAME } from './constants';
6+
7+
type Request = ExpressRequest & {
8+
readonly [NAME]: any,
9+
};
10+
11+
const list = async (_: Request, res: Response, next: NextFunction) => {
12+
try {
13+
// TODO: list things
14+
const things = [];
15+
16+
res.send(things);
17+
} catch (err) {
18+
next(new HttpError(err.code || INTERNAL_SERVER_ERROR, err));
19+
}
20+
};
21+
22+
const count = async (_: Request, res: Response, next: NextFunction) => {
23+
try {
24+
// TODO: count things
25+
const count = 0;
26+
27+
res.send({ count });
28+
} catch (err) {
29+
next(new HttpError(err.code || INTERNAL_SERVER_ERROR, err));
30+
}
31+
};
32+
33+
const create = async (_: Request, res: Response, next: NextFunction) => {
34+
try {
35+
// TODO: create thing
36+
const thing = {};
37+
38+
res.send(thing);
39+
} catch (err) {
40+
next(new HttpError(err.code || INTERNAL_SERVER_ERROR, err));
41+
}
42+
};
43+
44+
const getById = async (req: Request, _: Response, next: NextFunction) => {
45+
if (!req.params.id) {
46+
next(new HttpError(BAD_REQUEST, 'Invalid resource Id'));
47+
48+
return;
49+
}
50+
51+
try {
52+
// TODO: get thing
53+
const thing = {};
54+
55+
if (!thing) {
56+
next(new HttpError(NOT_FOUND, 'Resource not found'));
57+
58+
return;
59+
}
60+
// tslint:disable-next-line:no-object-mutation
61+
Object.assign(req, { [NAME]: thing });
62+
63+
next();
64+
} catch (err) {
65+
next(new HttpError(err.code || INTERNAL_SERVER_ERROR, err));
66+
}
67+
};
68+
69+
const get = (req: Request, res: Response) => {
70+
res.send(req[NAME]);
71+
};
72+
73+
const update = async (req: Request, res: Response, next: NextFunction) => {
74+
try {
75+
// TODO: update thing
76+
const thing = req[NAME];
77+
78+
res.send(thing);
79+
} catch (err) {
80+
next(err);
81+
}
82+
};
83+
84+
const del = async (req: Request, res: Response, next: NextFunction) => {
85+
try {
86+
// TODO: delete thing
87+
const thing = req[NAME];
88+
89+
res.send(thing);
90+
} catch (err) {
91+
next(new HttpError(err.code || INTERNAL_SERVER_ERROR, err));
92+
}
93+
};
94+
95+
export {
96+
list,
97+
create,
98+
count,
99+
getById,
100+
get,
101+
update,
102+
del,
103+
};

0 commit comments

Comments
 (0)