meadow-endpoints 3.0.7 → 4.0.2

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.
Files changed (127) hide show
  1. package/Dockerfile_LUXURYCode +1 -1
  2. package/README.md +48 -14
  3. package/debug/Animal.json +62 -0
  4. package/debug/Harness-Configuration.json +31 -0
  5. package/debug/Harness.js +7 -108
  6. package/debug/KillHarness.sh +10 -0
  7. package/dist/meadowendpoints.js +4402 -0
  8. package/dist/meadowendpoints.min.js +92 -0
  9. package/dist/meadowendpoints.min.js.map +1 -0
  10. package/gulpfile.js +83 -0
  11. package/package.json +27 -15
  12. package/source/Meadow-Endpoints-Browser-Shim.js +14 -0
  13. package/source/Meadow-Endpoints.js +176 -565
  14. package/source/controller/Meadow-Endpoints-Controller-Base.js +161 -0
  15. package/source/controller/components/Meadow-Endpoints-Controller-BehaviorInjection.js +125 -0
  16. package/source/controller/components/Meadow-Endpoints-Controller-Error-StatusCodes.txt +189 -0
  17. package/source/controller/components/Meadow-Endpoints-Controller-Error.js +118 -0
  18. package/source/controller/components/Meadow-Endpoints-Controller-Log.js +103 -0
  19. package/source/controller/utility/Meadow-Endpoints-Filter-Parser.js +225 -0
  20. package/source/controller/utility/Meadow-Endpoints-Session-Marshaler.js +48 -0
  21. package/source/controller/utility/Meadow-Endpoints-Stream-RecordArray.js +66 -0
  22. package/source/endpoints/count/Meadow-Endpoint-Count.js +49 -0
  23. package/source/endpoints/count/Meadow-Endpoint-CountBy.js +40 -0
  24. package/source/endpoints/create/Meadow-Endpoint-BulkCreate.js +53 -0
  25. package/source/endpoints/create/Meadow-Endpoint-Create.js +58 -0
  26. package/source/endpoints/create/Meadow-Operation-Create.js +83 -0
  27. package/source/endpoints/delete/Meadow-Endpoint-Delete.js +93 -0
  28. package/source/endpoints/delete/Meadow-Endpoint-Undelete.js +108 -0
  29. package/source/endpoints/read/Meadow-Endpoint-Read.js +72 -0
  30. package/source/endpoints/read/Meadow-Endpoint-ReadDistinctList.js +92 -0
  31. package/source/endpoints/read/Meadow-Endpoint-ReadLiteList.js +85 -0
  32. package/source/endpoints/read/Meadow-Endpoint-ReadMax.js +55 -0
  33. package/source/endpoints/read/Meadow-Endpoint-ReadSelectList.js +89 -0
  34. package/source/endpoints/read/Meadow-Endpoint-Reads.js +75 -0
  35. package/source/endpoints/read/Meadow-Endpoint-ReadsBy.js +100 -0
  36. package/source/{crud → endpoints/read}/Meadow-Marshal-DistinctList.js +4 -13
  37. package/source/{crud → endpoints/read}/Meadow-Marshal-LiteList.js +5 -14
  38. package/source/endpoints/schema/Meadow-Endpoint-New.js +36 -0
  39. package/source/endpoints/schema/Meadow-Endpoint-Schema.js +36 -0
  40. package/source/endpoints/schema/Meadow-Endpoint-Validate.js +41 -0
  41. package/source/endpoints/update/Meadow-Endpoint-BulkUpdate.js +50 -0
  42. package/source/endpoints/update/Meadow-Endpoint-Update.js +58 -0
  43. package/source/endpoints/update/Meadow-Operation-Update.js +115 -0
  44. package/source/endpoints/upsert/Meadow-Endpoint-BulkUpsert.js +52 -0
  45. package/source/endpoints/upsert/Meadow-Endpoint-Upsert.js +57 -0
  46. package/source/endpoints/upsert/Meadow-Operation-Upsert.js +137 -0
  47. package/test/MeadowEndpoints_basic_tests.js +50 -2408
  48. package/test_support/bookstore-api-endpoint-exercises.paw +0 -0
  49. package/test_support/bookstore-configuration.json +28 -0
  50. package/test_support/bookstore-import-books-run.js +1 -0
  51. package/test_support/bookstore-import-books.js +215 -0
  52. package/test_support/bookstore-serve-meadow-endpoint-apis-IPC.js +138 -0
  53. package/test_support/bookstore-serve-meadow-endpoint-apis-run.js +6 -0
  54. package/test_support/bookstore-serve-meadow-endpoint-apis.js +129 -0
  55. package/test_support/data/books.csv +10001 -0
  56. package/test_support/model/ddl/BookStore.ddl +66 -0
  57. package/test_support/model/generated_diagram/README.md +1 -0
  58. package/test_support/model/generated_diagram/Stricture_Output.dot +13 -0
  59. package/test_support/model/generated_diagram/Stricture_Output.png +0 -0
  60. package/test_support/model/generated_documentation/Dictionary.md +18 -0
  61. package/test_support/model/generated_documentation/Model-Author.md +20 -0
  62. package/test_support/model/generated_documentation/Model-Book.md +26 -0
  63. package/test_support/model/generated_documentation/Model-BookAuthorJoin.md +14 -0
  64. package/test_support/model/generated_documentation/Model-BookPrice.md +25 -0
  65. package/test_support/model/generated_documentation/Model-Review.md +22 -0
  66. package/test_support/model/generated_documentation/ModelChangeTracking.md +17 -0
  67. package/test_support/model/generated_documentation/README.md +1 -0
  68. package/test_support/model/manual_scripts/DropTables.sql +5 -0
  69. package/test_support/model/manual_scripts/README.md +2 -0
  70. package/test_support/model/sql_create/BookStore-CreateDatabase.mysql.sql +116 -0
  71. package/test_support/model/sql_create/README.md +1 -0
  72. package/test_support/test_old/Tests.js +3243 -0
  73. package/test_support/test_old/untitled.js +88 -0
  74. package/source/Meadow-Authenticator.js +0 -31
  75. package/source/Meadow-Authorizers.js +0 -214
  76. package/source/Meadow-BehaviorModifications.js +0 -170
  77. package/source/Meadow-CommonServices.js +0 -206
  78. package/source/Meadow-MarshallSessionData.js +0 -64
  79. package/source/Restify-RouteParser.js +0 -114
  80. package/source/authorizers/Meadow-Authorizer-Allow.js +0 -17
  81. package/source/authorizers/Meadow-Authorizer-Deny.js +0 -17
  82. package/source/authorizers/Meadow-Authorizer-Mine.js +0 -47
  83. package/source/authorizers/Meadow-Authorizer-MyCustomer.js +0 -48
  84. package/source/crud/Meadow-Endpoint-BulkCreate.js +0 -67
  85. package/source/crud/Meadow-Endpoint-BulkUpdate.js +0 -74
  86. package/source/crud/Meadow-Endpoint-BulkUpsert.js +0 -76
  87. package/source/crud/Meadow-Endpoint-Count.js +0 -93
  88. package/source/crud/Meadow-Endpoint-CountBy.js +0 -101
  89. package/source/crud/Meadow-Endpoint-Create.js +0 -77
  90. package/source/crud/Meadow-Endpoint-Delete.js +0 -139
  91. package/source/crud/Meadow-Endpoint-Read.js +0 -109
  92. package/source/crud/Meadow-Endpoint-ReadDistinctList.js +0 -146
  93. package/source/crud/Meadow-Endpoint-ReadLiteList.js +0 -139
  94. package/source/crud/Meadow-Endpoint-ReadMax.js +0 -86
  95. package/source/crud/Meadow-Endpoint-ReadSelectList.js +0 -145
  96. package/source/crud/Meadow-Endpoint-Reads.js +0 -129
  97. package/source/crud/Meadow-Endpoint-ReadsBy.js +0 -155
  98. package/source/crud/Meadow-Endpoint-Undelete.js +0 -161
  99. package/source/crud/Meadow-Endpoint-Update.js +0 -80
  100. package/source/crud/Meadow-Endpoint-Upsert.js +0 -78
  101. package/source/crud/Meadow-Operation-Create.js +0 -105
  102. package/source/crud/Meadow-Operation-Update.js +0 -145
  103. package/source/crud/Meadow-Operation-Upsert.js +0 -106
  104. package/source/crud/Meadow-StreamRecordArray.js +0 -45
  105. package/source/schema/Meadow-Endpoint-New.js +0 -37
  106. package/source/schema/Meadow-Endpoint-Schema.js +0 -37
  107. package/source/schema/Meadow-Endpoint-Validate.js +0 -43
  108. package/test/Animal.json +0 -140
  109. package/test/MeadowEndpoints_disabledAuth_tests.js +0 -1325
  110. package/test/MeadowEndpoints_trustedSession_tests.js +0 -1731
  111. package/test/load/artillery-low.yml +0 -10
  112. package/test/load/cloud9setup.sh +0 -25
  113. package/test/load/package.json +0 -19
  114. package/test/load/test-schema-initializedatabase.sql +0 -29
  115. package/test/load/test-schema.json +0 -119
  116. package/test/load/test-server.js +0 -157
  117. package/test/scripts/InitializeDatabase-C9.sql +0 -7
  118. /package/{test/schemas → test_support/model}/json_schema/BookStore-Extended.json +0 -0
  119. /package/{test/schemas → test_support/model}/json_schema/BookStore-PICT.json +0 -0
  120. /package/{test/schemas → test_support/model}/json_schema/BookStore.json +0 -0
  121. /package/{test/schemas → test_support/model}/json_schema/README.md +0 -0
  122. /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-Author.json +0 -0
  123. /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-Book.json +0 -0
  124. /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-BookAuthorJoin.json +0 -0
  125. /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-BookPrice.json +0 -0
  126. /package/{test/schemas → test_support/model}/meadow_schema/BookStore-MeadowSchema-Review.json +0 -0
  127. /package/{test/schemas → test_support/model}/meadow_schema/README.md +0 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Meadow Endpoint - Delete a Record
3
+ */
4
+ const doAPIEndpointDelete = function(pRequest, pResponse, fNext)
5
+ {
6
+ let tmpRequestState = this.initializeRequestState(pRequest, 'Delete');
7
+ let fBehaviorInjector = (pBehaviorHash) => { return (fStageComplete) => { this.BehaviorInjection.runBehavior(pBehaviorHash, this, pRequest, tmpRequestState, fStageComplete); }; };
8
+
9
+ tmpRequestState.IDRecord = 0;
10
+ tmpRequestState.RecordCount = { Count:0 };
11
+
12
+ this.waterfall(
13
+ [
14
+ (fStageComplete) =>
15
+ {
16
+ if (typeof(pRequest.params.IDRecord) === 'string')
17
+ {
18
+ tmpRequestState.IDRecord = pRequest.params.IDRecord;
19
+ }
20
+ else if (typeof(pRequest.body[this.DAL.defaultIdentifier]) === 'number')
21
+ {
22
+ tmpRequestState.IDRecord = pRequest.body[this.DAL.defaultIdentifier];
23
+ }
24
+ else if (typeof(pRequest.body[this.DAL.defaultIdentifier]) === 'string')
25
+ {
26
+ tmpRequestState.IDRecord = pRequest.body[this.DAL.defaultIdentifier];
27
+ }
28
+ // Although the Meadow delete behavior does allow multiple deletes, we require an identifier.
29
+ // If a developer wants bulk delete, it will require a custom endpoint.
30
+ if (tmpRequestState.IDRecord < 1)
31
+ {
32
+ return fStageComplete(this.ErrorHandler.getError('Record delete failure - a valid record ID is required in the passed-in record.', 500));
33
+ }
34
+ return fStageComplete();
35
+ },
36
+ (fStageComplete) =>
37
+ {
38
+ tmpRequestState.Query = this.DAL.query;
39
+ tmpRequestState.Query.addFilter(this.DAL.defaultIdentifier, tmpRequestState.IDRecord);
40
+ tmpRequestState.Query.setIDUser(tmpRequestState.SessionData.UserID);
41
+ return fStageComplete();
42
+ },
43
+ (fStageComplete) =>
44
+ {
45
+ return this.BehaviorInjection.runBehavior(`Delete-QueryConfiguration`, this, pRequest, tmpRequestState, fStageComplete);
46
+ },
47
+ (fStageComplete) =>
48
+ {
49
+ // Load the record so we can do security checks on it
50
+ this.DAL.doRead(tmpRequestState.Query,
51
+ (pError, pQuery, pRecord) =>
52
+ {
53
+ if (!pRecord)
54
+ {
55
+ return fStageComplete(this.ErrorHandler.getError('Record not found.', 404));
56
+ }
57
+ tmpRequestState.Record = pRecord;
58
+ return fStageComplete();
59
+ });
60
+ },
61
+ (fStageComplete) =>
62
+ {
63
+ return this.BehaviorInjection.runBehavior(`Delete-PreOperation`, this, pRequest, tmpRequestState, fStageComplete);
64
+ },
65
+ (fStageComplete) =>
66
+ {
67
+ // Do the delete
68
+ this.DAL.doDelete(tmpRequestState.Query,
69
+ (pError, pQuery, pCount) =>
70
+ {
71
+ // MySQL returns the number of rows deleted
72
+ tmpRequestState.RecordCount.Count = pCount;
73
+ return fStageComplete(pError);
74
+ });
75
+ },
76
+ (fStageComplete) =>
77
+ {
78
+ return this.BehaviorInjection.runBehavior(`Delete-PostOperation`, this, pRequest, tmpRequestState, fStageComplete);
79
+ },
80
+ (fStageComplete) =>
81
+ {
82
+ pResponse.send(tmpRequestState.RecordCount);
83
+ this.log.requestCompletedSuccessfully(pRequest, tmpRequestState, `Deleted ${tmpRequestState.RecordCount.Count} ${this.DAL.scope} records with ID ${tmpRequestState.IDRecord}`);
84
+ return fStageComplete();
85
+ }
86
+ ], (pError) =>
87
+ {
88
+ return this.ErrorHandler.handleErrorIfSet(pRequest, tmpRequestState, pResponse, pError, fNext);
89
+ }
90
+ );
91
+ };
92
+
93
+ module.exports = doAPIEndpointDelete;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Meadow Endpoint - Undelete a Record
3
+ */
4
+ const doAPIEndpointUndelete = function(pRequest, pResponse, fNext)
5
+ {
6
+ let tmpRequestState = this.initializeRequestState(pRequest, 'Undelete');
7
+ let fBehaviorInjector = (pBehaviorHash) => { return (fStageComplete) => { this.BehaviorInjection.runBehavior(pBehaviorHash, this, pRequest, tmpRequestState, fStageComplete); }; };
8
+
9
+ var tmpIDRecord = 0;
10
+ if (typeof(pRequest.params.IDRecord) === 'string')
11
+ {
12
+ tmpIDRecord = pRequest.params.IDRecord;
13
+ }
14
+ else if (typeof(pRequest.body[this.DAL.defaultIdentifier]) === 'number')
15
+ {
16
+ tmpIDRecord = pRequest.body[this.DAL.defaultIdentifier];
17
+ }
18
+ else if (typeof(pRequest.body[this.DAL.defaultIdentifier]) === 'string')
19
+ {
20
+ tmpIDRecord = pRequest.body[this.DAL.defaultIdentifier];
21
+ }
22
+ // Although the undelete request does allow multiple undeletes, we require an identifier.
23
+ // TODO: Decide if we want to keep this pattern similar to Delete, or, if we want to change it to allow bulk undeletes.
24
+ if (tmpIDRecord < 1)
25
+ {
26
+ return fStageComplete(this.ErrorHandler.getError('Record undelete failure - a valid record ID is required.', 500));
27
+ }
28
+
29
+ tmpRequestState.RecordCount = {Count:0};
30
+
31
+ this.waterfall(
32
+ [
33
+ (fStageComplete) =>
34
+ {
35
+ // Validate that the schema has a deleted bit
36
+ var tmpSchema = this.DAL.schema;
37
+ var tmpHasDeletedBit = false;
38
+ for (let i = 0; i < tmpSchema.length; i++)
39
+ {
40
+ if (tmpSchema[i].Type == 'Deleted')
41
+ {
42
+ tmpHasDeletedBit = true;
43
+ }
44
+ }
45
+
46
+ if (!tmpHasDeletedBit)
47
+ {
48
+ return fStageComplete(this.ErrorHandler.getError('No undelete bit on record.', 500));
49
+ }
50
+
51
+ return fStageComplete();
52
+ },
53
+ (fStageComplete) =>
54
+ {
55
+ // Now see if the record, with this identifier, for this user, exists with the deleted bit set to 1
56
+ tmpRequestState.Query = this.DAL.query;
57
+ tmpRequestState.Query.addFilter(this.DAL.defaultIdentifier, tmpIDRecord);
58
+ tmpRequestState.Query.addFilter('Deleted', 1);
59
+ tmpRequestState.Query.setIDUser(tmpRequestState.SessionData.UserID);
60
+ return fStageComplete();
61
+ },
62
+ (fStageComplete) =>
63
+ {
64
+ // Load the record so we can do security checks on it
65
+ this.DAL.doRead(tmpRequestState.Query,
66
+ (pError, pQuery, pRecord) =>
67
+ {
68
+ if (!pRecord)
69
+ {
70
+ return fStageComplete(this.ErrorHandler.getError('Record not found.', 404));
71
+ }
72
+ tmpRequestState.Record = pRecord;
73
+ return fStageComplete();
74
+ });
75
+ },
76
+ (fStageComplete) =>
77
+ {
78
+ return this.BehaviorInjection.runBehavior(`Undelete-PreOperation`, this, pRequest, tmpRequestState, fStageComplete);
79
+ },
80
+ (fStageComplete) =>
81
+ {
82
+ // Do the undelete
83
+ this.DAL.doUndelete(tmpRequestState.Query,
84
+ (pError, pQuery, pCount) =>
85
+ {
86
+ // MySQL returns the number of rows deleted
87
+ tmpRequestState.RecordCount = {Count:pCount};
88
+ return fStageComplete(pError);
89
+ });
90
+ },
91
+ (fStageComplete) =>
92
+ {
93
+ return this.BehaviorInjection.runBehavior(`Undelete-PostOperation`, this, pRequest, tmpRequestState, fStageComplete);
94
+ },
95
+ (fStageComplete) =>
96
+ {
97
+ pResponse.send(tmpRequestState.RecordCount);
98
+ this.log.requestCompletedSuccessfully(pRequest, tmpRequestState, 'Undeleted '+tmpRequestState.RecordCount.Count+' records with ID '+tmpIDRecord+'.');
99
+ return fStageComplete();
100
+ }
101
+ ], (pError) =>
102
+ {
103
+ return this.ErrorHandler.handleErrorIfSet(pRequest, tmpRequestState, pResponse, pError, fNext);
104
+ }
105
+ );
106
+ };
107
+
108
+ module.exports = doAPIEndpointUndelete;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Meadow Endpoint - Read a Record
3
+ */
4
+ const doAPIEndpointRead = function(pRequest, pResponse, fNext)
5
+ {
6
+ let tmpRequestState = this.initializeRequestState(pRequest, 'Read');
7
+ let fBehaviorInjector = (pBehaviorHash) => { return (fStageComplete) => { this.BehaviorInjection.runBehavior(pBehaviorHash, this, pRequest, tmpRequestState, fStageComplete); }; };
8
+
9
+ this.waterfall(
10
+ [
11
+ (fStageComplete) =>
12
+ {
13
+ tmpRequestState.Query = this.DAL.query;
14
+ return fStageComplete();
15
+ },
16
+ fBehaviorInjector(`Read-PreOperation`),
17
+ (fStageComplete) =>
18
+ {
19
+ if (!pRequest.params.IDRecord && pRequest.params.GUIDRecord)
20
+ {
21
+ // We use a custom name for this (RequestDefaultIdentifier) in case there is a query with a dot in the default identifier.
22
+ tmpRequestState.RecordSearchCriteria = `${this.DAL.defaultGUIdentifier} = ${pRequest.params.GUIDRecord}`;
23
+ tmpRequestState.Query.addFilter(this.DAL.defaultGUIdentifier, pRequest.params.GUIDRecord, '=', 'AND', 'RequestDefaultIdentifier');
24
+ }
25
+ else if (pRequest.params.IDRecord)
26
+ {
27
+ // We use a custon name for this (RequestDefaultIdentifier) in case there is a query with a dot in the default identifier.
28
+ tmpRequestState.RecordSearchCriteria = `${this.DAL.defaultIdentifier} = ${pRequest.params.IDRecord}`;
29
+ tmpRequestState.Query.addFilter(this.DAL.defaultIdentifier, pRequest.params.IDRecord, '=', 'AND', 'RequestDefaultIdentifier');
30
+ }
31
+ else
32
+ {
33
+ return fStageComplete(this.ErrorHandler.getError('No ID Provided', 400));
34
+ }
35
+ return fStageComplete();
36
+ },
37
+ fBehaviorInjector(`Read-QueryConfiguration`),
38
+ (fStageComplete) =>
39
+ {
40
+ try
41
+ {
42
+ this.DAL.doRead(tmpRequestState.Query, (pError, pQuery, pRecord) =>
43
+ {
44
+ if (!pRecord)
45
+ {
46
+ return fStageComplete(this.ErrorHandler.getError('Record not Found', 404));
47
+ }
48
+ tmpRequestState.Record = pRecord;
49
+ return fStageComplete();
50
+ });
51
+ }
52
+ catch (pQueryError)
53
+ {
54
+ return fStageComplete(pQueryError);
55
+ }
56
+ },
57
+ fBehaviorInjector(`Read-PostOperation`),
58
+ (fStageComplete) =>
59
+ {
60
+ pResponse.send(tmpRequestState.Record);
61
+ this.log.requestCompletedSuccessfully(pRequest, tmpRequestState, `Read Record Where ${tmpRequestState.RecordSearchCriteria}`);
62
+ return fStageComplete();
63
+ }
64
+ ],
65
+ (pError) =>
66
+ {
67
+ return this.ErrorHandler.handleErrorIfSet(pRequest, tmpRequestState, pResponse, pError, fNext);
68
+ }
69
+ );
70
+ };
71
+
72
+ module.exports = doAPIEndpointRead;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Meadow Endpoint - Read a list of Records with a specified set of columns, distinct by those columns.
3
+ */
4
+ const marshalDistinctList = require('./Meadow-Marshal-DistinctList.js');
5
+
6
+ const doAPIEndpointReadDistinct = function(pRequest, pResponse, fNext)
7
+ {
8
+ let tmpRequestState = this.initializeRequestState(pRequest, 'ReadDistinct');
9
+ let fBehaviorInjector = (pBehaviorHash) => { return (fStageComplete) => { this.BehaviorInjection.runBehavior(pBehaviorHash, this, pRequest, tmpRequestState, fStageComplete); }; };
10
+
11
+ tmpRequestState.DistinctColumns;
12
+
13
+ this.waterfall(
14
+ [
15
+ (fStageComplete) =>
16
+ {
17
+ tmpRequestState.Query = this.DAL.query.setDistinct(true);
18
+
19
+ let tmpCap = false;
20
+ let tmpBegin = false;
21
+ if (typeof(pRequest.params.Begin) === 'string' ||
22
+ typeof(pRequest.params.Begin) === 'number')
23
+ {
24
+ tmpBegin = parseInt(pRequest.params.Begin, 10);
25
+ }
26
+ if (typeof(pRequest.params.Cap) === 'string' ||
27
+ typeof(pRequest.params.Cap) === 'number')
28
+ {
29
+ tmpCap = parseInt(pRequest.params.Cap, 10);
30
+ }
31
+ else
32
+ {
33
+ //maximum number of records to return by default on Read queries. Override via "MeadowDefaultMaxCap" fable setting.
34
+ tmpCap = (this.settings['MeadowDefaultMaxCap']) || 250;
35
+ }
36
+ tmpRequestState.Query.setCap(tmpCap).setBegin(tmpBegin);
37
+ if (typeof(pRequest.params.Filter) === 'string')
38
+ {
39
+ // If a filter has been passed in, parse it and add the values to the query.
40
+ this.parseFilter(pRequest.params.Filter, tmpRequestState.Query);
41
+ }
42
+ else if (pRequest.params.Filter)
43
+ {
44
+ tmpRequestState.Query.setFilter(pRequest.params.Filter);
45
+ }
46
+ if (typeof(pRequest.params.Columns) === 'string')
47
+ {
48
+ tmpRequestState.DistinctColumns = pRequest.params.Columns.split(',');
49
+ if (!tmpRequestState.DistinctColumns)
50
+ {
51
+ return fStageComplete({Code:400, Message:'Columns to distinct on must be provided.'});
52
+ }
53
+ tmpRequestState.Query.setDataElements(tmpRequestState.DistinctColumns);
54
+ }
55
+ return fStageComplete();
56
+ },
57
+ fBehaviorInjector(`Reads-QueryConfiguration`),
58
+ (fStageComplete) =>
59
+ {
60
+ this.DAL.doReads(tmpRequestState.Query, fStageComplete);
61
+ },
62
+ (pQuery, pRecords, fStageComplete) =>
63
+ {
64
+ if (pRecords.length < 1)
65
+ {
66
+ pRecords = [];
67
+ }
68
+ tmpRequestState.Records = pRecords;
69
+ return fStageComplete();
70
+ },
71
+ (fStageComplete) =>
72
+ {
73
+ tmpRequestState.ResultRecords = marshalDistinctList.call(this, tmpRequestState.Records, pRequest, tmpRequestState.DistinctColumns);
74
+ return fStageComplete();
75
+ },
76
+ (fStageComplete) =>
77
+ {
78
+ return this.doStreamRecordArray(pResponse, tmpRequestState.ResultRecords, fStageComplete);
79
+ },
80
+ (fStageComplete) =>
81
+ {
82
+ this.log.requestCompletedSuccessfully(pRequest, tmpRequestState, `Read a recordset distinct lite list with ${tmpRequestState.ResultRecords.length} results.`);
83
+ return fStageComplete();
84
+ }
85
+ ],
86
+ (pError) =>
87
+ {
88
+ return this.ErrorHandler.handleErrorIfSet(pRequest, tmpRequestState, pResponse, pError, fNext);
89
+ });
90
+ };
91
+
92
+ module.exports = doAPIEndpointReadDistinct;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Meadow Endpoint - Read a list of lite Records (for Drop-downs and such)
3
+ */
4
+ const marshalLiteList = require('./Meadow-Marshal-LiteList.js');
5
+
6
+ const doAPIEndpointReadLite = function(pRequest, pResponse, fNext)
7
+ {
8
+ let tmpRequestState = this.initializeRequestState(pRequest, 'ReadsLite');
9
+ let fBehaviorInjector = (pBehaviorHash) => { return (fStageComplete) => { this.BehaviorInjection.runBehavior(pBehaviorHash, this, pRequest, tmpRequestState, fStageComplete); }; };
10
+
11
+ this.waterfall(
12
+ [
13
+ // 1a. Get the records
14
+ (fStageComplete) =>
15
+ {
16
+ tmpRequestState.Query = this.DAL.query;
17
+ // TODO: Limit the query to the columns we need for the templated expression
18
+
19
+ var tmpCap = false;
20
+ var tmpBegin = false;
21
+ if (typeof(pRequest.params.Begin) === 'string' ||
22
+ typeof(pRequest.params.Begin) === 'number')
23
+ {
24
+ tmpBegin = parseInt(pRequest.params.Begin, 10);
25
+ }
26
+ if (typeof(pRequest.params.Cap) === 'string' ||
27
+ typeof(pRequest.params.Cap) === 'number')
28
+ {
29
+ tmpCap = parseInt(pRequest.params.Cap, 10);
30
+ }
31
+ else
32
+ {
33
+ //maximum number of records to return by default on Read queries. Override via "MeadowDefaultMaxCap" fable setting.
34
+ tmpCap = (this.settings['MeadowDefaultMaxCap']) || 250;
35
+ }
36
+ tmpRequestState.Query.setCap(tmpCap).setBegin(tmpBegin);
37
+ if (typeof(pRequest.params.Filter) === 'string')
38
+ {
39
+ // If a filter has been passed in, parse it and add the values to the query.
40
+ this.parseFilter(pRequest.params.Filter, tmpRequestState.Query);
41
+ }
42
+ else if (pRequest.params.Filter)
43
+ {
44
+ tmpRequestState.Query.setFilter(pRequest.params.Filter);
45
+ }
46
+
47
+ return fStageComplete();
48
+ },
49
+ fBehaviorInjector(`Reads-QueryConfiguration`),
50
+ (fStageComplete) =>
51
+ {
52
+ this.DAL.doReads(tmpRequestState.Query, fStageComplete);
53
+ },
54
+ (pQuery, pRecords, fStageComplete) =>
55
+ {
56
+ if (pRecords.length < 1)
57
+ {
58
+ pRecords = [];
59
+ }
60
+ tmpRequestState.RawRecords = pRecords;
61
+ return fStageComplete();
62
+ },
63
+ (fStageComplete) =>
64
+ {
65
+ tmpRequestState.Records = marshalLiteList.call(this, tmpRequestState.RawRecords, pRequest, (typeof(pRequest.params.ExtraColumns) === 'string') ? pRequest.params.ExtraColumns.split(',') : []);
66
+ return fStageComplete();
67
+ },
68
+ (fStageComplete) =>
69
+ {
70
+ return this.doStreamRecordArray(pResponse, tmpRequestState.Records, fNext);
71
+ },
72
+ (fStageComplete) =>
73
+ {
74
+ this.log.requestCompletedSuccessfully(pRequest, tmpRequestState, `Read a recordset lite list with ${tmpRequestState.Records.length} results`);
75
+ return fStageComplete();
76
+ }
77
+ ],
78
+ (pError, pResultRecords) =>
79
+ {
80
+ return this.ErrorHandler.handleErrorIfSet(pRequest, tmpRequestState, pResponse, pError, fNext);
81
+ }
82
+ );
83
+ };
84
+
85
+ module.exports = doAPIEndpointReadLite;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Meadow Endpoint - Read the Max Value of a Column in a Set
3
+ */
4
+ const doAPIEndpointReadMax = function(pRequest, pResponse, fNext)
5
+ {
6
+ let tmpRequestState = this.initializeRequestState(pRequest, 'ReadMax');
7
+ let fBehaviorInjector = (pBehaviorHash) => { return (fStageComplete) => { this.BehaviorInjection.runBehavior(pBehaviorHash, this, pRequest, tmpRequestState, fStageComplete); }; };
8
+
9
+ this.waterfall(
10
+ [
11
+ (fStageComplete) =>
12
+ {
13
+ tmpRequestState.Query = this.DAL.query;
14
+ return fStageComplete();
15
+ },
16
+ (fStageComplete) =>
17
+ {
18
+ tmpRequestState.ColumnName = pRequest.params.ColumnName;
19
+ tmpRequestState.Query.setSort({Column:tmpRequestState.ColumnName, Direction:'Descending'});
20
+ tmpRequestState.Query.setCap(1);
21
+
22
+ return fStageComplete();
23
+ },
24
+ fBehaviorInjector(`ReadMax-QueryConfiguration`),
25
+ (fStageComplete) =>
26
+ {
27
+ this.DAL.doRead(tmpRequestState.Query, fStageComplete);
28
+ },
29
+ (pQuery, pRecord, fStageComplete) =>
30
+ {
31
+ if (!pRecord)
32
+ {
33
+ return fStageComplete(this.ErrorHandler.getError('Record not Found', 404));
34
+ }
35
+ tmpRequestState.Record = pRecord;
36
+ return fStageComplete();
37
+ },
38
+ (fStageComplete) =>
39
+ {
40
+ this.BehaviorInjection.runBehavior(`ReadMax-PostOperation`, this, pRequest, tmpRequestState, fStageComplete);
41
+ },
42
+ (fStageComplete) =>
43
+ {
44
+ this.log.requestCompletedSuccessfully(pRequest, tmpRequestState, `Read max record of ${this.DAL.scope} on ${tmpRequestState.ColumnName}`);
45
+ pResponse.send(tmpRequestState.Record);
46
+ }
47
+ ],
48
+ (pError) =>
49
+ {
50
+ return this.ErrorHandler.handleErrorIfSet(pRequest, tmpRequestState, pResponse, pError, fNext);
51
+ }
52
+ );
53
+ };
54
+
55
+ module.exports = doAPIEndpointReadMax;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Meadow Endpoint - Read a select list of Records (for Drop-downs and such)
3
+ */
4
+ const doAPIEndpointReadSelectList = function(pRequest, pResponse, fNext)
5
+ {
6
+ let tmpRequestState = this.initializeRequestState(pRequest, 'ReadsBy');
7
+ let fBehaviorInjector = (pBehaviorHash) => { return (fStageComplete) => { this.BehaviorInjection.runBehavior(pBehaviorHash, this, pRequest, tmpRequestState, fStageComplete); }; };
8
+
9
+ this.waterfall(
10
+ [
11
+ (fStageComplete) =>
12
+ {
13
+ tmpRequestState.Query = this.DAL.query;
14
+
15
+ var tmpCap = false;
16
+ var tmpBegin = false;
17
+ if (typeof(pRequest.params.Begin) === 'string' ||
18
+ typeof(pRequest.params.Begin) === 'number')
19
+ {
20
+ tmpBegin = parseInt(pRequest.params.Begin);
21
+ }
22
+ if (typeof(pRequest.params.Cap) === 'string' ||
23
+ typeof(pRequest.params.Cap) === 'number')
24
+ {
25
+ tmpCap = parseInt(pRequest.params.Cap);
26
+ }
27
+ else
28
+ {
29
+ tmpCap = (this.settings['MeadowDefaultMaxCap']) || 250;
30
+ }
31
+ tmpRequestState.Query.setCap(tmpCap).setBegin(tmpBegin);
32
+ if (typeof(pRequest.params.Filter) === 'string')
33
+ {
34
+ this.parseFilter(pRequest.params.Filter, tmpRequestState.Query);
35
+ }
36
+
37
+ return fStageComplete();
38
+ },
39
+ fBehaviorInjector(`Reads-QueryConfiguration`),
40
+ (fStageComplete) =>
41
+ {
42
+ this.DAL.doReads(tmpRequestState.Query, fStageComplete);
43
+ },
44
+ (pQuery, pRecords, fStageComplete) =>
45
+ {
46
+ if (pRecords.length < 1)
47
+ {
48
+ pRecords = [];
49
+ }
50
+
51
+ tmpRequestState.Records = pRecords;
52
+
53
+ return fStageComplete();
54
+ },
55
+ (fStageComplete) =>
56
+ {
57
+ tmpRequestState.SelectList = [];
58
+
59
+ for (var i = 0; i < tmpRequestState.Records.length; i++)
60
+ {
61
+ tmpRequestState.SelectList.push
62
+ (
63
+ {
64
+ Hash: tmpRequestState.Records[i][this.DAL.defaultIdentifier],
65
+ Value: this.BehaviorInjection.processTemplate('SelectList', {Record:tmpRequestState.Records[i]}, this.DAL.scope+' #<%= Record.'+this.DAL.defaultIdentifier+'%>')
66
+ }
67
+ );
68
+ }
69
+
70
+ return fStageComplete();
71
+ },
72
+ (fStageComplete) =>
73
+ {
74
+ return this.doStreamRecordArray(pResponse, tmpRequestState.SelectList, fStageComplete);
75
+ },
76
+ (fStageComplete) =>
77
+ {
78
+ this.log.requestCompletedSuccessfully(pRequest, tmpRequestState, `Read a recordset lite list with ${tmpRequestState.SelectList.length} results.`);
79
+ return fStageComplete();
80
+ }
81
+ ],
82
+ (pError, pResultRecords) =>
83
+ {
84
+ return this.ErrorHandler.handleErrorIfSet(pRequest, tmpRequestState, pResponse, pError, fNext);
85
+ }
86
+ );
87
+ };
88
+
89
+ module.exports = doAPIEndpointReadSelectList;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Meadow Endpoint - Read a Set of Records
3
+ */
4
+ const doAPIEndpointReads = function(pRequest, pResponse, fNext)
5
+ {
6
+ let tmpRequestState = this.initializeRequestState(pRequest, 'Reads');
7
+ let fBehaviorInjector = (pBehaviorHash) => { return (fStageComplete) => { this.BehaviorInjection.runBehavior(pBehaviorHash, this, pRequest, tmpRequestState, fStageComplete); }; };
8
+
9
+ this.waterfall(
10
+ [
11
+ (fStageComplete) =>
12
+ {
13
+ tmpRequestState.Query = this.DAL.query;
14
+
15
+ var tmpCap = false;
16
+ var tmpBegin = false;
17
+ if (typeof(pRequest.params.Begin) === 'string' ||
18
+ typeof(pRequest.params.Begin) === 'number')
19
+ {
20
+ tmpBegin = parseInt(pRequest.params.Begin);
21
+ }
22
+ if (typeof(pRequest.params.Cap) === 'string' ||
23
+ typeof(pRequest.params.Cap) === 'number')
24
+ {
25
+ tmpCap = parseInt(pRequest.params.Cap);
26
+ }
27
+ else
28
+ {
29
+ tmpCap = (this.settings['MeadowDefaultMaxCap']) || 250;
30
+ }
31
+ tmpRequestState.Query.setCap(tmpCap).setBegin(tmpBegin);
32
+ if (typeof(pRequest.params.Filter) === 'string')
33
+ {
34
+ // If a filter has been passed in, parse it and add the values to the query.
35
+ this.parseFilter(pRequest.params.Filter, tmpRequestState.Query);
36
+ }
37
+ else if (pRequest.params.Filter)
38
+ {
39
+ tmpRequestState.Query.setFilter(pRequest.params.Filter);
40
+ }
41
+
42
+ return fStageComplete();
43
+ },
44
+ fBehaviorInjector(`Reads-QueryConfiguration`),
45
+ (fStageComplete) =>
46
+ {
47
+ this.DAL.doReads(tmpRequestState.Query, fStageComplete);
48
+ },
49
+ (pQuery, pRecords, fStageComplete) =>
50
+ {
51
+ if (!pRecords)
52
+ {
53
+ return fStageComplete(this.ErrorHandler.getError('No records found.', 404));
54
+ }
55
+ tmpRequestState.Records = pRecords;
56
+ return fStageComplete();
57
+ },
58
+ fBehaviorInjector(`Reads-PostOperation`),
59
+ (fStageComplete) =>
60
+ {
61
+ this.doStreamRecordArray(pResponse, tmpRequestState.Records, fStageComplete);
62
+ },
63
+ (fStageComplete) =>
64
+ {
65
+ this.log.requestCompletedSuccessfully(pRequest, tmpRequestState, 'Read a list of records.');
66
+ return fStageComplete();
67
+ }
68
+ ],
69
+ (pError) =>
70
+ {
71
+ return this.ErrorHandler.handleErrorIfSet(pRequest, tmpRequestState, pResponse, pError, fNext);
72
+ });
73
+ };
74
+
75
+ module.exports = doAPIEndpointReads;