koa3-cli 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,27 @@
1
1
  const userService = require('../service/user');
2
+ const { Joi, validateValue } = require('../lib/validator');
3
+
4
+ const idParamSchema = Joi.object({
5
+ id: Joi.string().required().messages({ 'any.required': '用户 id 不能为空' })
6
+ });
7
+
8
+ const createUserBodySchema = Joi.object({
9
+ name: Joi.string().trim().min(1).max(100).required().messages({
10
+ 'any.required': '用户名为必填',
11
+ 'string.empty': '用户名不能为空',
12
+ 'string.max': '用户名不能超过 100 个字符'
13
+ }),
14
+ email: Joi.string().email().allow('').optional(),
15
+ age: Joi.number().integer().min(0).max(150).optional()
16
+ }).options({ stripUnknown: true });
17
+
18
+ const updateUserBodySchema = Joi.object({
19
+ name: Joi.string().trim().min(1).max(100).optional(),
20
+ email: Joi.string().email().allow('').optional(),
21
+ age: Joi.number().integer().min(0).max(150).optional()
22
+ }).min(1).messages({
23
+ 'object.min': '至少需要提供一个要更新的字段'
24
+ }).options({ stripUnknown: true });
2
25
 
3
26
  function logMeta(ctx, extra = {}) {
4
27
  return {
@@ -22,7 +45,7 @@ class UserController {
22
45
  }
23
46
 
24
47
  async detail(ctx) {
25
- const { id } = ctx.state.validated ? ctx.state.validated.params : ctx.params;
48
+ const { id } = await validateValue(idParamSchema, ctx.params);
26
49
 
27
50
  try {
28
51
  const user = await userService.getUserById(id);
@@ -42,7 +65,7 @@ class UserController {
42
65
  }
43
66
 
44
67
  async create(ctx) {
45
- const userData = ctx.state.validated ? ctx.state.validated.body : ctx.request.body;
68
+ const userData = await validateValue(createUserBodySchema, ctx.request.body);
46
69
 
47
70
  try {
48
71
  const user = await userService.createUser(userData);
@@ -56,8 +79,8 @@ class UserController {
56
79
  }
57
80
 
58
81
  async update(ctx) {
59
- const { id } = ctx.state.validated ? ctx.state.validated.params : ctx.params;
60
- const userData = ctx.state.validated ? ctx.state.validated.body : ctx.request.body;
82
+ const { id } = await validateValue(idParamSchema, ctx.params);
83
+ const userData = await validateValue(updateUserBodySchema, ctx.request.body);
61
84
 
62
85
  try {
63
86
  const user = await userService.updateUser(id, userData);
@@ -77,7 +100,7 @@ class UserController {
77
100
  }
78
101
 
79
102
  async delete(ctx) {
80
- const { id } = ctx.state.validated ? ctx.state.validated.params : ctx.params;
103
+ const { id } = await validateValue(idParamSchema, ctx.params);
81
104
 
82
105
  try {
83
106
  const result = await userService.deleteUser(id);
@@ -43,7 +43,28 @@ function validate(schemas = {}) {
43
43
  };
44
44
  }
45
45
 
46
+ /**
47
+ * 在控制器内校验单个对象,失败时抛出与 validate() 中间件相同形态的 422 错误
48
+ */
49
+ async function validateValue(schema, value, validateOptions = { stripUnknown: true }) {
50
+ try {
51
+ return await schema.validateAsync(value ?? {}, validateOptions);
52
+ } catch (err) {
53
+ if (!Joi.isError(err)) {
54
+ throw err;
55
+ }
56
+ const validationError = new Error(err.message || 'Validation Failed');
57
+ validationError.status = 422;
58
+ validationError.details = err.details.map(d => ({
59
+ field: d.path.join('.'),
60
+ message: d.message
61
+ }));
62
+ throw validationError;
63
+ }
64
+ }
65
+
46
66
  module.exports = {
47
67
  validate,
68
+ validateValue,
48
69
  Joi
49
70
  };
package/app/router.js CHANGED
@@ -1,6 +1,4 @@
1
1
  const { Router } = require('@koa/router');
2
- const { validate } = require('./lib/validator');
3
- const userSchema = require('./schema/user');
4
2
 
5
3
  const router = new Router();
6
4
 
@@ -14,9 +12,9 @@ router.get('/', homeController.index);
14
12
 
15
13
  // 用户相关路由
16
14
  router.get('/api/user', userController.list);
17
- router.get('/api/user/:id', validate({ params: userSchema.idParam }), userController.detail);
18
- router.post('/api/user', validate({ body: userSchema.createUserBody }), userController.create);
19
- router.put('/api/user/:id', validate({ params: userSchema.idParam, body: userSchema.updateUserBody }), userController.update);
20
- router.delete('/api/user/:id', validate({ params: userSchema.idParam }), userController.delete);
15
+ router.get('/api/user/:id', userController.detail);
16
+ router.post('/api/user', userController.create);
17
+ router.put('/api/user/:id', userController.update);
18
+ router.delete('/api/user/:id', userController.delete);
21
19
 
22
20
  module.exports = router;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koa3-cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Koa3脚手架",
5
5
  "main": "app.js",
6
6
  "bin": {
@@ -1,29 +0,0 @@
1
- const { Joi } = require('../lib/validator');
2
-
3
- const idParam = Joi.object({
4
- id: Joi.string().required().messages({ 'any.required': '用户 id 不能为空' })
5
- });
6
-
7
- const createUserBody = Joi.object({
8
- name: Joi.string().trim().min(1).max(100).required().messages({
9
- 'any.required': '用户名为必填',
10
- 'string.empty': '用户名不能为空',
11
- 'string.max': '用户名不能超过 100 个字符'
12
- }),
13
- email: Joi.string().email().allow('').optional(),
14
- age: Joi.number().integer().min(0).max(150).optional()
15
- }).options({ stripUnknown: true });
16
-
17
- const updateUserBody = Joi.object({
18
- name: Joi.string().trim().min(1).max(100).optional(),
19
- email: Joi.string().email().allow('').optional(),
20
- age: Joi.number().integer().min(0).max(150).optional()
21
- }).min(1).messages({
22
- 'object.min': '至少需要提供一个要更新的字段'
23
- }).options({ stripUnknown: true });
24
-
25
- module.exports = {
26
- idParam,
27
- createUserBody,
28
- updateUserBody
29
- };