Skip to content

Commit 87952b8

Browse files
committed
feat(generators): create new app :with-postgres-prisma
1 parent d7d8098 commit 87952b8

File tree

7 files changed

+257
-2
lines changed

7 files changed

+257
-2
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ $ yo create-service-component:with-postgres
6666

6767
# or :with-postgres-typeorm
6868
$ yo create-service-component:with-postgres-typeorm
69+
70+
# or :with-postgres-prisma
71+
$ yo create-service-component:with-postgres-prisma
6972
```
7073

7174
This scaffolds out:
@@ -77,8 +80,8 @@ This scaffolds out:
7780
│ │   │   ├── constants.ts
7881
│ │   │   ├── controller.ts
7982
│ │   │   ├── index.ts
80-
│ │   │   ├── model.ts (:with-mongo, :with-postgres or :with-postgres-typeorm)
81-
│ │   │   ├── repository.ts (:with-mongo, :with-postgres or :with-postgres-typeorm)
83+
│ │   │   ├── model.ts (:with-mongo/:with-postgres/:with-postgres-typeorm)
84+
│ │   │   ├── repository.ts (:with-mongo/:with-postgres/:with-postgres-typeorm/:with-postgres-prisma)
8285
│ │   │   ├── types.ts
8386
│ │   └── ...
8487
│ ├── ...
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const Generator = require('yeoman-generator');
2+
const chalk = require('chalk');
3+
const yosay = require('yosay');
4+
const changeCase = require('change-case');
5+
const pluralize = require('pluralize');
6+
7+
const pkg = require('../../package.json');
8+
9+
module.exports = class extends Generator {
10+
async prompting() {
11+
this.log(yosay(`Welcome to the ${chalk.red(pkg.name)} generator!`));
12+
13+
const prompts = [
14+
{
15+
type: 'input',
16+
name: 'compName',
17+
message: 'Name of the new component (singular)?',
18+
default: 'thing',
19+
},
20+
];
21+
22+
return this.prompt(prompts).then((props) => {
23+
const compNameParamCase = changeCase.paramCase(props.compName);
24+
const compNamePascalCase = changeCase.pascalCase(props.compName);
25+
const compNameCamelCase = changeCase.camelCase(props.compName);
26+
27+
this.props = {
28+
// param-case
29+
compNameParamCase,
30+
// param-cases
31+
compNameParamCasePlural: pluralize(compNameParamCase),
32+
// PascalCase
33+
compNamePascalCase,
34+
// PasCalCases
35+
compNamePascalCasePlural: pluralize(compNamePascalCase),
36+
// camelCase
37+
compNameCamelCase,
38+
// camelCases
39+
compNameCamelCasePlural: pluralize(compNameCamelCase),
40+
};
41+
});
42+
}
43+
44+
writing() {
45+
this.fs.copyTpl(
46+
[this.templatePath('**/*'), this.templatePath('**/.*')],
47+
this.destinationPath('src/components'),
48+
this.props,
49+
);
50+
}
51+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const ENTITY = '<%= compNameParamCase %>';
2+
const RESOURCE = '<%= compNameParamCasePlural %>';
3+
4+
export { ENTITY, RESOURCE };
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { Request, Response, NextFunction } from 'express';
2+
import { StatusCodes } from 'http-status-codes';
3+
import { HttpError } from '@boringcodes/utils/error';
4+
5+
import { <%= compNamePascalCase %> } from './types';
6+
import { ENTITY } from './constants';
7+
import repository from './repository';
8+
9+
interface MyRequest extends Request {
10+
readonly [ENTITY]: Required<<%= compNamePascalCase %>>;
11+
}
12+
13+
const getById = async (
14+
req: Request,
15+
_: Response,
16+
next: NextFunction,
17+
): Promise<void> => {
18+
try {
19+
const { id = '' } = req.params;
20+
if (id === '') {
21+
throw new HttpError(StatusCodes.BAD_REQUEST, 'Invalid resource Id');
22+
}
23+
24+
try {
25+
// get object by id
26+
const object = await repository.get(+id);
27+
28+
// assign object to request for using in the next handlers
29+
Object.assign(req, { [ENTITY]: object });
30+
31+
next();
32+
} catch (err) {
33+
throw new HttpError(StatusCodes.NOT_FOUND, 'Resource not found');
34+
}
35+
} catch (err) {
36+
next(new HttpError(err.code ?? StatusCodes.INTERNAL_SERVER_ERROR, err));
37+
}
38+
};
39+
40+
const list = async (
41+
_: Request,
42+
res: Response,
43+
next: NextFunction,
44+
): Promise<void> => {
45+
try {
46+
// list objects
47+
const objects = await repository.list();
48+
49+
res.send(objects);
50+
} catch (err) {
51+
next(new HttpError(err.code ?? StatusCodes.INTERNAL_SERVER_ERROR, err));
52+
}
53+
};
54+
55+
const create = async (
56+
req: Request,
57+
res: Response,
58+
next: NextFunction,
59+
): Promise<void> => {
60+
try {
61+
// create object
62+
const object = await repository.create(req.body);
63+
64+
res.send(object);
65+
} catch (err) {
66+
next(new HttpError(err.code ?? StatusCodes.INTERNAL_SERVER_ERROR, err));
67+
}
68+
};
69+
70+
const get = (req: Request, res: Response, next: NextFunction): void => {
71+
try {
72+
// get object
73+
res.send((req as MyRequest)[ENTITY]);
74+
} catch (err) {
75+
next(new HttpError(err.code ?? StatusCodes.INTERNAL_SERVER_ERROR, err));
76+
}
77+
};
78+
79+
const update = async (
80+
req: Request,
81+
res: Response,
82+
next: NextFunction,
83+
): Promise<void> => {
84+
try {
85+
// update object
86+
const object = await repository.update(
87+
(req as MyRequest)[ENTITY].id,
88+
req.body,
89+
);
90+
91+
res.send(object);
92+
} catch (err) {
93+
next(new HttpError(err.code ?? StatusCodes.INTERNAL_SERVER_ERROR, err));
94+
}
95+
};
96+
97+
const del = async (
98+
req: Request,
99+
res: Response,
100+
next: NextFunction,
101+
): Promise<void> => {
102+
try {
103+
// delete object
104+
const object = await repository.del((req as MyRequest)[ENTITY].id);
105+
106+
res.send(object);
107+
} catch (err) {
108+
next(new HttpError(err.code ?? StatusCodes.INTERNAL_SERVER_ERROR, err));
109+
}
110+
};
111+
112+
export default { getById, list, create, get, update, del };
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Router } from 'express';
2+
3+
import { RouteOptions } from '../types';
4+
import { RESOURCE } from './constants';
5+
import controller from './controller';
6+
7+
const path = `/${RESOURCE}`;
8+
9+
const routes = (_: RouteOptions): Router => {
10+
const router = Router();
11+
12+
router.param('id', controller.getById);
13+
14+
router.route('/').get(controller.list).post(controller.create);
15+
16+
router
17+
.route('/:id')
18+
.get(controller.get)
19+
.patch(controller.update)
20+
.delete(controller.del);
21+
22+
return router;
23+
};
24+
25+
export default { path, routes };
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { MyError } from '@boringcodes/utils/error';
2+
3+
import postgres from '../../db/postgres';
4+
import { <%= compNamePascalCase %> } from './types';
5+
6+
const list = async (): Promise<<%= compNamePascalCase %>[]> => {
7+
// list documents
8+
return await postgres.<%= compNameCamelCase %>.findMany();
9+
};
10+
11+
const create = async (data: Omit<<%= compNamePascalCase %>, 'id'>): Promise<<%= compNamePascalCase %>> => {
12+
// create document
13+
return await postgres.<%= compNameCamelCase %>.create({ data });
14+
};
15+
16+
const get = async (id: number): Promise<<%= compNamePascalCase %>> => {
17+
// get document
18+
const document = await postgres.<%= compNameCamelCase %>.findUnique({ where: { id } });
19+
if (document === null) {
20+
throw new MyError('Document not found');
21+
}
22+
23+
return document;
24+
};
25+
26+
const update = async (id: number, data: Omit<<%= compNamePascalCase %>, 'id'>): Promise<<%= compNamePascalCase %>> => {
27+
// get document
28+
const document = await postgres.<%= compNameCamelCase %>.findUnique({ where: { id } });
29+
if (document === null) {
30+
throw new MyError('Document not found');
31+
}
32+
33+
// update document
34+
return await postgres.<%= compNameCamelCase %>.update({
35+
data,
36+
where: { id },
37+
});
38+
};
39+
40+
const del = async (id: number): Promise<<%= compNamePascalCase %>> => {
41+
// get document
42+
const document = await postgres.<%= compNameCamelCase %>.findUnique({ where: { id } });
43+
if (document === null) {
44+
throw new MyError('Document not found');
45+
}
46+
47+
// delete document
48+
await postgres.<%= compNameCamelCase %>.delete({ where: { id } });
49+
50+
return document;
51+
};
52+
53+
export default { list, create, get, update, del };
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
interface <%= compNamePascalCase %> {
2+
readonly id: number;
3+
readonly name: string | null;
4+
// TODO: add more props
5+
}
6+
7+
export { <%= compNamePascalCase %> };

0 commit comments

Comments
 (0)