crud-api-express 1.0.4 → 1.0.6
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/dist/index.d.ts +6 -0
- package/dist/index.js +39 -9
- package/package.json +1 -1
- package/readme.md +1 -0
- package/src/index.ts +59 -34
package/dist/index.d.ts
CHANGED
|
@@ -44,8 +44,14 @@ declare class CrudController<T extends Document> {
|
|
|
44
44
|
private model;
|
|
45
45
|
private endpoint;
|
|
46
46
|
private router;
|
|
47
|
+
private routes;
|
|
47
48
|
constructor(model: Model<T>, endpoint: string, options?: CrudOptions<T>);
|
|
48
49
|
private configureRoutes;
|
|
49
50
|
getRouter(): Router;
|
|
51
|
+
getRoutes(): {
|
|
52
|
+
method: string;
|
|
53
|
+
path: string;
|
|
54
|
+
params?: string[];
|
|
55
|
+
}[];
|
|
50
56
|
}
|
|
51
57
|
export default CrudController;
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ class CrudController {
|
|
|
5
5
|
this.model = model;
|
|
6
6
|
this.endpoint = endpoint;
|
|
7
7
|
this.router = Router();
|
|
8
|
+
this.routes = [];
|
|
8
9
|
this.configureRoutes(options);
|
|
9
10
|
}
|
|
10
11
|
configureRoutes(options) {
|
|
@@ -12,13 +13,18 @@ class CrudController {
|
|
|
12
13
|
const applyMiddleware = (routeHandler) => {
|
|
13
14
|
return [...middleware, routeHandler];
|
|
14
15
|
};
|
|
16
|
+
// Helper to register a route
|
|
17
|
+
const registerRoute = (method, path, params) => {
|
|
18
|
+
this.routes.push({ method, path, params });
|
|
19
|
+
};
|
|
15
20
|
// Create
|
|
16
21
|
if (methods.includes('POST')) {
|
|
17
|
-
|
|
22
|
+
const path = `/${this.endpoint}`;
|
|
23
|
+
this.router.post(path, applyMiddleware(async (req, res) => {
|
|
18
24
|
const method = 'POST';
|
|
19
25
|
try {
|
|
20
|
-
|
|
21
|
-
const result = await
|
|
26
|
+
console.log("debug", req.body);
|
|
27
|
+
const result = await this.model.create(req.body);
|
|
22
28
|
if (options.relatedModel && options.relatedMethods?.includes('POST')) {
|
|
23
29
|
await options.relatedModel.create({ [options.relatedField]: result._id, ...req.body });
|
|
24
30
|
}
|
|
@@ -28,9 +34,12 @@ class CrudController {
|
|
|
28
34
|
onError(res, method, error);
|
|
29
35
|
}
|
|
30
36
|
}));
|
|
37
|
+
registerRoute('POST', path);
|
|
31
38
|
}
|
|
39
|
+
// Read all
|
|
32
40
|
if (methods.includes('GET')) {
|
|
33
|
-
|
|
41
|
+
const path = `/${this.endpoint}`;
|
|
42
|
+
this.router.get(path, applyMiddleware(async (req, res) => {
|
|
34
43
|
const method = 'GET';
|
|
35
44
|
try {
|
|
36
45
|
const { filter, sort, page, limit } = req.query;
|
|
@@ -65,9 +74,12 @@ class CrudController {
|
|
|
65
74
|
onError(res, method, error);
|
|
66
75
|
}
|
|
67
76
|
}));
|
|
77
|
+
registerRoute('GET', path, ['filter', 'sort', 'page', 'limit']);
|
|
68
78
|
}
|
|
79
|
+
// Read one
|
|
69
80
|
if (methods.includes('GET')) {
|
|
70
|
-
|
|
81
|
+
const path = `/${this.endpoint}/:id`;
|
|
82
|
+
this.router.get(path, applyMiddleware(async (req, res) => {
|
|
71
83
|
const method = 'GET';
|
|
72
84
|
try {
|
|
73
85
|
let item;
|
|
@@ -97,9 +109,12 @@ class CrudController {
|
|
|
97
109
|
onError(res, method, error);
|
|
98
110
|
}
|
|
99
111
|
}));
|
|
112
|
+
registerRoute('GET', path, ['id']);
|
|
100
113
|
}
|
|
114
|
+
// Update
|
|
101
115
|
if (methods.includes('PUT')) {
|
|
102
|
-
|
|
116
|
+
const path = `/${this.endpoint}/:id`;
|
|
117
|
+
this.router.put(path, applyMiddleware(async (req, res) => {
|
|
103
118
|
const method = 'PUT';
|
|
104
119
|
try {
|
|
105
120
|
const item = await this.model.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
|
|
@@ -115,9 +130,12 @@ class CrudController {
|
|
|
115
130
|
onError(res, method, error);
|
|
116
131
|
}
|
|
117
132
|
}));
|
|
133
|
+
registerRoute('PUT', path, ['id']);
|
|
118
134
|
}
|
|
135
|
+
// Delete multiple
|
|
119
136
|
if (methods.includes('DELETE')) {
|
|
120
|
-
|
|
137
|
+
const path = `/${this.endpoint}`;
|
|
138
|
+
this.router.delete(path, applyMiddleware(async (req, res) => {
|
|
121
139
|
const method = 'DELETE';
|
|
122
140
|
try {
|
|
123
141
|
const query = req.query.filter ? JSON.parse(req.query.filter) : {};
|
|
@@ -134,9 +152,12 @@ class CrudController {
|
|
|
134
152
|
onError(res, method, error);
|
|
135
153
|
}
|
|
136
154
|
}));
|
|
155
|
+
registerRoute('DELETE', path, ['filter']);
|
|
137
156
|
}
|
|
157
|
+
// Delete one
|
|
138
158
|
if (methods.includes('DELETE')) {
|
|
139
|
-
|
|
159
|
+
const path = `/${this.endpoint}/:id`;
|
|
160
|
+
this.router.delete(path, applyMiddleware(async (req, res) => {
|
|
140
161
|
const method = 'DELETE';
|
|
141
162
|
try {
|
|
142
163
|
const item = await this.model.findByIdAndDelete(req.params.id);
|
|
@@ -152,9 +173,12 @@ class CrudController {
|
|
|
152
173
|
onError(res, method, error);
|
|
153
174
|
}
|
|
154
175
|
}));
|
|
176
|
+
registerRoute('DELETE', path, ['id']);
|
|
155
177
|
}
|
|
178
|
+
// Aggregate
|
|
156
179
|
if (methods.includes('GET') && options.aggregatePipeline) {
|
|
157
|
-
|
|
180
|
+
const path = `/${this.endpoint}/aggregate`;
|
|
181
|
+
this.router.get(path, applyMiddleware(async (req, res) => {
|
|
158
182
|
const method = 'GET (Aggregate)';
|
|
159
183
|
try {
|
|
160
184
|
const pipeline = options.aggregatePipeline ?? [];
|
|
@@ -165,12 +189,15 @@ class CrudController {
|
|
|
165
189
|
onError(res, method, error);
|
|
166
190
|
}
|
|
167
191
|
}));
|
|
192
|
+
registerRoute('GET', path);
|
|
168
193
|
}
|
|
194
|
+
// Custom routes
|
|
169
195
|
if (options.customRoutes) {
|
|
170
196
|
options.customRoutes.forEach(route => {
|
|
171
197
|
const { method, path, handler } = route;
|
|
172
198
|
if (methods.includes(method.toUpperCase())) {
|
|
173
199
|
this.router[method](`/${this.endpoint}${path}`, applyMiddleware(handler));
|
|
200
|
+
registerRoute(method.toUpperCase(), `/${this.endpoint}${path}`);
|
|
174
201
|
}
|
|
175
202
|
});
|
|
176
203
|
}
|
|
@@ -178,6 +205,9 @@ class CrudController {
|
|
|
178
205
|
getRouter() {
|
|
179
206
|
return this.router;
|
|
180
207
|
}
|
|
208
|
+
getRoutes() {
|
|
209
|
+
return this.routes;
|
|
210
|
+
}
|
|
181
211
|
}
|
|
182
212
|
|
|
183
213
|
export { CrudController as default };
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -66,6 +66,7 @@ mongoose.connect(mongoURI, { useNewUrlParser: false, useUnifiedTopology: false }
|
|
|
66
66
|
app.use(express.json());
|
|
67
67
|
|
|
68
68
|
app.use('/api', exampleController.getRouter());
|
|
69
|
+
console.log(exampleController.getRoutes());
|
|
69
70
|
|
|
70
71
|
const PORT = process.env.PORT || 3000;
|
|
71
72
|
app.listen(PORT, () => {
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Request, Response, Router, NextFunction } from 'express';
|
|
2
2
|
import { Document, Model, Aggregate } from 'mongoose';
|
|
3
3
|
|
|
4
4
|
interface CrudOptions<T extends Document> {
|
|
@@ -17,11 +17,13 @@ class CrudController<T extends Document> {
|
|
|
17
17
|
private model: Model<T>;
|
|
18
18
|
private endpoint: string;
|
|
19
19
|
private router: Router;
|
|
20
|
+
private routes: { method: string, path: string, params?: string[] }[];
|
|
20
21
|
|
|
21
22
|
constructor(model: Model<T>, endpoint: string, options: CrudOptions<T> = {}) {
|
|
22
23
|
this.model = model;
|
|
23
24
|
this.endpoint = endpoint;
|
|
24
25
|
this.router = Router();
|
|
26
|
+
this.routes = [];
|
|
25
27
|
this.configureRoutes(options);
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -33,18 +35,23 @@ class CrudController<T extends Document> {
|
|
|
33
35
|
methods = ['POST', 'GET', 'PUT', 'DELETE']
|
|
34
36
|
} = options;
|
|
35
37
|
|
|
36
|
-
|
|
37
38
|
const applyMiddleware = (routeHandler: (req: Request, res: Response) => void) => {
|
|
38
39
|
return [...middleware, routeHandler];
|
|
39
40
|
};
|
|
40
41
|
|
|
42
|
+
// Helper to register a route
|
|
43
|
+
const registerRoute = (method: string, path: string, params?: string[]) => {
|
|
44
|
+
this.routes.push({ method, path, params });
|
|
45
|
+
};
|
|
46
|
+
|
|
41
47
|
// Create
|
|
42
48
|
if (methods.includes('POST')) {
|
|
43
|
-
|
|
49
|
+
const path = `/${this.endpoint}`;
|
|
50
|
+
this.router.post(path, applyMiddleware(async (req, res) => {
|
|
44
51
|
const method = 'POST';
|
|
45
52
|
try {
|
|
46
|
-
|
|
47
|
-
const result:any = await
|
|
53
|
+
console.log("debug",req.body)
|
|
54
|
+
const result:any = await this.model.create(req.body);
|
|
48
55
|
if (options.relatedModel && options.relatedMethods?.includes('POST')) {
|
|
49
56
|
await options.relatedModel.create({ [options.relatedField!]: result._id, ...req.body });
|
|
50
57
|
}
|
|
@@ -53,11 +60,13 @@ class CrudController<T extends Document> {
|
|
|
53
60
|
onError(res, method, error);
|
|
54
61
|
}
|
|
55
62
|
}));
|
|
63
|
+
registerRoute('POST', path);
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
// Read all
|
|
59
67
|
if (methods.includes('GET')) {
|
|
60
|
-
|
|
68
|
+
const path = `/${this.endpoint}`;
|
|
69
|
+
this.router.get(path, applyMiddleware(async (req, res) => {
|
|
61
70
|
const method = 'GET';
|
|
62
71
|
try {
|
|
63
72
|
const { filter, sort, page, limit } = req.query;
|
|
@@ -91,10 +100,13 @@ class CrudController<T extends Document> {
|
|
|
91
100
|
onError(res, method, error);
|
|
92
101
|
}
|
|
93
102
|
}));
|
|
103
|
+
registerRoute('GET', path, ['filter', 'sort', 'page', 'limit']);
|
|
94
104
|
}
|
|
95
105
|
|
|
106
|
+
// Read one
|
|
96
107
|
if (methods.includes('GET')) {
|
|
97
|
-
|
|
108
|
+
const path = `/${this.endpoint}/:id`;
|
|
109
|
+
this.router.get(path, applyMiddleware(async (req, res) => {
|
|
98
110
|
const method = 'GET';
|
|
99
111
|
try {
|
|
100
112
|
let item: T | null;
|
|
@@ -122,11 +134,13 @@ class CrudController<T extends Document> {
|
|
|
122
134
|
onError(res, method, error);
|
|
123
135
|
}
|
|
124
136
|
}));
|
|
137
|
+
registerRoute('GET', path, ['id']);
|
|
125
138
|
}
|
|
126
139
|
|
|
127
|
-
|
|
140
|
+
// Update
|
|
128
141
|
if (methods.includes('PUT')) {
|
|
129
|
-
|
|
142
|
+
const path = `/${this.endpoint}/:id`;
|
|
143
|
+
this.router.put(path, applyMiddleware(async (req, res) => {
|
|
130
144
|
const method = 'PUT';
|
|
131
145
|
try {
|
|
132
146
|
const item = await this.model.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
|
|
@@ -141,32 +155,35 @@ class CrudController<T extends Document> {
|
|
|
141
155
|
onError(res, method, error);
|
|
142
156
|
}
|
|
143
157
|
}));
|
|
158
|
+
registerRoute('PUT', path, ['id']);
|
|
144
159
|
}
|
|
145
160
|
|
|
146
|
-
|
|
147
|
-
if (methods.includes('DELETE')) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
// Delete multiple
|
|
162
|
+
if (methods.includes('DELETE')) {
|
|
163
|
+
const path = `/${this.endpoint}`;
|
|
164
|
+
this.router.delete(path, applyMiddleware(async (req, res) => {
|
|
165
|
+
const method = 'DELETE';
|
|
166
|
+
try {
|
|
167
|
+
const query = req.query.filter ? JSON.parse(req.query.filter as string) : {};
|
|
168
|
+
const deleteResult:any = await this.model.deleteMany(query);
|
|
169
|
+
if (deleteResult.deletedCount === 0) {
|
|
170
|
+
return res.status(404).send();
|
|
171
|
+
}
|
|
172
|
+
if (options.relatedModel && options.relatedMethods?.includes('DELETE')) {
|
|
173
|
+
await options.relatedModel.deleteMany({ [options.relatedField!]: { $in: query } });
|
|
174
|
+
}
|
|
175
|
+
onSuccess(res, method, deleteResult);
|
|
176
|
+
} catch (error: any) {
|
|
177
|
+
onError(res, method, error);
|
|
178
|
+
}
|
|
179
|
+
}));
|
|
180
|
+
registerRoute('DELETE', path, ['filter']);
|
|
162
181
|
}
|
|
163
|
-
}));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
182
|
|
|
183
|
+
// Delete one
|
|
168
184
|
if (methods.includes('DELETE')) {
|
|
169
|
-
|
|
185
|
+
const path = `/${this.endpoint}/:id`;
|
|
186
|
+
this.router.delete(path, applyMiddleware(async (req, res) => {
|
|
170
187
|
const method = 'DELETE';
|
|
171
188
|
try {
|
|
172
189
|
const item = await this.model.findByIdAndDelete(req.params.id);
|
|
@@ -181,11 +198,13 @@ if (methods.includes('DELETE')) {
|
|
|
181
198
|
onError(res, method, error);
|
|
182
199
|
}
|
|
183
200
|
}));
|
|
201
|
+
registerRoute('DELETE', path, ['id']);
|
|
184
202
|
}
|
|
185
203
|
|
|
186
|
-
|
|
204
|
+
// Aggregate
|
|
187
205
|
if (methods.includes('GET') && options.aggregatePipeline) {
|
|
188
|
-
|
|
206
|
+
const path = `/${this.endpoint}/aggregate`;
|
|
207
|
+
this.router.get(path, applyMiddleware(async (req, res) => {
|
|
189
208
|
const method = 'GET (Aggregate)';
|
|
190
209
|
try {
|
|
191
210
|
const pipeline:any = options.aggregatePipeline ?? [];
|
|
@@ -195,14 +214,16 @@ if (methods.includes('DELETE')) {
|
|
|
195
214
|
onError(res, method, error);
|
|
196
215
|
}
|
|
197
216
|
}));
|
|
217
|
+
registerRoute('GET', path);
|
|
198
218
|
}
|
|
199
219
|
|
|
200
|
-
|
|
220
|
+
// Custom routes
|
|
201
221
|
if (options.customRoutes) {
|
|
202
222
|
options.customRoutes.forEach(route => {
|
|
203
223
|
const { method, path, handler } = route;
|
|
204
224
|
if (methods.includes(method.toUpperCase() as 'POST' | 'GET' | 'PUT' | 'DELETE')) {
|
|
205
225
|
this.router[method](`/${this.endpoint}${path}`, applyMiddleware(handler));
|
|
226
|
+
registerRoute(method.toUpperCase(), `/${this.endpoint}${path}`);
|
|
206
227
|
}
|
|
207
228
|
});
|
|
208
229
|
}
|
|
@@ -211,6 +232,10 @@ if (methods.includes('DELETE')) {
|
|
|
211
232
|
public getRouter(): Router {
|
|
212
233
|
return this.router;
|
|
213
234
|
}
|
|
235
|
+
|
|
236
|
+
public getRoutes(): { method: string, path: string, params?: string[] }[] {
|
|
237
|
+
return this.routes;
|
|
238
|
+
}
|
|
214
239
|
}
|
|
215
240
|
|
|
216
241
|
export default CrudController;
|