meadow-endpoints 2.0.23 → 2.0.24
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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
since 2022
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"EntrypointInputSourceFile": "/home/alex/dev/
|
|
2
|
+
"EntrypointInputSourceFile": "/home/alex/dev/retold/modules/meadow/meadow-endpoints/source/Meadow-Endpoints.js",
|
|
3
3
|
"LibraryObjectName": "MeadowEndpoints",
|
|
4
|
-
"LibraryOutputFolder": "/home/alex/dev/
|
|
4
|
+
"LibraryOutputFolder": "/home/alex/dev/retold/modules/meadow/meadow-endpoints/dist/",
|
|
5
5
|
"LibraryUniminifiedFileName": "meadow-endpoints.js",
|
|
6
6
|
"LibraryMinifiedFileName": "meadow-endpoints.min.js",
|
|
7
7
|
"BrowserifyIgnore": []
|
package/.gulpfile-quackage.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require('/home/alex/dev/
|
|
2
|
-
require('/home/alex/dev/
|
|
1
|
+
require('/home/alex/dev/retold/modules/meadow/meadow-endpoints/node_modules/quackage/gulp/Quackage-Gulpfile.js');
|
|
2
|
+
require('/home/alex/dev/retold/modules/meadow/meadow-endpoints/node_modules/quackage/gulp/Quackage-Gulpfile.js');
|
package/package.json
CHANGED
|
@@ -54,6 +54,9 @@ var MeadowEndpoints = function()
|
|
|
54
54
|
Reads: require('./crud/Meadow-Endpoint-Reads.js'),
|
|
55
55
|
ReadsBy: require('./crud/Meadow-Endpoint-ReadsBy.js'),
|
|
56
56
|
|
|
57
|
+
// Body-driven read: filter/pagination/mode travel in a JSON POST body
|
|
58
|
+
Query: require('./crud/Meadow-Endpoint-Query.js'),
|
|
59
|
+
|
|
57
60
|
ReadSelectList: require('./crud/Meadow-Endpoint-ReadSelectList.js'),
|
|
58
61
|
ReadLiteList: require('./crud/Meadow-Endpoint-ReadLiteList.js'),
|
|
59
62
|
ReadDistinctList: require('./crud/Meadow-Endpoint-ReadDistinctList.js'),
|
|
@@ -343,6 +346,7 @@ var MeadowEndpoints = function()
|
|
|
343
346
|
}
|
|
344
347
|
if (_EnabledBehaviors.Reads)
|
|
345
348
|
{
|
|
349
|
+
pRestServer.post(`${tmpEndpointPrefix}s/Query`, _CommonServices.bodyParser(), _EndpointAuthenticators.Reads, wireState, _Endpoints.Query);
|
|
346
350
|
pRestServer.get(`${tmpEndpointPrefix}s`, _EndpointAuthenticators.Reads, wireState, _Endpoints.Reads);
|
|
347
351
|
pRestServer.get(`${tmpEndpointPrefix}s/By/:ByField/:ByValue`, _EndpointAuthenticators.Reads, wireState, _Endpoints.ReadsBy);
|
|
348
352
|
pRestServer.get(`${tmpEndpointPrefix}s/By/:ByField/:ByValue/:Begin/:Cap`, _EndpointAuthenticators.Reads, wireState, _Endpoints.ReadsBy);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meadow Endpoint - Body-driven Read
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
*
|
|
6
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
+
* @module Meadow
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A single POST endpoint that carries the filter, pagination and read-mode
|
|
12
|
+
* selection in a JSON body instead of the URI. This sidesteps URI length
|
|
13
|
+
* limits hit by complex filters and large IN-lists, while reusing the exact
|
|
14
|
+
* GET read handlers (and therefore their authorizers, marshalling and response
|
|
15
|
+
* shapes) by mapping the body onto pRequest.params and delegating.
|
|
16
|
+
*
|
|
17
|
+
* Body envelope:
|
|
18
|
+
* {
|
|
19
|
+
* "Filter": "FBV~Genre~EQ~Books~...", // meadow-filter string
|
|
20
|
+
* "Begin": 0,
|
|
21
|
+
* "Cap": 250,
|
|
22
|
+
* "ExtraColumns": "ColumnA,ColumnB", // Lite read
|
|
23
|
+
* "Columns": "ColumnA,ColumnB", // Distinct read
|
|
24
|
+
* "Lite": true, "Distinct": true, "Count": true
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* The read mode is selected by the flags, resolved by precedence:
|
|
28
|
+
* Count > Distinct > Lite > Reads (the default). This lets a caller compose a
|
|
29
|
+
* read query (filter, pagination, Lite/Distinct shaping) and flip Count on to
|
|
30
|
+
* get the count of that same query.
|
|
31
|
+
*/
|
|
32
|
+
var doReads = require('./Meadow-Endpoint-Reads.js');
|
|
33
|
+
var doReadLite = require('./Meadow-Endpoint-ReadLiteList.js');
|
|
34
|
+
var doReadDistinct = require('./Meadow-Endpoint-ReadDistinctList.js');
|
|
35
|
+
var doCount = require('./Meadow-Endpoint-Count.js');
|
|
36
|
+
|
|
37
|
+
// Body keys hydrated onto pRequest.params so the delegated GET handlers see
|
|
38
|
+
// the same inputs they read from the URI.
|
|
39
|
+
var PARAM_KEYS = [ 'Filter', 'Begin', 'Cap', 'ExtraColumns', 'Columns' ];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the read mode from the request body flags, by precedence:
|
|
43
|
+
* Count > Distinct > Lite > Reads (the default).
|
|
44
|
+
*
|
|
45
|
+
* @param {Object} pBody - the parsed request body
|
|
46
|
+
*
|
|
47
|
+
* @return {String} one of 'Count', 'Distinct', 'Lite', 'Reads'
|
|
48
|
+
*/
|
|
49
|
+
var resolveMode = function(pBody)
|
|
50
|
+
{
|
|
51
|
+
if (pBody.Count)
|
|
52
|
+
{
|
|
53
|
+
return 'Count';
|
|
54
|
+
}
|
|
55
|
+
if (pBody.Distinct)
|
|
56
|
+
{
|
|
57
|
+
return 'Distinct';
|
|
58
|
+
}
|
|
59
|
+
if (pBody.Lite)
|
|
60
|
+
{
|
|
61
|
+
return 'Lite';
|
|
62
|
+
}
|
|
63
|
+
return 'Reads';
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
var doAPIQueryEndpoint = function(pRequest, pResponse, fNext)
|
|
67
|
+
{
|
|
68
|
+
var tmpBody = (pRequest.body && typeof(pRequest.body) === 'object') ? pRequest.body : {};
|
|
69
|
+
pRequest.params = (pRequest.params && typeof(pRequest.params) === 'object') ? pRequest.params : {};
|
|
70
|
+
|
|
71
|
+
for (var i = 0; i < PARAM_KEYS.length; i++)
|
|
72
|
+
{
|
|
73
|
+
if (typeof(tmpBody[PARAM_KEYS[i]]) !== 'undefined')
|
|
74
|
+
{
|
|
75
|
+
pRequest.params[PARAM_KEYS[i]] = tmpBody[PARAM_KEYS[i]];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
switch (resolveMode(tmpBody))
|
|
80
|
+
{
|
|
81
|
+
case 'Count':
|
|
82
|
+
return doCount(pRequest, pResponse, fNext);
|
|
83
|
+
case 'Distinct':
|
|
84
|
+
return doReadDistinct(pRequest, pResponse, fNext);
|
|
85
|
+
case 'Lite':
|
|
86
|
+
return doReadLite(pRequest, pResponse, fNext);
|
|
87
|
+
case 'Reads':
|
|
88
|
+
default:
|
|
89
|
+
return doReads(pRequest, pResponse, fNext);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
module.exports = doAPIQueryEndpoint;
|
|
@@ -588,6 +588,102 @@ suite
|
|
|
588
588
|
}
|
|
589
589
|
);
|
|
590
590
|
test
|
|
591
|
+
(
|
|
592
|
+
'query: reads all records via JSON body (default mode)',
|
|
593
|
+
function(fDone)
|
|
594
|
+
{
|
|
595
|
+
libSuperTest('http://localhost:9080/')
|
|
596
|
+
.post('1.0/FableTests/Query')
|
|
597
|
+
.send({})
|
|
598
|
+
.end(
|
|
599
|
+
function (pError, pResponse)
|
|
600
|
+
{
|
|
601
|
+
var tmpResults = JSON.parse(pResponse.text);
|
|
602
|
+
Expect(tmpResults).to.be.an('array');
|
|
603
|
+
Expect(tmpResults.length).to.equal(6);
|
|
604
|
+
fDone();
|
|
605
|
+
}
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
);
|
|
609
|
+
test
|
|
610
|
+
(
|
|
611
|
+
'query: reads with filter in the body',
|
|
612
|
+
function(fDone)
|
|
613
|
+
{
|
|
614
|
+
libSuperTest('http://localhost:9080/')
|
|
615
|
+
.post('1.0/FableTests/Query')
|
|
616
|
+
.send({ Filter: 'FBV~Type~EQ~Dog' })
|
|
617
|
+
.end(
|
|
618
|
+
function (pError, pResponse)
|
|
619
|
+
{
|
|
620
|
+
var tmpResults = JSON.parse(pResponse.text);
|
|
621
|
+
Expect(tmpResults).to.be.an('array');
|
|
622
|
+
Expect(tmpResults.length).to.equal(2);
|
|
623
|
+
Expect(tmpResults[0].Type).to.equal('Dog');
|
|
624
|
+
fDone();
|
|
625
|
+
}
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
);
|
|
629
|
+
test
|
|
630
|
+
(
|
|
631
|
+
'query: Lite read via boolean flag with pagination',
|
|
632
|
+
function(fDone)
|
|
633
|
+
{
|
|
634
|
+
libSuperTest('http://localhost:9080/')
|
|
635
|
+
.post('1.0/FableTests/Query')
|
|
636
|
+
.send({ Lite: true, Begin: 0, Cap: 3 })
|
|
637
|
+
.end(
|
|
638
|
+
function (pError, pResponse)
|
|
639
|
+
{
|
|
640
|
+
var tmpResults = JSON.parse(pResponse.text);
|
|
641
|
+
Expect(tmpResults).to.be.an('array');
|
|
642
|
+
Expect(tmpResults.length).to.equal(3);
|
|
643
|
+
fDone();
|
|
644
|
+
}
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
test
|
|
649
|
+
(
|
|
650
|
+
'query: Distinct read via boolean flag and Columns',
|
|
651
|
+
function(fDone)
|
|
652
|
+
{
|
|
653
|
+
libSuperTest('http://localhost:9080/')
|
|
654
|
+
.post('1.0/FableTests/Query')
|
|
655
|
+
.send({ Distinct: true, Columns: 'Type' })
|
|
656
|
+
.end(
|
|
657
|
+
function (pError, pResponse)
|
|
658
|
+
{
|
|
659
|
+
var tmpResults = JSON.parse(pResponse.text);
|
|
660
|
+
Expect(tmpResults).to.be.an('array');
|
|
661
|
+
Expect(tmpResults.length).to.be.at.least(1);
|
|
662
|
+
fDone();
|
|
663
|
+
}
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
);
|
|
667
|
+
test
|
|
668
|
+
(
|
|
669
|
+
'query: Count flag takes precedence and honors the filter',
|
|
670
|
+
function(fDone)
|
|
671
|
+
{
|
|
672
|
+
libSuperTest('http://localhost:9080/')
|
|
673
|
+
.post('1.0/FableTests/Query')
|
|
674
|
+
.send({ Lite: true, Count: true, Filter: 'FBV~Type~EQ~Dog' })
|
|
675
|
+
.end(
|
|
676
|
+
function (pError, pResponse)
|
|
677
|
+
{
|
|
678
|
+
var tmpResults = JSON.parse(pResponse.text);
|
|
679
|
+
Expect(tmpResults).to.have.property('Count');
|
|
680
|
+
Expect(tmpResults.Count).to.equal(2);
|
|
681
|
+
fDone();
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
);
|
|
686
|
+
test
|
|
591
687
|
(
|
|
592
688
|
'readsLiteExtended: get all records',
|
|
593
689
|
function(fDone)
|