codeweaver 1.0.14 → 1.1.0
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.
- package/README.md +252 -40
- package/command.js +11 -10
- package/package.json +17 -13
- package/src/app.ts +21 -3
- package/src/config.ts +33 -0
- package/src/packages/ts-zod-decorators/index.ts +3 -0
- package/src/packages/ts-zod-decorators/validate.decorator.ts +20 -0
- package/src/packages/ts-zod-decorators/validator.class.ts +72 -0
- package/src/packages/ts-zod-decorators/zod-input.decorator.ts +12 -0
- package/src/packages/ts-zod-decorators/zod-output.decorator.ts +11 -0
- package/src/routers/index.ts +2 -2
- package/src/routers/orders/dto/order.dto.ts +40 -0
- package/src/routers/orders/index.ts +131 -10
- package/src/routers/orders/order.controller.ts +191 -0
- package/src/routers/products/dto/product.dto.ts +36 -0
- package/src/routers/products/index.ts +104 -64
- package/src/routers/products/product.controller.ts +237 -0
- package/src/routers/users/dto/user.dto.ts +14 -2
- package/src/routers/users/index.ts +54 -36
- package/src/routers/users/user.controller.ts +144 -16
- package/src/types.ts +16 -0
- package/src/utilities.ts +47 -0
- package/tsconfig.json +9 -3
- package/tsconfig.paths.json +10 -0
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import { Router, Request, Response } from "express";
|
|
2
2
|
import asyncHandler from "express-async-handler";
|
|
3
|
+
import ProductController from "./product.controller";
|
|
4
|
+
import { sendError } from "@/utilities";
|
|
3
5
|
|
|
4
6
|
const router = Router();
|
|
5
|
-
|
|
6
|
-
// Array to store products (as a mock database)
|
|
7
|
-
const products = [
|
|
8
|
-
{ id: 1, name: "Product1" },
|
|
9
|
-
{ id: 2, name: "Product2" },
|
|
10
|
-
{ id: 3, name: "Product3" },
|
|
11
|
-
{ id: 4, name: "Product4" },
|
|
12
|
-
{ id: 5, name: "Product5" },
|
|
13
|
-
{ id: 6, name: "Product6" },
|
|
14
|
-
{ id: 7, name: "Product7" },
|
|
15
|
-
{ id: 8, name: "Product8" },
|
|
16
|
-
{ id: 9, name: "Product9" },
|
|
17
|
-
];
|
|
7
|
+
const productController = new ProductController();
|
|
18
8
|
|
|
19
9
|
// CRUD Routes
|
|
20
10
|
|
|
@@ -22,28 +12,59 @@ const products = [
|
|
|
22
12
|
* @swagger
|
|
23
13
|
* /products:
|
|
24
14
|
* post:
|
|
25
|
-
* summary: Create
|
|
15
|
+
* summary: Create a product
|
|
26
16
|
* description: Create a new product.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
17
|
+
* consumes:
|
|
18
|
+
* - application/json
|
|
19
|
+
* produces:
|
|
20
|
+
* - application/json
|
|
21
|
+
* parameters:
|
|
22
|
+
* - in: body
|
|
23
|
+
* name: product
|
|
24
|
+
* required: true
|
|
25
|
+
* schema:
|
|
26
|
+
* type: object
|
|
27
|
+
* required:
|
|
28
|
+
* - name
|
|
29
|
+
* - price
|
|
30
|
+
* - category
|
|
31
|
+
* - stock
|
|
32
|
+
* properties:
|
|
33
|
+
* id:
|
|
34
|
+
* type: integer
|
|
35
|
+
* example: 1
|
|
36
|
+
* name:
|
|
37
|
+
* type: string
|
|
38
|
+
* example: "New Product"
|
|
39
|
+
* price:
|
|
40
|
+
* type: number
|
|
41
|
+
* example: 1499
|
|
42
|
+
* description:
|
|
43
|
+
* type: string
|
|
44
|
+
* example: "This is a detailed description."
|
|
45
|
+
* category:
|
|
46
|
+
* type: string
|
|
47
|
+
* enum:
|
|
48
|
+
* - Electronics
|
|
49
|
+
* - Appliances
|
|
50
|
+
* - Sports
|
|
51
|
+
* - Kitchen
|
|
52
|
+
* - Mobile Accessories
|
|
53
|
+
* - Computer Accessories
|
|
54
|
+
* - Home Appliances
|
|
55
|
+
* - Books
|
|
56
|
+
* example: "Electronics"
|
|
57
|
+
* stock:
|
|
58
|
+
* type: integer
|
|
59
|
+
* example: 50
|
|
38
60
|
* responses:
|
|
39
61
|
* 201:
|
|
40
|
-
* description:
|
|
62
|
+
* description: Product created
|
|
41
63
|
*/
|
|
42
64
|
router.post(
|
|
43
65
|
"/",
|
|
44
66
|
asyncHandler(async (req: Request, res: Response) => {
|
|
45
|
-
const product =
|
|
46
|
-
products.push(product);
|
|
67
|
+
const product = await productController.create(req.body);
|
|
47
68
|
res.status(201).json(product);
|
|
48
69
|
})
|
|
49
70
|
);
|
|
@@ -60,7 +81,7 @@ router.post(
|
|
|
60
81
|
router.get(
|
|
61
82
|
"/",
|
|
62
83
|
asyncHandler(async (req: Request, res: Response) => {
|
|
63
|
-
res.json(
|
|
84
|
+
res.json(await productController.getAll());
|
|
64
85
|
})
|
|
65
86
|
);
|
|
66
87
|
|
|
@@ -68,7 +89,7 @@ router.get(
|
|
|
68
89
|
* @swagger
|
|
69
90
|
* /products/{id}:
|
|
70
91
|
* get:
|
|
71
|
-
* summary: Get
|
|
92
|
+
* summary: Get a product by ID
|
|
72
93
|
* parameters:
|
|
73
94
|
* - name: id
|
|
74
95
|
* in: path
|
|
@@ -78,15 +99,14 @@ router.get(
|
|
|
78
99
|
* type: integer
|
|
79
100
|
* responses:
|
|
80
101
|
* 200:
|
|
81
|
-
* description:
|
|
82
|
-
* 404:
|
|
83
|
-
* description: product not found
|
|
102
|
+
* description: A product object
|
|
84
103
|
*/
|
|
85
104
|
router.get(
|
|
86
105
|
"/:id",
|
|
87
106
|
asyncHandler(async (req: Request, res: Response) => {
|
|
88
|
-
const product =
|
|
89
|
-
|
|
107
|
+
const product = await productController.get(req.params.id);
|
|
108
|
+
|
|
109
|
+
if ("id" in product == false) sendError(res, product);
|
|
90
110
|
else res.json(product);
|
|
91
111
|
})
|
|
92
112
|
);
|
|
@@ -95,7 +115,12 @@ router.get(
|
|
|
95
115
|
* @swagger
|
|
96
116
|
* /products/{id}:
|
|
97
117
|
* put:
|
|
98
|
-
* summary: Update
|
|
118
|
+
* summary: Update a product
|
|
119
|
+
* description: Update an existing product.
|
|
120
|
+
* consumes:
|
|
121
|
+
* - application/json
|
|
122
|
+
* produces:
|
|
123
|
+
* - application/json
|
|
99
124
|
* parameters:
|
|
100
125
|
* - name: id
|
|
101
126
|
* in: path
|
|
@@ -103,32 +128,49 @@ router.get(
|
|
|
103
128
|
* description: The ID of the product to update
|
|
104
129
|
* schema:
|
|
105
130
|
* type: integer
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
131
|
+
* - in: body
|
|
132
|
+
* name: product
|
|
133
|
+
* required: true
|
|
134
|
+
* schema:
|
|
135
|
+
* type: object
|
|
136
|
+
* properties:
|
|
137
|
+
* name:
|
|
138
|
+
* type: string
|
|
139
|
+
* example: "Updated Product"
|
|
140
|
+
* price:
|
|
141
|
+
* type: number
|
|
142
|
+
* example: 2000
|
|
143
|
+
* description:
|
|
144
|
+
* type: string
|
|
145
|
+
* example: "This is a detailed description."
|
|
146
|
+
* category:
|
|
147
|
+
* type: string
|
|
148
|
+
* enum:
|
|
149
|
+
* - Electronics
|
|
150
|
+
* - Appliances
|
|
151
|
+
* - Sports
|
|
152
|
+
* - Kitchen
|
|
153
|
+
* - Mobile Accessories
|
|
154
|
+
* - Computer Accessories
|
|
155
|
+
* - Home Appliances
|
|
156
|
+
* - Books
|
|
157
|
+
* example: "Sports"
|
|
158
|
+
* stock:
|
|
159
|
+
* type: integer
|
|
160
|
+
* example: 70
|
|
117
161
|
* responses:
|
|
118
162
|
* 200:
|
|
119
|
-
* description:
|
|
163
|
+
* description: Product updated
|
|
120
164
|
* 404:
|
|
121
|
-
* description:
|
|
165
|
+
* description: Product not found
|
|
122
166
|
*/
|
|
123
167
|
router.put(
|
|
124
168
|
"/:id",
|
|
125
169
|
asyncHandler(async (req: Request, res: Response) => {
|
|
126
|
-
const product =
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
res.json(product);
|
|
131
|
-
}
|
|
170
|
+
const product = await productController.update(req.params.id, req.body);
|
|
171
|
+
|
|
172
|
+
if ("id" in product == false) sendError(res, product);
|
|
173
|
+
else res.json(product);
|
|
132
174
|
})
|
|
133
175
|
);
|
|
134
176
|
|
|
@@ -136,7 +178,7 @@ router.put(
|
|
|
136
178
|
* @swagger
|
|
137
179
|
* /products/{id}:
|
|
138
180
|
* delete:
|
|
139
|
-
* summary: Delete
|
|
181
|
+
* summary: Delete a product
|
|
140
182
|
* parameters:
|
|
141
183
|
* - name: id
|
|
142
184
|
* in: path
|
|
@@ -147,20 +189,18 @@ router.put(
|
|
|
147
189
|
* responses:
|
|
148
190
|
* 204:
|
|
149
191
|
* description: product deleted
|
|
192
|
+
* 400:
|
|
193
|
+
* description: invalid request
|
|
150
194
|
* 404:
|
|
151
195
|
* description: product not found
|
|
152
196
|
*/
|
|
153
197
|
router.delete(
|
|
154
198
|
"/:id",
|
|
155
199
|
asyncHandler(async (req: Request, res: Response) => {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
else {
|
|
161
|
-
products.splice(productIndex, 1);
|
|
162
|
-
res.status(204).send();
|
|
163
|
-
}
|
|
200
|
+
const product = await productController.delete(req.params.id);
|
|
201
|
+
|
|
202
|
+
if ("id" in product == false) sendError(res, product);
|
|
203
|
+
else res.json(product);
|
|
164
204
|
})
|
|
165
205
|
);
|
|
166
206
|
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { onError, rateLimit, timeout } from "utils-decorators";
|
|
2
|
+
import {
|
|
3
|
+
Product,
|
|
4
|
+
ProductCreationDto,
|
|
5
|
+
ProductUpdateDto,
|
|
6
|
+
ZodProductCreationDto,
|
|
7
|
+
ZodProductUpdateDto,
|
|
8
|
+
} from "./dto/product.dto";
|
|
9
|
+
import { Validate, ZodInput } from "@pkg/ts-zod-decorators";
|
|
10
|
+
import { ResponseError } from "@/types";
|
|
11
|
+
import { tryParseId } from "@/utilities";
|
|
12
|
+
|
|
13
|
+
// Array to store products (as a mock database)
|
|
14
|
+
const products: Product[] = [
|
|
15
|
+
{
|
|
16
|
+
id: 1,
|
|
17
|
+
name: "ASUS ROG Zephyrus G15",
|
|
18
|
+
price: 45000000,
|
|
19
|
+
description: "Gaming laptop with AMD Ryzen 9 5900HS and RTX 3080 GPU",
|
|
20
|
+
category: "Electronics",
|
|
21
|
+
stock: 15,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 2,
|
|
25
|
+
name: "Sony WH-1000XM5 Wireless Headphones",
|
|
26
|
+
price: 12000000,
|
|
27
|
+
description:
|
|
28
|
+
"Premium noise-canceling over-ear headphones with 30hr battery",
|
|
29
|
+
category: "Electronics",
|
|
30
|
+
stock: 8,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: 3,
|
|
34
|
+
name: "LG Smart Inverter Microwave",
|
|
35
|
+
price: 25000000,
|
|
36
|
+
description: "1.7 cu.ft countertop microwave with smart sensor cooking",
|
|
37
|
+
category: "Appliances",
|
|
38
|
+
stock: 5,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 4,
|
|
42
|
+
name: "Trek Marlin 5 Mountain Bike",
|
|
43
|
+
price: 18000000,
|
|
44
|
+
description: "Entry-level mountain bike with aluminum frame and 21 speeds",
|
|
45
|
+
category: "Sports",
|
|
46
|
+
stock: 3,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 5,
|
|
50
|
+
name: "DeLonghi Espresso Machine",
|
|
51
|
+
price: 6500000,
|
|
52
|
+
description: "Compact espresso maker with manual milk frother",
|
|
53
|
+
category: "Kitchen",
|
|
54
|
+
stock: 12,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 6,
|
|
58
|
+
name: "Anker Wireless Charger",
|
|
59
|
+
price: 1200000,
|
|
60
|
+
description: "15W fast wireless charger with anti-slip surface",
|
|
61
|
+
category: "Mobile Accessories",
|
|
62
|
+
stock: 30,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: 7,
|
|
66
|
+
name: "Logitech MX Master 3 Mouse",
|
|
67
|
+
price: 4500000,
|
|
68
|
+
description: "Ergonomic wireless mouse with Darkfield tracking",
|
|
69
|
+
category: "Computer Accessories",
|
|
70
|
+
stock: 18,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 8,
|
|
74
|
+
name: "Kindle Paperwhite",
|
|
75
|
+
price: 3800000,
|
|
76
|
+
description: 'Waterproof e-reader with 6.8" 300ppi display',
|
|
77
|
+
category: "Electronics",
|
|
78
|
+
stock: 9,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 9,
|
|
82
|
+
name: "Dyson V11 Vacuum Cleaner",
|
|
83
|
+
price: 32000000,
|
|
84
|
+
description: "Cordless stick vacuum with LCD screen and 60min runtime",
|
|
85
|
+
category: "Home Appliances",
|
|
86
|
+
stock: 7,
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
function exceedHandler() {
|
|
91
|
+
const message = "Too much call in allowed window";
|
|
92
|
+
|
|
93
|
+
throw new Error(message, {
|
|
94
|
+
cause: { status: 500, message } satisfies ResponseError,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function getProductErrorHandler(e: Error) {
|
|
99
|
+
const message = "User not found.";
|
|
100
|
+
|
|
101
|
+
throw new Error(message, {
|
|
102
|
+
cause: { status: 404, message, details: e.message } satisfies ResponseError,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Controller for handling product-related operations
|
|
108
|
+
* @class ProductController
|
|
109
|
+
* @desc Provides methods for product management including CRUD operations
|
|
110
|
+
*/
|
|
111
|
+
export default class ProductController {
|
|
112
|
+
@rateLimit({
|
|
113
|
+
timeSpanMs: 60000,
|
|
114
|
+
allowedCalls: 300,
|
|
115
|
+
exceedHandler,
|
|
116
|
+
})
|
|
117
|
+
@Validate
|
|
118
|
+
/**
|
|
119
|
+
* Creates a new product with validated data
|
|
120
|
+
* @param product - Product creation data validated by Zod schema
|
|
121
|
+
* @returns Newly created product with generated ID
|
|
122
|
+
*/
|
|
123
|
+
public async create(
|
|
124
|
+
@ZodInput(ZodProductCreationDto) product: ProductCreationDto
|
|
125
|
+
) {
|
|
126
|
+
products.push({
|
|
127
|
+
...product,
|
|
128
|
+
id: products.length + 1,
|
|
129
|
+
} satisfies Product);
|
|
130
|
+
|
|
131
|
+
return product;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@timeout(20000)
|
|
135
|
+
@rateLimit({
|
|
136
|
+
timeSpanMs: 60000,
|
|
137
|
+
allowedCalls: 300,
|
|
138
|
+
exceedHandler,
|
|
139
|
+
})
|
|
140
|
+
/**
|
|
141
|
+
* Retrieves all products with truncated descriptions
|
|
142
|
+
* @returns List of products with summarized descriptions
|
|
143
|
+
*/
|
|
144
|
+
public async getAll(): Promise<Product[]> {
|
|
145
|
+
return products.map(
|
|
146
|
+
(product) =>
|
|
147
|
+
({
|
|
148
|
+
...product,
|
|
149
|
+
description: product.description?.substring(0, 50) + "..." || "",
|
|
150
|
+
} satisfies Product)
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@onError({
|
|
155
|
+
func: getProductErrorHandler,
|
|
156
|
+
})
|
|
157
|
+
@rateLimit({
|
|
158
|
+
timeSpanMs: 60000,
|
|
159
|
+
allowedCalls: 300,
|
|
160
|
+
exceedHandler,
|
|
161
|
+
})
|
|
162
|
+
/**
|
|
163
|
+
* Finds a product by its ID
|
|
164
|
+
* @param id - Product ID as string
|
|
165
|
+
* @returns Product details or error object if not found
|
|
166
|
+
*/
|
|
167
|
+
public async get(id: string): Promise<Product | ResponseError> {
|
|
168
|
+
const productId = tryParseId(id);
|
|
169
|
+
if (typeof productId != "number") return productId satisfies ResponseError;
|
|
170
|
+
const product = products.find((product) => product.id === productId);
|
|
171
|
+
|
|
172
|
+
if (!product)
|
|
173
|
+
return {
|
|
174
|
+
status: 404,
|
|
175
|
+
message: "Product dose not exist.",
|
|
176
|
+
} satisfies ResponseError;
|
|
177
|
+
|
|
178
|
+
return product satisfies Product;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@rateLimit({
|
|
182
|
+
timeSpanMs: 60000,
|
|
183
|
+
allowedCalls: 300,
|
|
184
|
+
exceedHandler,
|
|
185
|
+
})
|
|
186
|
+
@Validate
|
|
187
|
+
/**
|
|
188
|
+
* Updates an existing product
|
|
189
|
+
* @param {string} id - Product ID to update
|
|
190
|
+
* @param {ProductUpdateDto} updateData - Partial product data to update
|
|
191
|
+
* @returns {Promise<Product | ResponseError>} Updated product or error object
|
|
192
|
+
* @throws {ResponseError} 404 - Product not found
|
|
193
|
+
* @throws {ResponseError} 400 - Invalid ID format or update data
|
|
194
|
+
*/
|
|
195
|
+
public async update(
|
|
196
|
+
id: string,
|
|
197
|
+
@ZodInput(ZodProductUpdateDto) updateData: ProductUpdateDto
|
|
198
|
+
): Promise<Product | ResponseError> {
|
|
199
|
+
const product = await this.get(id);
|
|
200
|
+
if ("id" in product == false) return product satisfies ResponseError;
|
|
201
|
+
|
|
202
|
+
if (product) Object.assign(product, updateData);
|
|
203
|
+
else
|
|
204
|
+
return {
|
|
205
|
+
status: 404,
|
|
206
|
+
message: "Product not found",
|
|
207
|
+
} satisfies ResponseError;
|
|
208
|
+
|
|
209
|
+
return product;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@rateLimit({
|
|
213
|
+
timeSpanMs: 60000,
|
|
214
|
+
allowedCalls: 300,
|
|
215
|
+
exceedHandler,
|
|
216
|
+
})
|
|
217
|
+
/**
|
|
218
|
+
* Deletes a product by ID
|
|
219
|
+
* @param {string} id - Product ID to delete
|
|
220
|
+
* @returns {Promise<Product | ResponseError>} Deleted product or error object
|
|
221
|
+
* @throws {ResponseError} 404 - Product not found
|
|
222
|
+
* @throws {ResponseError} 400 - Invalid ID format
|
|
223
|
+
*/
|
|
224
|
+
public async delete(id: string): Promise<Product | ResponseError> {
|
|
225
|
+
const productId = tryParseId(id);
|
|
226
|
+
if (typeof productId != "number") return productId satisfies ResponseError;
|
|
227
|
+
const index = products.findIndex((product) => product.id === productId);
|
|
228
|
+
|
|
229
|
+
if (index == -1)
|
|
230
|
+
return {
|
|
231
|
+
status: 404,
|
|
232
|
+
message: "Product dose not exist.",
|
|
233
|
+
} satisfies ResponseError;
|
|
234
|
+
|
|
235
|
+
return products.splice(index, 1)[0] satisfies Product;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for User entity
|
|
5
|
+
* @typedef {Object} ZodUser
|
|
6
|
+
* @property {number} id - Unique identifier (min 1)
|
|
7
|
+
* @property {string} username - Username (min 3 chars)
|
|
8
|
+
* @property {string} email - Valid email format
|
|
9
|
+
* @property {string} password - Password (min 6 chars)
|
|
10
|
+
*/
|
|
11
|
+
export const ZodUser = z.object({
|
|
12
|
+
id: z.number().min(1).int(),
|
|
4
13
|
username: z.string().min(3),
|
|
5
14
|
email: z.string().email(),
|
|
6
15
|
password: z.string().min(6),
|
|
7
16
|
});
|
|
8
17
|
|
|
9
|
-
export
|
|
18
|
+
export const ZodUserCreationDto = ZodUser.omit({ id: true });
|
|
19
|
+
|
|
20
|
+
export type User = z.infer<typeof ZodUser>;
|
|
21
|
+
export type UserCreationDto = z.infer<typeof ZodUserCreationDto>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Router, Request, Response } from "express";
|
|
2
2
|
import asyncHandler from "express-async-handler";
|
|
3
3
|
import UserController from "./user.controller";
|
|
4
|
+
import { sendError } from "@/utilities";
|
|
4
5
|
|
|
5
6
|
const router = Router();
|
|
6
7
|
const userController = new UserController();
|
|
@@ -11,70 +12,87 @@ const userController = new UserController();
|
|
|
11
12
|
* post:
|
|
12
13
|
* summary: Create a user
|
|
13
14
|
* description: Create a new user.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
15
|
+
* consumes:
|
|
16
|
+
* - application/json
|
|
17
|
+
* produces:
|
|
18
|
+
* - application/json
|
|
19
|
+
* parameters:
|
|
20
|
+
* - in: body
|
|
21
|
+
* name: user
|
|
22
|
+
* required: true
|
|
23
|
+
* schema:
|
|
24
|
+
* type: object
|
|
25
|
+
* required:
|
|
26
|
+
* - username
|
|
27
|
+
* - email
|
|
28
|
+
* - password
|
|
29
|
+
* properties:
|
|
30
|
+
* username:
|
|
31
|
+
* type: string
|
|
32
|
+
* minLength: 3
|
|
33
|
+
* example: JessicaSmith
|
|
34
|
+
* email:
|
|
35
|
+
* type: string
|
|
36
|
+
* format: email
|
|
37
|
+
* example: user@example.com
|
|
38
|
+
* password:
|
|
39
|
+
* type: string
|
|
40
|
+
* minLength: 6
|
|
41
|
+
* example: securePassword123
|
|
35
42
|
* responses:
|
|
36
43
|
* 201:
|
|
37
|
-
* description:
|
|
44
|
+
* description: User created
|
|
38
45
|
*/
|
|
39
46
|
router.post(
|
|
40
47
|
"/",
|
|
41
48
|
asyncHandler(async (req: Request, res: Response) => {
|
|
42
|
-
const
|
|
43
|
-
res.status(201).json(
|
|
49
|
+
const user = await userController.create(req.body);
|
|
50
|
+
res.status(201).json(user);
|
|
44
51
|
})
|
|
45
52
|
);
|
|
46
53
|
|
|
47
54
|
/**
|
|
48
55
|
* @swagger
|
|
49
|
-
* /
|
|
56
|
+
* /users/{id}:
|
|
50
57
|
* get:
|
|
51
|
-
* summary: Get user
|
|
52
|
-
*
|
|
58
|
+
* summary: Get a user by ID
|
|
59
|
+
* parameters:
|
|
60
|
+
* - name: id
|
|
61
|
+
* in: path
|
|
62
|
+
* required: true
|
|
63
|
+
* description: The ID of the product
|
|
64
|
+
* schema:
|
|
65
|
+
* type: integer
|
|
53
66
|
* responses:
|
|
54
67
|
* 200:
|
|
55
|
-
* description:
|
|
68
|
+
* description: A user object
|
|
69
|
+
* 404:
|
|
70
|
+
* description: user not found
|
|
56
71
|
*/
|
|
57
72
|
router.get(
|
|
58
|
-
"
|
|
73
|
+
"/:id",
|
|
59
74
|
asyncHandler(async (req: Request, res: Response) => {
|
|
60
|
-
|
|
75
|
+
const user = await userController.get(req.params.id);
|
|
76
|
+
|
|
77
|
+
if ("id" in user == false) sendError(res, user);
|
|
78
|
+
else res.json(user);
|
|
61
79
|
})
|
|
62
80
|
);
|
|
63
81
|
|
|
64
82
|
/**
|
|
65
83
|
* @swagger
|
|
66
|
-
* /
|
|
84
|
+
* /users:
|
|
67
85
|
* get:
|
|
68
|
-
* summary: Get
|
|
69
|
-
* description: Returns user
|
|
86
|
+
* summary: Get users
|
|
87
|
+
* description: Returns a list of user objects.
|
|
70
88
|
* responses:
|
|
71
89
|
* 200:
|
|
72
|
-
* description:
|
|
90
|
+
* description: A list of user objects
|
|
73
91
|
*/
|
|
74
92
|
router.get(
|
|
75
|
-
"/
|
|
93
|
+
"/",
|
|
76
94
|
asyncHandler(async (req: Request, res: Response) => {
|
|
77
|
-
res.
|
|
95
|
+
res.json(await userController.getAll());
|
|
78
96
|
})
|
|
79
97
|
);
|
|
80
98
|
|