@fjell/express-router 4.4.12 → 4.4.18
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 +332 -0
- package/build.js +4 -0
- package/dist/CItemRouter.d.ts +5 -4
- package/dist/CItemRouter.d.ts.map +1 -0
- package/dist/CItemRouter.js +63 -92
- package/dist/CItemRouter.js.map +7 -1
- package/dist/Instance.d.ts +5 -4
- package/dist/Instance.d.ts.map +1 -0
- package/dist/Instance.js +12 -22
- package/dist/Instance.js.map +7 -1
- package/dist/InstanceFactory.d.ts +5 -4
- package/dist/InstanceFactory.d.ts.map +1 -0
- package/dist/InstanceFactory.js +10 -18
- package/dist/InstanceFactory.js.map +7 -1
- package/dist/ItemRouter.d.ts +5 -4
- package/dist/ItemRouter.d.ts.map +1 -0
- package/dist/ItemRouter.js +290 -405
- package/dist/ItemRouter.js.map +7 -1
- package/dist/PItemRouter.d.ts +5 -4
- package/dist/PItemRouter.d.ts.map +1 -0
- package/dist/PItemRouter.js +43 -67
- package/dist/PItemRouter.js.map +7 -1
- package/dist/Registry.d.ts +1 -0
- package/dist/Registry.d.ts.map +1 -0
- package/dist/Registry.js +22 -27
- package/dist/Registry.js.map +7 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -6
- package/dist/index.js.map +7 -1
- package/dist/logger.d.ts +2 -1
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +6 -5
- package/dist/logger.js.map +7 -1
- package/dist/util/general.d.ts +1 -0
- package/dist/util/general.d.ts.map +1 -0
- package/dist/util/general.js +50 -0
- package/dist/util/general.js.map +7 -0
- package/docs/docs.config.ts +44 -0
- package/docs/index.html +18 -0
- package/docs/package.json +34 -0
- package/docs/public/README.md +332 -0
- package/docs/public/examples-README.md +339 -0
- package/docs/public/fjell-icon.svg +1 -0
- package/docs/public/pano.png +0 -0
- package/docs/src/index.css +21 -0
- package/docs/src/main.tsx +12 -0
- package/docs/src/test/setup.ts +1 -0
- package/docs/src/types.d.ts +4 -0
- package/docs/tsconfig.node.json +6 -0
- package/package.json +21 -19
- package/vitest.config.ts +45 -0
- package/dist/CItemRouter.cjs +0 -100
- package/dist/CItemRouter.cjs.map +0 -1
- package/dist/Instance.cjs +0 -31
- package/dist/Instance.cjs.map +0 -1
- package/dist/InstanceFactory.cjs +0 -25
- package/dist/InstanceFactory.cjs.map +0 -1
- package/dist/ItemRouter.cjs +0 -427
- package/dist/ItemRouter.cjs.map +0 -1
- package/dist/PItemRouter.cjs +0 -75
- package/dist/PItemRouter.cjs.map +0 -1
- package/dist/Registry.cjs +0 -36
- package/dist/Registry.cjs.map +0 -1
- package/dist/index.cjs +0 -657
- package/dist/index.cjs.map +0 -1
- package/dist/logger.cjs +0 -10
- package/dist/logger.cjs.map +0 -1
package/dist/ItemRouter.js
CHANGED
|
@@ -1,423 +1,308 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.defineProperty(obj, key, {
|
|
10
|
-
value: value,
|
|
11
|
-
enumerable: true,
|
|
12
|
-
configurable: true,
|
|
13
|
-
writable: true
|
|
14
|
-
});
|
|
15
|
-
} else {
|
|
16
|
-
obj[key] = value;
|
|
17
|
-
}
|
|
18
|
-
return obj;
|
|
19
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
cPK,
|
|
3
|
+
validatePK
|
|
4
|
+
} from "@fjell/core";
|
|
5
|
+
import { NotFoundError } from "@fjell/lib";
|
|
6
|
+
import deepmerge from "deepmerge";
|
|
7
|
+
import { Router } from "express";
|
|
8
|
+
import LibLogger from "./logger";
|
|
20
9
|
class ItemRouter {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
10
|
+
lib;
|
|
11
|
+
keyType;
|
|
12
|
+
options;
|
|
13
|
+
childRouters = {};
|
|
14
|
+
logger;
|
|
15
|
+
constructor(lib, keyType, options = {}) {
|
|
16
|
+
this.lib = lib;
|
|
17
|
+
this.keyType = keyType;
|
|
18
|
+
this.options = options;
|
|
19
|
+
this.logger = LibLogger.get("ItemRouter", keyType);
|
|
20
|
+
}
|
|
21
|
+
getPkType = () => {
|
|
22
|
+
return this.keyType;
|
|
23
|
+
};
|
|
24
|
+
getPkParam = () => {
|
|
25
|
+
return `${this.getPkType()}Pk`;
|
|
26
|
+
};
|
|
27
|
+
getLk(res) {
|
|
28
|
+
return { kt: this.keyType, lk: res.locals[this.getPkParam()] };
|
|
29
|
+
}
|
|
30
|
+
// this is meant to be consumed by children routers
|
|
31
|
+
getLKA(res) {
|
|
32
|
+
return [this.getLk(res)];
|
|
33
|
+
}
|
|
34
|
+
getPk(res) {
|
|
35
|
+
return cPK(res.locals[this.getPkParam()], this.getPkType());
|
|
36
|
+
}
|
|
37
|
+
// Unless this is a contained router, the locations will always be an empty array.
|
|
38
|
+
/* eslint-disable */
|
|
39
|
+
getLocations(res) {
|
|
40
|
+
throw new Error("Method not implemented in an abstract router");
|
|
41
|
+
}
|
|
42
|
+
/* eslint-enable */
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
44
|
+
getIk(res) {
|
|
45
|
+
throw new Error("Method not implemented in an abstract router");
|
|
46
|
+
}
|
|
47
|
+
postAllAction = async (req, res) => {
|
|
48
|
+
const libOptions = this.lib.options;
|
|
49
|
+
const libOperations = this.lib.operations;
|
|
50
|
+
this.logger.debug("Posting All Action", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
51
|
+
const allActionKey = req.path.substring(req.path.lastIndexOf("/") + 1);
|
|
52
|
+
if (!libOptions.allActions) {
|
|
53
|
+
this.logger.error("Item Actions are not configured");
|
|
54
|
+
res.status(500).json({ error: "Item Actions are not configured" });
|
|
55
|
+
return;
|
|
26
56
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
57
|
+
const allAction = libOptions.allActions[allActionKey];
|
|
58
|
+
if (!allAction) {
|
|
59
|
+
this.logger.error("All Action is not configured", { allActionKey });
|
|
60
|
+
res.status(500).json({ error: "Item Action is not configured" });
|
|
61
|
+
return;
|
|
32
62
|
}
|
|
33
|
-
|
|
34
|
-
|
|
63
|
+
try {
|
|
64
|
+
res.json(await libOperations.allAction(allActionKey, req.body));
|
|
65
|
+
} catch (err) {
|
|
66
|
+
this.logger.error("Error in All Action", { message: err?.message, stack: err?.stack });
|
|
67
|
+
res.status(500).json(err);
|
|
35
68
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
69
|
+
};
|
|
70
|
+
getAllFacet = async (req, res) => {
|
|
71
|
+
const libOptions = this.lib.options;
|
|
72
|
+
const libOperations = this.lib.operations;
|
|
73
|
+
this.logger.debug("Getting All Facet", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
74
|
+
const facetKey = req.path.substring(req.path.lastIndexOf("/") + 1);
|
|
75
|
+
if (!libOptions.allFacets) {
|
|
76
|
+
this.logger.error("Item Facets are not configured");
|
|
77
|
+
res.status(500).json({ error: "Item Facets are not configured" });
|
|
78
|
+
return;
|
|
39
79
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
80
|
+
const facet = libOptions.allFacets[facetKey];
|
|
81
|
+
if (!facet) {
|
|
82
|
+
this.logger.error("Item Facet is not configured", { facetKey });
|
|
83
|
+
res.status(500).json({ error: "Item Facet is not configured" });
|
|
84
|
+
return;
|
|
43
85
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
86
|
+
try {
|
|
87
|
+
const combinedQueryParams = { ...req.query, ...req.params };
|
|
88
|
+
res.json(await libOperations.allFacet(facetKey, combinedQueryParams));
|
|
89
|
+
} catch (err) {
|
|
90
|
+
this.logger.error("Error in All Facet", { message: err?.message, stack: err?.stack });
|
|
91
|
+
res.status(500).json(err);
|
|
48
92
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
} catch (err) {
|
|
208
|
-
this.logger.error('Error in Item Facet', {
|
|
209
|
-
message: err === null || err === void 0 ? void 0 : err.message,
|
|
210
|
-
stack: err === null || err === void 0 ? void 0 : err.stack
|
|
211
|
-
});
|
|
212
|
-
res.status(500).json(err);
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
_define_property(this, "configure", (router)=>{
|
|
216
|
-
const libOptions = this.lib.options;
|
|
217
|
-
this.logger.debug('Configuring Router', {
|
|
218
|
-
pkType: this.getPkType()
|
|
219
|
-
});
|
|
220
|
-
router.get('/', this.findItems);
|
|
221
|
-
router.post('/', this.createItem);
|
|
222
|
-
this.logger.default('All Actions supplied to Router', {
|
|
223
|
-
allActions: libOptions.allActions
|
|
224
|
-
});
|
|
225
|
-
if (libOptions.allActions) {
|
|
226
|
-
Object.keys(libOptions.allActions).forEach((actionKey)=>{
|
|
227
|
-
this.logger.debug('Configuring All Action %s', actionKey);
|
|
228
|
-
// TODO: Ok, this is a bit of a hack, but we need to customize the types of the request handlers
|
|
229
|
-
router.post(`/${actionKey}`, this.postAllAction);
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
this.logger.default('All Facets supplied to Router', {
|
|
233
|
-
allFacets: libOptions.allFacets
|
|
234
|
-
});
|
|
235
|
-
if (libOptions.allFacets) {
|
|
236
|
-
Object.keys(libOptions.allFacets).forEach((facetKey)=>{
|
|
237
|
-
this.logger.debug('Configuring All Facet %s', facetKey);
|
|
238
|
-
// TODO: Ok, this is a bit of a hack, but we need to customize the types of the request handlers
|
|
239
|
-
router.get(`/${facetKey}`, this.getAllFacet);
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
const itemRouter = Router();
|
|
243
|
-
itemRouter.get('/', this.getItem);
|
|
244
|
-
itemRouter.put('/', this.updateItem);
|
|
245
|
-
itemRouter.delete('/', this.deleteItem);
|
|
246
|
-
this.logger.default('Item Actions supplied to Router', {
|
|
247
|
-
itemActions: libOptions.actions
|
|
248
|
-
});
|
|
249
|
-
if (libOptions.actions) {
|
|
250
|
-
Object.keys(libOptions.actions).forEach((actionKey)=>{
|
|
251
|
-
this.logger.debug('Configuring Item Action %s', actionKey);
|
|
252
|
-
// TODO: Ok, this is a bit of a hack, but we need to customize the types of the request handlers
|
|
253
|
-
itemRouter.post(`/${actionKey}`, this.postItemAction);
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
this.logger.default('Item Facets supplied to Router', {
|
|
257
|
-
itemFacets: libOptions.facets
|
|
258
|
-
});
|
|
259
|
-
if (libOptions.facets) {
|
|
260
|
-
Object.keys(libOptions.facets).forEach((facetKey)=>{
|
|
261
|
-
this.logger.debug('Configuring Item Facet %s', facetKey);
|
|
262
|
-
// TODO: Ok, this is a bit of a hack, but we need to customize the types of the request handlers
|
|
263
|
-
itemRouter.get(`/${facetKey}`, this.getItemFacet);
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
this.logger.debug('Configuring Item Operations under PK Param %s', this.getPkParam());
|
|
267
|
-
router.use(`/:${this.getPkParam()}`, this.validatePrimaryKeyValue, itemRouter);
|
|
268
|
-
if (this.childRouters) {
|
|
269
|
-
this.configureChildRouters(itemRouter, this.childRouters);
|
|
270
|
-
}
|
|
271
|
-
return router;
|
|
272
|
-
});
|
|
273
|
-
_define_property(this, "validatePrimaryKeyValue", (req, res, next)=>{
|
|
274
|
-
const pkParamValue = req.params[this.getPkParam()];
|
|
275
|
-
if (this.validatePKParam(pkParamValue)) {
|
|
276
|
-
res.locals[this.getPkParam()] = pkParamValue;
|
|
277
|
-
next();
|
|
278
|
-
} else {
|
|
279
|
-
this.logger.error('Invalid Primary Key', {
|
|
280
|
-
pkParamValue,
|
|
281
|
-
path: req === null || req === void 0 ? void 0 : req.originalUrl
|
|
282
|
-
});
|
|
283
|
-
res.status(500).json({
|
|
284
|
-
error: 'Invalid Primary Key',
|
|
285
|
-
path: req === null || req === void 0 ? void 0 : req.originalUrl
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
_define_property(this, "configureChildRouters", (router, childRouters)=>{
|
|
290
|
-
for(const path in childRouters){
|
|
291
|
-
this.logger.debug('Configuring Child Router at Path %s', path);
|
|
292
|
-
router.use(`/${path}`, childRouters[path]);
|
|
293
|
-
}
|
|
294
|
-
return router;
|
|
295
|
-
});
|
|
296
|
-
_define_property(this, "addChildRouter", (path, router)=>{
|
|
297
|
-
this.childRouters[path] = router;
|
|
298
|
-
});
|
|
299
|
-
/* istanbul ignore next */ // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
300
|
-
_define_property(this, "createItem", async (req, res)=>{
|
|
301
|
-
throw new Error('Method not implemented in an abstract router');
|
|
302
|
-
});
|
|
303
|
-
// TODO: Probably a better way to do this, but this postCreate hook only needs the item.
|
|
304
|
-
/* istanbul ignore next */ _define_property(this, "postCreateItem", async (item)=>{
|
|
305
|
-
this.logger.debug('Post Create Item', {
|
|
306
|
-
item
|
|
307
|
-
});
|
|
308
|
-
return item;
|
|
309
|
-
});
|
|
310
|
-
_define_property(this, "deleteItem", async (req, res)=>{
|
|
311
|
-
const libOperations = this.lib.operations;
|
|
312
|
-
this.logger.debug('Deleting Item', {
|
|
313
|
-
query: req.query,
|
|
314
|
-
params: req.params,
|
|
315
|
-
locals: res.locals
|
|
316
|
-
});
|
|
317
|
-
const ik = this.getIk(res);
|
|
318
|
-
const removedItem = await libOperations.remove(ik);
|
|
319
|
-
const item = validatePK(removedItem, this.getPkType());
|
|
320
|
-
res.json(item);
|
|
321
|
-
});
|
|
322
|
-
/* eslint-disable */ /* istanbul ignore next */ _define_property(this, "findItems", async (req, res)=>{
|
|
323
|
-
throw new Error('Method not implemented in an abstract router');
|
|
324
|
-
});
|
|
325
|
-
/* eslint-enable */ _define_property(this, "getItem", async (req, res)=>{
|
|
326
|
-
const libOperations = this.lib.operations;
|
|
327
|
-
this.logger.debug('Getting Item', {
|
|
328
|
-
query: req.query,
|
|
329
|
-
params: req.params,
|
|
330
|
-
locals: res.locals
|
|
331
|
-
});
|
|
332
|
-
const ik = this.getIk(res);
|
|
333
|
-
try {
|
|
334
|
-
// TODO: What error does validate PK throw, when can that fail?
|
|
335
|
-
const item = validatePK(await libOperations.get(ik), this.getPkType());
|
|
336
|
-
res.json(item);
|
|
337
|
-
} catch (err) {
|
|
338
|
-
if (err instanceof NotFoundError) {
|
|
339
|
-
this.logger.error('Item Not Found', {
|
|
340
|
-
ik,
|
|
341
|
-
message: err === null || err === void 0 ? void 0 : err.message,
|
|
342
|
-
stack: err === null || err === void 0 ? void 0 : err.stack
|
|
343
|
-
});
|
|
344
|
-
res.status(404).json({
|
|
345
|
-
ik,
|
|
346
|
-
message: "Item Not Found"
|
|
347
|
-
});
|
|
348
|
-
} else {
|
|
349
|
-
this.logger.error('General Error', {
|
|
350
|
-
ik,
|
|
351
|
-
message: err === null || err === void 0 ? void 0 : err.message,
|
|
352
|
-
stack: err === null || err === void 0 ? void 0 : err.stack
|
|
353
|
-
});
|
|
354
|
-
res.status(500).json({
|
|
355
|
-
ik,
|
|
356
|
-
message: "General Error"
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
}
|
|
93
|
+
};
|
|
94
|
+
postItemAction = async (req, res) => {
|
|
95
|
+
const libOptions = this.lib.options;
|
|
96
|
+
const libOperations = this.lib.operations;
|
|
97
|
+
this.logger.debug("Getting Item", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
98
|
+
const ik = this.getIk(res);
|
|
99
|
+
const actionKey = req.path.substring(req.path.lastIndexOf("/") + 1);
|
|
100
|
+
if (!libOptions.actions) {
|
|
101
|
+
this.logger.error("Item Actions are not configured");
|
|
102
|
+
res.status(500).json({ error: "Item Actions are not configured" });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const action = libOptions.actions[actionKey];
|
|
106
|
+
if (!action) {
|
|
107
|
+
this.logger.error("Item Action is not configured", { actionKey });
|
|
108
|
+
res.status(500).json({ error: "Item Action is not configured" });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
res.json(await libOperations.action(ik, actionKey, req.body));
|
|
113
|
+
} catch (err) {
|
|
114
|
+
this.logger.error("Error in Item Action", { message: err?.message, stack: err?.stack });
|
|
115
|
+
res.status(500).json(err);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
getItemFacet = async (req, res) => {
|
|
119
|
+
const libOptions = this.lib.options;
|
|
120
|
+
const libOperations = this.lib.operations;
|
|
121
|
+
this.logger.debug("Getting Item", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
122
|
+
const ik = this.getIk(res);
|
|
123
|
+
const facetKey = req.path.substring(req.path.lastIndexOf("/") + 1);
|
|
124
|
+
if (!libOptions.facets) {
|
|
125
|
+
this.logger.error("Item Facets are not configured");
|
|
126
|
+
res.status(500).json({ error: "Item Facets are not configured" });
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const facet = libOptions.facets[facetKey];
|
|
130
|
+
if (!facet) {
|
|
131
|
+
this.logger.error("Item Facet is not configured", { facetKey });
|
|
132
|
+
res.status(500).json({ error: "Item Facet is not configured" });
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
const combinedQueryParams = { ...req.query, ...req.params };
|
|
137
|
+
res.json(await libOperations.facet(ik, facetKey, combinedQueryParams));
|
|
138
|
+
} catch (err) {
|
|
139
|
+
this.logger.error("Error in Item Facet", { message: err?.message, stack: err?.stack });
|
|
140
|
+
res.status(500).json(err);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
configure = (router) => {
|
|
144
|
+
const libOptions = this.lib.options;
|
|
145
|
+
this.logger.debug("Configuring Router", { pkType: this.getPkType() });
|
|
146
|
+
router.get("/", this.findItems);
|
|
147
|
+
router.post("/", this.createItem);
|
|
148
|
+
this.logger.default("All Actions supplied to Router", { allActions: libOptions.allActions });
|
|
149
|
+
if (libOptions.allActions) {
|
|
150
|
+
Object.keys(libOptions.allActions).forEach((actionKey) => {
|
|
151
|
+
this.logger.debug("Configuring All Action %s", actionKey);
|
|
152
|
+
router.post(`/${actionKey}`, this.postAllAction);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
this.logger.default("All Facets supplied to Router", { allFacets: libOptions.allFacets });
|
|
156
|
+
if (libOptions.allFacets) {
|
|
157
|
+
Object.keys(libOptions.allFacets).forEach((facetKey) => {
|
|
158
|
+
this.logger.debug("Configuring All Facet %s", facetKey);
|
|
159
|
+
router.get(`/${facetKey}`, this.getAllFacet);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
const itemRouter = Router();
|
|
163
|
+
itemRouter.get("/", this.getItem);
|
|
164
|
+
itemRouter.put("/", this.updateItem);
|
|
165
|
+
itemRouter.delete("/", this.deleteItem);
|
|
166
|
+
this.logger.default("Item Actions supplied to Router", { itemActions: libOptions.actions });
|
|
167
|
+
if (libOptions.actions) {
|
|
168
|
+
Object.keys(libOptions.actions).forEach((actionKey) => {
|
|
169
|
+
this.logger.debug("Configuring Item Action %s", actionKey);
|
|
170
|
+
itemRouter.post(`/${actionKey}`, this.postItemAction);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
this.logger.default("Item Facets supplied to Router", { itemFacets: libOptions.facets });
|
|
174
|
+
if (libOptions.facets) {
|
|
175
|
+
Object.keys(libOptions.facets).forEach((facetKey) => {
|
|
176
|
+
this.logger.debug("Configuring Item Facet %s", facetKey);
|
|
177
|
+
itemRouter.get(`/${facetKey}`, this.getItemFacet);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
this.logger.debug("Configuring Item Operations under PK Param %s", this.getPkParam());
|
|
181
|
+
router.use(`/:${this.getPkParam()}`, this.validatePrimaryKeyValue, itemRouter);
|
|
182
|
+
if (this.childRouters) {
|
|
183
|
+
this.configureChildRouters(itemRouter, this.childRouters);
|
|
184
|
+
}
|
|
185
|
+
return router;
|
|
186
|
+
};
|
|
187
|
+
validatePrimaryKeyValue = (req, res, next) => {
|
|
188
|
+
const pkParamValue = req.params[this.getPkParam()];
|
|
189
|
+
if (this.validatePKParam(pkParamValue)) {
|
|
190
|
+
res.locals[this.getPkParam()] = pkParamValue;
|
|
191
|
+
next();
|
|
192
|
+
} else {
|
|
193
|
+
this.logger.error("Invalid Primary Key", { pkParamValue, path: req?.originalUrl });
|
|
194
|
+
res.status(500).json({ error: "Invalid Primary Key", path: req?.originalUrl });
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
configureChildRouters = (router, childRouters) => {
|
|
198
|
+
for (const path in childRouters) {
|
|
199
|
+
this.logger.debug("Configuring Child Router at Path %s", path);
|
|
200
|
+
router.use(`/${path}`, childRouters[path]);
|
|
201
|
+
}
|
|
202
|
+
return router;
|
|
203
|
+
};
|
|
204
|
+
addChildRouter = (path, router) => {
|
|
205
|
+
this.childRouters[path] = router;
|
|
206
|
+
};
|
|
207
|
+
/* istanbul ignore next */
|
|
208
|
+
getRouter() {
|
|
209
|
+
const router = Router();
|
|
210
|
+
this.configure(router);
|
|
211
|
+
return router;
|
|
212
|
+
}
|
|
213
|
+
/* istanbul ignore next */
|
|
214
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
215
|
+
createItem = async (req, res) => {
|
|
216
|
+
throw new Error("Method not implemented in an abstract router");
|
|
217
|
+
};
|
|
218
|
+
// TODO: Probably a better way to do this, but this postCreate hook only needs the item.
|
|
219
|
+
/* istanbul ignore next */
|
|
220
|
+
postCreateItem = async (item) => {
|
|
221
|
+
this.logger.debug("Post Create Item", { item });
|
|
222
|
+
return item;
|
|
223
|
+
};
|
|
224
|
+
deleteItem = async (req, res) => {
|
|
225
|
+
const libOperations = this.lib.operations;
|
|
226
|
+
this.logger.debug("Deleting Item", { query: req.query, params: req.params, locals: res.locals });
|
|
227
|
+
const ik = this.getIk(res);
|
|
228
|
+
const removedItem = await libOperations.remove(ik);
|
|
229
|
+
const item = validatePK(removedItem, this.getPkType());
|
|
230
|
+
res.json(item);
|
|
231
|
+
};
|
|
232
|
+
/* eslint-disable */
|
|
233
|
+
/* istanbul ignore next */
|
|
234
|
+
findItems = async (req, res) => {
|
|
235
|
+
throw new Error("Method not implemented in an abstract router");
|
|
236
|
+
};
|
|
237
|
+
/* eslint-enable */
|
|
238
|
+
getItem = async (req, res) => {
|
|
239
|
+
const libOperations = this.lib.operations;
|
|
240
|
+
this.logger.debug("Getting Item", { query: req.query, params: req.params, locals: res.locals });
|
|
241
|
+
const ik = this.getIk(res);
|
|
242
|
+
try {
|
|
243
|
+
const item = validatePK(await libOperations.get(ik), this.getPkType());
|
|
244
|
+
res.json(item);
|
|
245
|
+
} catch (err) {
|
|
246
|
+
if (err instanceof NotFoundError) {
|
|
247
|
+
this.logger.error("Item Not Found", { ik, message: err?.message, stack: err?.stack });
|
|
248
|
+
res.status(404).json({
|
|
249
|
+
ik,
|
|
250
|
+
message: "Item Not Found"
|
|
360
251
|
});
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
params: req === null || req === void 0 ? void 0 : req.params,
|
|
367
|
-
locals: res === null || res === void 0 ? void 0 : res.locals
|
|
368
|
-
});
|
|
369
|
-
const ik = this.getIk(res);
|
|
370
|
-
const itemToUpdate = this.convertDates(req.body);
|
|
371
|
-
const retItem = validatePK(await libOperations.update(ik, itemToUpdate), this.getPkType());
|
|
372
|
-
res.json(retItem);
|
|
252
|
+
} else {
|
|
253
|
+
this.logger.error("General Error", { ik, message: err?.message, stack: err?.stack });
|
|
254
|
+
res.status(500).json({
|
|
255
|
+
ik,
|
|
256
|
+
message: "General Error"
|
|
373
257
|
});
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
updateItem = async (req, res) => {
|
|
262
|
+
const libOperations = this.lib.operations;
|
|
263
|
+
this.logger.debug(
|
|
264
|
+
"Updating Item",
|
|
265
|
+
{ body: req?.body, query: req?.query, params: req?.params, locals: res?.locals }
|
|
266
|
+
);
|
|
267
|
+
const ik = this.getIk(res);
|
|
268
|
+
const itemToUpdate = this.convertDates(req.body);
|
|
269
|
+
const retItem = validatePK(await libOperations.update(ik, itemToUpdate), this.getPkType());
|
|
270
|
+
res.json(retItem);
|
|
271
|
+
};
|
|
272
|
+
convertDates = (item) => {
|
|
273
|
+
const events = item.events;
|
|
274
|
+
this.logger.debug("Converting Dates", { item });
|
|
275
|
+
if (events) {
|
|
276
|
+
Object.keys(events).forEach((key) => {
|
|
277
|
+
Object.assign(events, {
|
|
278
|
+
[key]: deepmerge(events[key], { at: events[key].at ? new Date(events[key].at) : null })
|
|
392
279
|
});
|
|
393
|
-
|
|
394
|
-
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
Object.assign(item, { events });
|
|
283
|
+
return item;
|
|
284
|
+
};
|
|
285
|
+
// TODO: Maybe just simplify this and require that everything is a UUID?
|
|
286
|
+
/**
|
|
395
287
|
* This method might be an annoyance, but we need to capture a few cases where someone passes
|
|
396
288
|
* a PK parameter that has an odd string in it.
|
|
397
289
|
*
|
|
398
290
|
* @param pkParamValue The value of the primary key parameter
|
|
399
291
|
* @returns if the value is valid.
|
|
400
|
-
*/
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
pkParamValue
|
|
410
|
-
});
|
|
411
|
-
validPkParam = false;
|
|
412
|
-
}
|
|
413
|
-
return validPkParam;
|
|
414
|
-
});
|
|
415
|
-
this.lib = lib;
|
|
416
|
-
this.keyType = keyType;
|
|
417
|
-
this.options = options;
|
|
418
|
-
this.logger = LibLogger.get("ItemRouter", keyType);
|
|
292
|
+
*/
|
|
293
|
+
validatePKParam = (pkParamValue) => {
|
|
294
|
+
let validPkParam = true;
|
|
295
|
+
if (pkParamValue.length <= 0) {
|
|
296
|
+
this.logger.error("Primary Key is an Empty String", { pkParamValue });
|
|
297
|
+
validPkParam = false;
|
|
298
|
+
} else if (pkParamValue === "undefined") {
|
|
299
|
+
this.logger.error("Primary Key is the string 'undefined'", { pkParamValue });
|
|
300
|
+
validPkParam = false;
|
|
419
301
|
}
|
|
302
|
+
return validPkParam;
|
|
303
|
+
};
|
|
420
304
|
}
|
|
421
|
-
|
|
422
|
-
|
|
305
|
+
export {
|
|
306
|
+
ItemRouter
|
|
307
|
+
};
|
|
423
308
|
//# sourceMappingURL=ItemRouter.js.map
|