Skip to content

Commit 5920198

Browse files
committed
Added vscode snippets and implemented customer module's code
1 parent 24012ba commit 5920198

File tree

11 files changed

+552
-88
lines changed

11 files changed

+552
-88
lines changed

.vscode/snippets.code-snippets

Lines changed: 243 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"Domain index file": {
3-
"prefix": "nbp-di",
3+
"prefix": "nbp-d-index",
44
"body": [
55
"const { routes } = require('./api');",
66
"",
@@ -12,4 +12,246 @@
1212
],
1313
"description": "Nodejs boilerplate domain's index file"
1414
},
15+
"Domain API CRUD Routes": {
16+
"prefix": "nbp-d-api",
17+
"body": [
18+
"const express = require('express');",
19+
"const logger = require('../../libraries/log/logger');",
20+
"const { AppError } = require('../../libraries/error-handling/AppError');",
21+
"",
22+
"const {",
23+
" create,",
24+
" search,",
25+
" getById,",
26+
" updateById,",
27+
" deleteById,",
28+
"} = require('./service');",
29+
"",
30+
"const { createSchema, updateSchema, idSchema } = require('./request');",
31+
"const { validateRequest } = require('../../middlewares/request-validate');",
32+
"const { logRequest } = require('../../middlewares/log');",
33+
"",
34+
"const model = '${1:Product}';",
35+
"",
36+
"// CRUD for entity",
37+
"const routes = () => {",
38+
" const router = express.Router();",
39+
" logger.info(`Setting up routes for ${model}`);",
40+
"",
41+
" router.get('/', logRequest({}), async (req, res, next) => {",
42+
" try {",
43+
" // TODO: Add pagination and filtering",
44+
" const items = await search(req.query);",
45+
" res.json(items);",
46+
" } catch (error) {",
47+
" next(error);",
48+
" }",
49+
" });",
50+
"",
51+
" router.post(",
52+
" '/',",
53+
" logRequest({}),",
54+
" validateRequest({ schema: createSchema }),",
55+
" async (req, res, next) => {",
56+
" try {",
57+
" const item = await create(req.body);",
58+
" res.status(201).json(item);",
59+
" } catch (error) {",
60+
" next(error);",
61+
" }",
62+
" }",
63+
" );",
64+
"",
65+
" router.get(",
66+
" '/:id',",
67+
" logRequest({}),",
68+
" validateRequest({ schema: idSchema, isParam: true }),",
69+
" async (req, res, next) => {",
70+
" try {",
71+
" const item = await getById(req.params.id);",
72+
" if (!item) {",
73+
" throw new AppError(`${model} not found`, `${model} not found`, 404);",
74+
" }",
75+
" res.status(200).json(item);",
76+
" } catch (error) {",
77+
" next(error);",
78+
" }",
79+
" }",
80+
" );",
81+
"",
82+
" router.put(",
83+
" '/:id',",
84+
" logRequest({}),",
85+
" validateRequest({ schema: idSchema, isParam: true }),",
86+
" validateRequest({ schema: updateSchema }),",
87+
" async (req, res, next) => {",
88+
" try {",
89+
" const item = await updateById(req.params.id, req.body);",
90+
" if (!item) {",
91+
" throw new AppError(`${model} not found`, `${model} not found`, 404);",
92+
" }",
93+
" res.status(200).json(item);",
94+
" } catch (error) {",
95+
" next(error);",
96+
" }",
97+
" }",
98+
" );",
99+
"",
100+
" router.delete(",
101+
" '/:id',",
102+
" logRequest({}),",
103+
" validateRequest({ schema: idSchema, isParam: true }),",
104+
" async (req, res, next) => {",
105+
" try {",
106+
" await deleteById(req.params.id);",
107+
" res.status(204).json({ message: `${model} is deleted` });",
108+
" } catch (error) {",
109+
" next(error);",
110+
" }",
111+
" }",
112+
" );",
113+
"",
114+
" return router;",
115+
"};",
116+
"",
117+
"module.exports = { routes };"
118+
],
119+
"description": "CRUD routes for a model"
120+
},
121+
"Domain CRUD Service": {
122+
"prefix": "nbp-d-service",
123+
"body": [
124+
"const logger = require('../../libraries/log/logger');",
125+
"",
126+
"const Model = require('./schema');",
127+
"const { AppError } = require('../../libraries/error-handling/AppError');",
128+
"",
129+
"const model = '${1:product}';",
130+
"",
131+
"const create = async (data) => {",
132+
" try {",
133+
" const item = new Model(data);",
134+
" const saved = await item.save();",
135+
" logger.info(`create(): ${model} created`, {",
136+
" id: saved._id,",
137+
" });",
138+
" return saved;",
139+
" } catch (error) {",
140+
" logger.error(`create(): Failed to create ${model}`, error);",
141+
" throw new AppError(`Failed to create ${model}`, error.message);",
142+
" }",
143+
"};",
144+
"",
145+
"const search = async (query) => {",
146+
" try {",
147+
" const { keyword } = query ?? {};",
148+
" const filter = {};",
149+
" if (keyword) {",
150+
" filter.$or = [",
151+
" { name: { $regex: keyword, $options: 'i' } },",
152+
" { description: { $regex: keyword, $options: 'i' } },",
153+
" ];",
154+
" }",
155+
" const items = await Model.find(filter);",
156+
" logger.info('search(): filter and count', {",
157+
" filter,",
158+
" count: items.length,",
159+
" });",
160+
" return items;",
161+
" } catch (error) {",
162+
" logger.error(`search(): Failed to search ${model}`, error);",
163+
" throw new AppError(`Failed to search ${model}`, error.message, 400);",
164+
" }",
165+
"};",
166+
"",
167+
"const getById = async (id) => {",
168+
" try {",
169+
" const item = await Model.findById(id);",
170+
" logger.info(`getById(): ${model} fetched`, { id });",
171+
" return item;",
172+
" } catch (error) {",
173+
" logger.error(`getById(): Failed to get ${model}`, error);",
174+
" throw new AppError(`Failed to get ${model}`, error.message);",
175+
" }",
176+
"};",
177+
"",
178+
"const updateById = async (id, data) => {",
179+
" try {",
180+
" const item = await Model.findByIdAndUpdate(id, data, { new: true });",
181+
" logger.info(`updateById(): ${model} updated`, { id });",
182+
" return item;",
183+
" } catch (error) {",
184+
" logger.error(`updateById(): Failed to update ${model}`, error);",
185+
" throw new AppError(`Failed to update ${model}`, error.message);",
186+
" }",
187+
"};",
188+
"",
189+
"const deleteById = async (id) => {",
190+
" try {",
191+
" await Model.findByIdAndDelete(id);",
192+
" logger.info(`deleteById(): ${model} deleted`, { id });",
193+
" return true;",
194+
" } catch (error) {",
195+
" logger.error(`deleteById(): Failed to delete ${model}`, error);",
196+
" throw new AppError(`Failed to delete ${model}`, error.message);",
197+
" }",
198+
"};",
199+
"",
200+
"module.exports = {",
201+
" create,",
202+
" search,",
203+
" getById,",
204+
" updateById,",
205+
" deleteById,",
206+
"};"
207+
],
208+
"description": "CRUD service for a model"
209+
},
210+
"Mongoose Schema": {
211+
"prefix": "nbp-mongoose-schema",
212+
"body": [
213+
"const mongoose = require('mongoose');",
214+
"const { baseSchema } = require('../../libraries/db/base-schema');",
215+
"",
216+
"const schema = new mongoose.Schema({",
217+
" name: { type: String, required: true },",
218+
" // other properties",
219+
"});",
220+
"schema.add(baseSchema);",
221+
"",
222+
"module.exports = mongoose.model('${1:Model}', schema);"
223+
],
224+
"description": "Mongoose schema"
225+
},
226+
"Joi Validation Schemas": {
227+
"prefix": "nbp-joi-schemas",
228+
"body": [
229+
"const Joi = require('joi');",
230+
"const mongoose = require('mongoose');",
231+
"",
232+
"const createSchema = Joi.object().keys({",
233+
" name: Joi.string().required(),",
234+
" // other properties",
235+
"});",
236+
"",
237+
"const updateSchema = Joi.object().keys({",
238+
" name: Joi.string(),",
239+
" // other properties",
240+
"});",
241+
"",
242+
"const idSchema = Joi.object().keys({",
243+
" id: Joi.string()",
244+
" .custom((value, helpers) => {",
245+
" if (!mongoose.Types.ObjectId.isValid(value)) {",
246+
" return helpers.error('any.invalid');",
247+
" }",
248+
" return value;",
249+
" }, 'ObjectId validation')",
250+
" .required(),",
251+
"});",
252+
"",
253+
"module.exports = { createSchema, updateSchema, idSchema };"
254+
],
255+
"description": "Joi validation schemas"
256+
}
15257
}

src/domains/customer/api.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
const express = require('express');
2+
const logger = require('../../libraries/log/logger');
3+
const { AppError } = require('../../libraries/error-handling/AppError');
4+
5+
const {
6+
create,
7+
search,
8+
getById,
9+
updateById,
10+
deleteById,
11+
} = require('./service');
12+
13+
const { createSchema, updateSchema, idSchema } = require('./request');
14+
const { validateRequest } = require('../../middlewares/request-validate');
15+
const { logRequest } = require('../../middlewares/log');
16+
17+
const model = 'Customer';
18+
19+
// CRUD for entity
20+
const routes = () => {
21+
const router = express.Router();
22+
logger.info(`Setting up routes for ${model}`);
23+
24+
router.get('/', logRequest({}), async (req, res, next) => {
25+
try {
26+
// TODO: Add pagination and filtering
27+
const items = await search(req.query);
28+
res.json(items);
29+
} catch (error) {
30+
next(error);
31+
}
32+
});
33+
34+
router.post(
35+
'/',
36+
logRequest({}),
37+
validateRequest({ schema: createSchema }),
38+
async (req, res, next) => {
39+
try {
40+
const item = await create(req.body);
41+
res.status(201).json(item);
42+
} catch (error) {
43+
next(error);
44+
}
45+
}
46+
);
47+
48+
router.get(
49+
'/:id',
50+
logRequest({}),
51+
validateRequest({ schema: idSchema, isParam: true }),
52+
async (req, res, next) => {
53+
try {
54+
const item = await getById(req.params.id);
55+
if (!item) {
56+
throw new AppError(`${model} not found`, `${model} not found`, 404);
57+
}
58+
res.status(200).json(item);
59+
} catch (error) {
60+
next(error);
61+
}
62+
}
63+
);
64+
65+
router.put(
66+
'/:id',
67+
logRequest({}),
68+
validateRequest({ schema: idSchema, isParam: true }),
69+
validateRequest({ schema: updateSchema }),
70+
async (req, res, next) => {
71+
try {
72+
const item = await updateById(req.params.id, req.body);
73+
if (!item) {
74+
throw new AppError(`${model} not found`, `${model} not found`, 404);
75+
}
76+
res.status(200).json(item);
77+
} catch (error) {
78+
next(error);
79+
}
80+
}
81+
);
82+
83+
router.delete(
84+
'/:id',
85+
logRequest({}),
86+
validateRequest({ schema: idSchema, isParam: true }),
87+
async (req, res, next) => {
88+
try {
89+
await deleteById(req.params.id);
90+
res.status(204).json({ message: `${model} is deleted` });
91+
} catch (error) {
92+
next(error);
93+
}
94+
}
95+
);
96+
97+
return router;
98+
};
99+
100+
module.exports = { routes };

src/domains/customer/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const { routes } = require('./api');
2+
3+
const defineRoutes = (expressRouter) => {
4+
expressRouter.use('/customer', routes());
5+
};
6+
7+
module.exports = defineRoutes;

src/domains/customer/request.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const Joi = require('joi');
2+
const mongoose = require('mongoose');
3+
4+
const createSchema = Joi.object().keys({
5+
name: Joi.string().required(),
6+
// other properties
7+
});
8+
9+
const updateSchema = Joi.object().keys({
10+
name: Joi.string(),
11+
// other properties
12+
});
13+
14+
const idSchema = Joi.object().keys({
15+
id: Joi.string()
16+
.custom((value, helpers) => {
17+
if (!mongoose.Types.ObjectId.isValid(value)) {
18+
return helpers.error('any.invalid');
19+
}
20+
return value;
21+
}, 'ObjectId validation')
22+
.required(),
23+
});
24+
25+
module.exports = { createSchema, updateSchema, idSchema };

0 commit comments

Comments
 (0)