@hitchy/plugin-odem-rest 0.4.8 → 0.5.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/LICENSE +1 -1
- package/api/services/odem-rest/cors.js +204 -4
- package/coverage/tmp/coverage-17048-1649848422081-0.json +1 -0
- package/index.js +64 -81
- package/package.json +11 -9
package/index.js
CHANGED
|
@@ -1,31 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* (c) 2018 cepharum GmbH, Berlin, http://cepharum.de
|
|
3
|
-
*
|
|
4
|
-
* The MIT License (MIT)
|
|
5
|
-
*
|
|
6
|
-
* Copyright (c) 2018 cepharum GmbH
|
|
7
|
-
*
|
|
8
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
10
|
-
* in the Software without restriction, including without limitation the rights
|
|
11
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
13
|
-
* furnished to do so, subject to the following conditions:
|
|
14
|
-
*
|
|
15
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
16
|
-
* copies or substantial portions of the Software.
|
|
17
|
-
*
|
|
18
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
-
* SOFTWARE.
|
|
25
|
-
*
|
|
26
|
-
* @author: cepharum
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
1
|
"use strict";
|
|
30
2
|
|
|
31
3
|
const { posix: { resolve } } = require( "path" );
|
|
@@ -34,6 +6,9 @@ module.exports = function() {
|
|
|
34
6
|
const api = this;
|
|
35
7
|
const { runtime: { services: Services, models: Models }, utility: { case: Case } } = api;
|
|
36
8
|
|
|
9
|
+
const logDebug = api.log( "hitchy:odem:rest:debug" );
|
|
10
|
+
const logError = api.log( "hitchy:odem:rest:error" );
|
|
11
|
+
|
|
37
12
|
return {
|
|
38
13
|
policies() {
|
|
39
14
|
const { config: { model: modelConfig = {} } } = api;
|
|
@@ -45,6 +20,7 @@ module.exports = function() {
|
|
|
45
20
|
const after = new Map();
|
|
46
21
|
|
|
47
22
|
before.set( `ALL ${urlPrefix}`, CORS.getCommonRequestFilter() );
|
|
23
|
+
before.set( `ALL ${resolve( urlPrefix, ".schema" )}`, CORS.getRequestFilterForSchemata() );
|
|
48
24
|
after.set( `ALL ${resolve( urlPrefix, ".schema" )}`, reqNotSupported );
|
|
49
25
|
|
|
50
26
|
for ( let i = 0, numNames = modelNames.length; i < numNames; i++ ) {
|
|
@@ -53,6 +29,9 @@ module.exports = function() {
|
|
|
53
29
|
const model = Models[name] || {};
|
|
54
30
|
|
|
55
31
|
before.set( `ALL ${resolve( urlPrefix, routeName )}`, CORS.getRequestFilterForModel( model ) );
|
|
32
|
+
before.set( `ALL ${resolve( urlPrefix, routeName, ".schema" )}`, CORS.getRequestFilterForModelSchema( model ) );
|
|
33
|
+
before.set( `ALL ${resolve( urlPrefix, routeName, ":uuid" )}`, CORS.getRequestFilterForModelItem( model ) );
|
|
34
|
+
|
|
56
35
|
after.set( `ALL ${resolve( urlPrefix, routeName )}`, reqNotSupported );
|
|
57
36
|
}
|
|
58
37
|
|
|
@@ -63,8 +42,8 @@ module.exports = function() {
|
|
|
63
42
|
/**
|
|
64
43
|
* Responds on failure in case of not having handled request before.
|
|
65
44
|
*
|
|
66
|
-
* @param {
|
|
67
|
-
* @param {
|
|
45
|
+
* @param {Hitchy.Core.IncomingMessage} req request descriptor
|
|
46
|
+
* @param {Hitchy.Core.ServerResponse} res response manager
|
|
68
47
|
* @param {function(error:?Error):void} next callback to invoke when finished
|
|
69
48
|
* @returns {void}
|
|
70
49
|
*/
|
|
@@ -118,8 +97,8 @@ module.exports = function() {
|
|
|
118
97
|
/**
|
|
119
98
|
* Handles request for listing schemata of all available models.
|
|
120
99
|
*
|
|
121
|
-
* @param {
|
|
122
|
-
* @param {
|
|
100
|
+
* @param {Hitchy.Core.IncomingMessage} req request descriptor
|
|
101
|
+
* @param {Hitchy.Core.ServerResponse} res response manager
|
|
123
102
|
* @returns {void}
|
|
124
103
|
*/
|
|
125
104
|
function reqFetchSchemata( req, res ) {
|
|
@@ -197,8 +176,8 @@ module.exports = function() {
|
|
|
197
176
|
/**
|
|
198
177
|
* Responds on success.
|
|
199
178
|
*
|
|
200
|
-
* @param {
|
|
201
|
-
* @param {
|
|
179
|
+
* @param {Hitchy.Core.IncomingMessage} req request descriptor
|
|
180
|
+
* @param {Hitchy.Core.ServerResponse} res response manager
|
|
202
181
|
* @returns {void}
|
|
203
182
|
*/
|
|
204
183
|
function reqSuccess( req, res ) {
|
|
@@ -225,12 +204,12 @@ module.exports = function() {
|
|
|
225
204
|
/**
|
|
226
205
|
* Handles request for fetching schema of selected model.
|
|
227
206
|
*
|
|
228
|
-
* @param {
|
|
229
|
-
* @param {
|
|
207
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
208
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
230
209
|
* @returns {void}
|
|
231
210
|
*/
|
|
232
211
|
function reqFetchSchema( req, res ) {
|
|
233
|
-
|
|
212
|
+
logDebug( "got request fetching schema" );
|
|
234
213
|
|
|
235
214
|
if ( !Services.OdemRestSchema.mayBeExposed( req, Model ) ) {
|
|
236
215
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -244,12 +223,12 @@ module.exports = function() {
|
|
|
244
223
|
* Handles request for checking whether some selected item of model exists
|
|
245
224
|
* or not.
|
|
246
225
|
*
|
|
247
|
-
* @param {
|
|
248
|
-
* @param {
|
|
226
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
227
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
249
228
|
* @returns {Promise|undefined} promises request processed successfully
|
|
250
229
|
*/
|
|
251
230
|
function reqCheckItem( req, res ) {
|
|
252
|
-
|
|
231
|
+
logDebug( "got request checking if some item exists" );
|
|
253
232
|
|
|
254
233
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
255
234
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -269,7 +248,7 @@ module.exports = function() {
|
|
|
269
248
|
res.status( exists ? 200 : 404 ).send();
|
|
270
249
|
} )
|
|
271
250
|
.catch( error => {
|
|
272
|
-
|
|
251
|
+
logError( "checking %s:", routeName, error );
|
|
273
252
|
res.status( 500 ).json( { error: error.message } );
|
|
274
253
|
} );
|
|
275
254
|
}
|
|
@@ -277,12 +256,12 @@ module.exports = function() {
|
|
|
277
256
|
/**
|
|
278
257
|
* Handles request for fetching data of selected item.
|
|
279
258
|
*
|
|
280
|
-
* @param {
|
|
281
|
-
* @param {
|
|
259
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
260
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
282
261
|
* @returns {Promise} promises request processed successfully
|
|
283
262
|
*/
|
|
284
263
|
function reqFetchItem( req, res ) {
|
|
285
|
-
|
|
264
|
+
logDebug( "got request fetching some item" );
|
|
286
265
|
|
|
287
266
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
288
267
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -298,9 +277,10 @@ module.exports = function() {
|
|
|
298
277
|
const item = new Model( uuid ); // eslint-disable-line new-cap
|
|
299
278
|
|
|
300
279
|
return item.load()
|
|
301
|
-
.then( loaded => res.json( loaded.toObject() ) )
|
|
280
|
+
.then( loaded => res.json( loaded.toObject( { serialized: true } ) ) )
|
|
302
281
|
.catch( error => {
|
|
303
|
-
|
|
282
|
+
logError( "fetching %s:", routeName, error );
|
|
283
|
+
|
|
304
284
|
switch ( error.code ) {
|
|
305
285
|
case "ENOENT" : {
|
|
306
286
|
res.status( 404 ).json( { error: "selected item not found" } );
|
|
@@ -317,12 +297,12 @@ module.exports = function() {
|
|
|
317
297
|
* Fetches items of a collection optionally required to match some provided
|
|
318
298
|
* query.
|
|
319
299
|
*
|
|
320
|
-
* @param {
|
|
321
|
-
* @param {
|
|
300
|
+
* @param {Hitchy.Core.IncomingMessage} req incoming request
|
|
301
|
+
* @param {Hitchy.Core.ServerResponse} res response controller
|
|
322
302
|
* @returns {Promise} promises response sent
|
|
323
303
|
*/
|
|
324
304
|
function reqFetchItems( req, res ) {
|
|
325
|
-
|
|
305
|
+
logDebug( "got request fetching items" );
|
|
326
306
|
|
|
327
307
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
328
308
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -372,12 +352,12 @@ module.exports = function() {
|
|
|
372
352
|
/**
|
|
373
353
|
* Handles request for listing all items of model.
|
|
374
354
|
*
|
|
375
|
-
* @param {
|
|
376
|
-
* @param {
|
|
355
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
356
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
377
357
|
* @returns {Promise|undefined} promises request processed successfully
|
|
378
358
|
*/
|
|
379
359
|
function reqListMatches( req, res ) {
|
|
380
|
-
|
|
360
|
+
logDebug( "got request listing matching items" );
|
|
381
361
|
|
|
382
362
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
383
363
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -405,7 +385,7 @@ module.exports = function() {
|
|
|
405
385
|
} )
|
|
406
386
|
.then( matches => {
|
|
407
387
|
const result = {
|
|
408
|
-
items: matches.map( m => m.toObject() ),
|
|
388
|
+
items: matches.map( m => m.toObject( { serialized: true } ) ),
|
|
409
389
|
};
|
|
410
390
|
|
|
411
391
|
if ( meta ) {
|
|
@@ -416,7 +396,8 @@ module.exports = function() {
|
|
|
416
396
|
res.json( result );
|
|
417
397
|
} )
|
|
418
398
|
.catch( error => {
|
|
419
|
-
|
|
399
|
+
logError( "querying %s:", routeName, error );
|
|
400
|
+
|
|
420
401
|
res.status( 500 ).json( { error: error.message } );
|
|
421
402
|
} );
|
|
422
403
|
}
|
|
@@ -425,12 +406,12 @@ module.exports = function() {
|
|
|
425
406
|
* Handles request for listing all items of model matching single given
|
|
426
407
|
* condition.
|
|
427
408
|
*
|
|
428
|
-
* @param {
|
|
429
|
-
* @param {
|
|
409
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
410
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
430
411
|
* @returns {Promise|undefined} promises request processed successfully
|
|
431
412
|
*/
|
|
432
413
|
function reqListAll( req, res ) {
|
|
433
|
-
|
|
414
|
+
logDebug( "got request listing all items" );
|
|
434
415
|
|
|
435
416
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
436
417
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -447,7 +428,7 @@ module.exports = function() {
|
|
|
447
428
|
}, { loadRecords, metaCollector: meta } )
|
|
448
429
|
.then( matches => {
|
|
449
430
|
const result = {
|
|
450
|
-
items: matches.map( m => m.toObject() ),
|
|
431
|
+
items: matches.map( m => m.toObject( { serialized: true } ) ),
|
|
451
432
|
};
|
|
452
433
|
|
|
453
434
|
if ( meta ) {
|
|
@@ -458,7 +439,8 @@ module.exports = function() {
|
|
|
458
439
|
res.json( result );
|
|
459
440
|
} )
|
|
460
441
|
.catch( error => {
|
|
461
|
-
|
|
442
|
+
logError( "listing %s:", routeName, error );
|
|
443
|
+
|
|
462
444
|
res.status( 500 ).json( { error: error.message } );
|
|
463
445
|
} );
|
|
464
446
|
}
|
|
@@ -466,12 +448,12 @@ module.exports = function() {
|
|
|
466
448
|
/**
|
|
467
449
|
* Handles request for adding new item.
|
|
468
450
|
*
|
|
469
|
-
* @param {
|
|
470
|
-
* @param {
|
|
451
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
452
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
471
453
|
* @returns {Promise|undefined} promises request processed successfully
|
|
472
454
|
*/
|
|
473
455
|
function reqCreateItem( req, res ) {
|
|
474
|
-
|
|
456
|
+
logDebug( "got request creating item" );
|
|
475
457
|
|
|
476
458
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
477
459
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -483,7 +465,7 @@ module.exports = function() {
|
|
|
483
465
|
return ( req.method === "GET" ? Promise.resolve( req.query ) : req.fetchBody() )
|
|
484
466
|
.then( record => {
|
|
485
467
|
if ( record.uuid ) {
|
|
486
|
-
|
|
468
|
+
logDebug( "creating %s:", routeName, "new entry can not be created with uuid" );
|
|
487
469
|
res.status( 400 ).json( { error: "new entry can not be created with uuid" } );
|
|
488
470
|
return undefined;
|
|
489
471
|
}
|
|
@@ -507,12 +489,12 @@ module.exports = function() {
|
|
|
507
489
|
}
|
|
508
490
|
|
|
509
491
|
return item.save().then( saved => {
|
|
510
|
-
|
|
492
|
+
logDebug( "created %s with %s", routeName, saved.uuid );
|
|
511
493
|
res.status( 201 ).json( { uuid: saved.uuid } );
|
|
512
494
|
} );
|
|
513
495
|
} )
|
|
514
496
|
.catch( error => {
|
|
515
|
-
|
|
497
|
+
logError( "creating %s:", routeName, error );
|
|
516
498
|
res.status( 500 ).json( { error: error.message } );
|
|
517
499
|
} );
|
|
518
500
|
}
|
|
@@ -520,12 +502,12 @@ module.exports = function() {
|
|
|
520
502
|
/**
|
|
521
503
|
* Handles request for updating properties of a selected item.
|
|
522
504
|
*
|
|
523
|
-
* @param {
|
|
524
|
-
* @param {
|
|
505
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
506
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
525
507
|
* @returns {Promise|undefined} promises request processed successfully
|
|
526
508
|
*/
|
|
527
509
|
function reqModifyItem( req, res ) {
|
|
528
|
-
|
|
510
|
+
logDebug( "got request to modify some item" );
|
|
529
511
|
|
|
530
512
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
531
513
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -553,6 +535,7 @@ module.exports = function() {
|
|
|
553
535
|
] )
|
|
554
536
|
.then( ( [ loaded, record ] ) => {
|
|
555
537
|
if ( record ) {
|
|
538
|
+
// FIXME consider using Odem's Model.fromObject() method here
|
|
556
539
|
const names = Object.keys( record );
|
|
557
540
|
const numNames = names.length;
|
|
558
541
|
|
|
@@ -563,21 +546,21 @@ module.exports = function() {
|
|
|
563
546
|
const name = names[i];
|
|
564
547
|
|
|
565
548
|
if ( definedProps[name] ) {
|
|
566
|
-
loaded.$properties[name] = record[name];
|
|
549
|
+
loaded.$properties[name] = record[name]; // eslint-disable-line no-param-reassign
|
|
567
550
|
} else if ( definedComputed[name] ) {
|
|
568
|
-
loaded[name] = record[name];
|
|
551
|
+
loaded[name] = record[name]; // eslint-disable-line no-param-reassign
|
|
569
552
|
}
|
|
570
553
|
}
|
|
571
554
|
}
|
|
572
555
|
|
|
573
556
|
return loaded.save()
|
|
574
557
|
.then( saved => {
|
|
575
|
-
res.json( saved.toObject() );
|
|
558
|
+
res.json( saved.toObject( { serialized: true } ) );
|
|
576
559
|
} );
|
|
577
560
|
} );
|
|
578
561
|
} )
|
|
579
562
|
.catch( error => {
|
|
580
|
-
|
|
563
|
+
logError( "updating %s:", routeName, error );
|
|
581
564
|
res.status( 500 ).json( { error: error.message } );
|
|
582
565
|
} );
|
|
583
566
|
}
|
|
@@ -586,12 +569,12 @@ module.exports = function() {
|
|
|
586
569
|
/**
|
|
587
570
|
* Handles request for updating properties of a selected item.
|
|
588
571
|
*
|
|
589
|
-
* @param {
|
|
590
|
-
* @param {
|
|
572
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
573
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
591
574
|
* @returns {Promise|undefined} promises request processed successfully
|
|
592
575
|
*/
|
|
593
576
|
function reqReplaceItem( req, res ) {
|
|
594
|
-
|
|
577
|
+
logDebug( "got request replacing some item" );
|
|
595
578
|
|
|
596
579
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
597
580
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -647,7 +630,7 @@ module.exports = function() {
|
|
|
647
630
|
res.json( { uuid: saved.uuid } );
|
|
648
631
|
} )
|
|
649
632
|
.catch( error => {
|
|
650
|
-
|
|
633
|
+
logError( "updating %s:", routeName, error );
|
|
651
634
|
res.status( 500 ).json( { error: error.message } );
|
|
652
635
|
} );
|
|
653
636
|
}
|
|
@@ -655,12 +638,12 @@ module.exports = function() {
|
|
|
655
638
|
/**
|
|
656
639
|
* Handles request for removing selected item.
|
|
657
640
|
*
|
|
658
|
-
* @param {
|
|
659
|
-
* @param {
|
|
641
|
+
* @param {Hitchy.Core.IncomingMessage} req description of request
|
|
642
|
+
* @param {Hitchy.Core.ServerResponse} res API for creating response
|
|
660
643
|
* @returns {Promise|undefined} promises request processed successfully
|
|
661
644
|
*/
|
|
662
645
|
function reqRemoveItem( req, res ) {
|
|
663
|
-
|
|
646
|
+
logDebug( "got request removing some item" );
|
|
664
647
|
|
|
665
648
|
if ( !Schema.mayBeExposed( req, Model ) ) {
|
|
666
649
|
res.status( 403 ).json( { error: "access forbidden by model" } );
|
|
@@ -685,12 +668,12 @@ module.exports = function() {
|
|
|
685
668
|
action: "remove"
|
|
686
669
|
} ) )
|
|
687
670
|
.catch( error => {
|
|
688
|
-
|
|
671
|
+
logError( "removing %s:", routeName, error );
|
|
689
672
|
res.status( 500 ).json( { error: error.message } );
|
|
690
673
|
} );
|
|
691
674
|
}
|
|
692
675
|
|
|
693
|
-
|
|
676
|
+
logError( "request for removing missing %s ignored", routeName );
|
|
694
677
|
res.status( 404 ).json( { error: "no such entry" } );
|
|
695
678
|
|
|
696
679
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hitchy/plugin-odem-rest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "HTTP REST API for Hitchy's ODM",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"lint": "eslint .",
|
|
8
|
-
"test": "hitchy-pm odem --exec mocha --ui=tdd test/**/*.js"
|
|
8
|
+
"test": "hitchy-pm odem --exec mocha --ui=tdd 'test/scripts/**/*.js'",
|
|
9
|
+
"coverage": "hitchy-pm odem --exec c8 mocha --ui=tdd 'test/scripts/**/*.js'"
|
|
9
10
|
},
|
|
10
11
|
"repository": "https://gitlab.com/hitchy/plugin-odem-rest.git",
|
|
11
12
|
"keywords": [
|
|
@@ -17,15 +18,16 @@
|
|
|
17
18
|
"bugs": "https://gitlab.com/hitchy/plugin-odem-rest/-/issues",
|
|
18
19
|
"homepage": "https://gitlab.com/hitchy/plugin-odem-rest#plugin-odem-rest",
|
|
19
20
|
"peerDependencies": {
|
|
20
|
-
"@hitchy/core": "^0.6.
|
|
21
|
-
"@hitchy/plugin-odem": "^0.
|
|
21
|
+
"@hitchy/core": "^0.6.18",
|
|
22
|
+
"@hitchy/plugin-odem": "^0.7.0"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"eslint
|
|
27
|
-
"
|
|
28
|
-
"
|
|
25
|
+
"@hitchy/server-dev-tools": "^0.4.2",
|
|
26
|
+
"c8": "^7.11.0",
|
|
27
|
+
"eslint": "^8.13.0",
|
|
28
|
+
"eslint-config-cepharum": "^1.0.12",
|
|
29
|
+
"eslint-plugin-promise": "^6.0.0",
|
|
30
|
+
"mocha": "^9.2.2",
|
|
29
31
|
"should": "^13.2.3",
|
|
30
32
|
"should-http": "^0.1.1"
|
|
31
33
|
}
|