meadow-endpoints 3.0.7 → 4.0.3

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/Controller/Meadow-Endpoints-Controller-Base.js +161 -0
  13. package/source/Controller/components/Meadow-Endpoints-Controller-BehaviorInjection.js +125 -0
  14. package/source/Controller/components/Meadow-Endpoints-Controller-Error-StatusCodes.txt +189 -0
  15. package/source/Controller/components/Meadow-Endpoints-Controller-Error.js +118 -0
  16. package/source/Controller/components/Meadow-Endpoints-Controller-Log.js +103 -0
  17. package/source/Controller/utility/Meadow-Endpoints-Filter-Parser.js +225 -0
  18. package/source/Controller/utility/Meadow-Endpoints-Session-Marshaler.js +48 -0
  19. package/source/Controller/utility/Meadow-Endpoints-Stream-RecordArray.js +66 -0
  20. package/source/Meadow-Endpoints-Browser-Shim.js +14 -0
  21. package/source/Meadow-Endpoints.js +176 -565
  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 +53 -0
  45. package/source/endpoints/upsert/Meadow-Endpoint-Upsert.js +58 -0
  46. package/source/endpoints/upsert/Meadow-Operation-Upsert.js +132 -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,118 @@
1
+ class MeadowEndpointsControllerErrorBase
2
+ {
3
+ constructor(pController)
4
+ {
5
+ this._Controller = pController;
6
+ }
7
+
8
+ // Get the error object
9
+ getError(pMessage, pStatusCode, pSuppressSoftwareTrace)
10
+ {
11
+ let tmpError = new Error(pMessage);
12
+
13
+ // Default the error status code to 400 if none is passed
14
+ tmpError.StatusCode = (typeof(pStatusCode) == 'number') ? pStatusCode : 400;
15
+ // This suppresses the stack trace from being sent back or logged.
16
+ // And by default it does not send a stack trace, as we expect errors created this way to be protocol, schema or data related.
17
+ tmpError.SuppressSoftwareTrace = (typeof(pSuppressSoftwareTrace) != 'undefined') ? pSuppressSoftwareTrace : true;
18
+
19
+ return tmpError;
20
+ }
21
+
22
+ // Handle an error if set -- some errors don't send the response back because they aren't fully errory errors.
23
+ handleErrorIfSet(pRequest, pRequestState, pResponse, pError, fCallback)
24
+ {
25
+ if (pError)
26
+ {
27
+ return this.sendError(pRequest, pRequestState, pResponse, pError, fCallback);
28
+ }
29
+
30
+ return fCallback();
31
+ }
32
+
33
+ // Send an error object
34
+ sendError(pRequest, pRequestState, pResponse, pError, fCallback)
35
+ {
36
+ this._Controller.log.logRequestError(pRequest, pRequestState, pError);
37
+
38
+ // TODO: Detect if we've already sent headers?
39
+ if (!this._Controller.ControllerOptions.SendErrorStatusCodes)
40
+ {
41
+ let tmpStatusCode = (pError.hasOwnProperty('StatusCode')) ? pError.StatusCode : 500;
42
+ pResponse.status(tmpStatusCode);
43
+ }
44
+
45
+ let tmpResponseObject = (
46
+ {
47
+ Error:pError.message,
48
+ StatusCode:pError.StatusCode
49
+ });
50
+
51
+ tmpResponseObject = this._Controller.ErrorHandler.prepareRequestContextOutputObject(tmpResponseObject, pRequest, pRequestState, pError);
52
+
53
+ pResponse.send(tmpResponseObject);
54
+
55
+ fCallback(pError);
56
+ }
57
+
58
+ // This looks for some generic markers in the request state and puts them into a log or send object
59
+ prepareRequestContextOutputObject(pObjectToPopulate, pRequest, pRequestState, pError)
60
+ {
61
+ // Internally created errors supress stack traces
62
+ if (pError)
63
+ {
64
+ pObjectToPopulate.Error = pError.message;
65
+ pObjectToPopulate.Code = pError.code;
66
+ pObjectToPopulate.StatusCode = pError.StatusCode;
67
+
68
+ if (!pError.SuppressSoftwareTrace)
69
+ {
70
+ pObjectToPopulate.Stack = pError.stack;
71
+ }
72
+
73
+ if (pRequestState.hasOwnProperty('Record'))
74
+ {
75
+ pObjectToPopulate.Record = pRequestState.Record;
76
+ }
77
+
78
+ if (pRequestState.hasOwnProperty('Query') && (typeof(pRequestState.Query) == 'object'))
79
+ {
80
+ if (pRequestState.Query.query)
81
+ {
82
+ if (typeof(pRequestState.Query.query.body) == 'string')
83
+ {
84
+ pObjectToPopulate.Query = pRequestState.Query.query.body;
85
+ }
86
+
87
+ if ((typeof(pRequestState.Query.query.parameters) == 'object'))
88
+ {
89
+ pObjectToPopulate.QueryParameters = pRequestState.Query.query.parameters;
90
+
91
+ pObjectToPopulate.RebuiltQueryString = (typeof(pObjectToPopulate.Query) == 'string') ? pObjectToPopulate.Query : '';
92
+
93
+ // This gnarly bit of code attempts to reconstruct a non prepared string version of the query, to help.
94
+ let tmpQueryParameterSet = Object.keys(pObjectToPopulate.QueryParameters);
95
+ for (let i = 0; i < tmpQueryParameterSet.length; i++)
96
+ {
97
+ switch(typeof(tmpQueryParameterSet[i]))
98
+ {
99
+ case 'number':
100
+ pObjectToPopulate.RebuiltQueryString = pObjectToPopulate.RebuiltQueryString.replace(new RegExp(`:${tmpQueryParameterSet[i]}\\b`, 'g'), `'${pObjectToPopulate.QueryParameters[tmpQueryParameterSet[i]]}'`);
101
+ break;
102
+ case 'string':
103
+ // TODO: This may need more ... nuance...
104
+ default:
105
+ pObjectToPopulate.RebuiltQueryString = pObjectToPopulate.RebuiltQueryString.replace(new RegExp(`:${tmpQueryParameterSet[i]}\\b`,'g'), pObjectToPopulate.QueryParameters[tmpQueryParameterSet[i]]);
106
+ break;
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ return pObjectToPopulate;
115
+ }
116
+ }
117
+
118
+ module.exports = MeadowEndpointsControllerErrorBase;
@@ -0,0 +1,103 @@
1
+ class MeadowEndpointsControllerLogBase
2
+ {
3
+ constructor(pController)
4
+ {
5
+ this._Controller = pController;
6
+ }
7
+
8
+ // This is called for every successful request log line. Be careful what you add in overloads!
9
+ prepareLogData(pRequest, pRequestState, pLogData)
10
+ {
11
+ // TODO: Discuss if these should be configurations
12
+ if (pRequestState.hasOwnProperty('Record'))
13
+ {
14
+ if (pRequestState.Record.hasOwnProperty(this._Controller.DAL.defaultIdentifier))
15
+ {
16
+ pLogData[this._Controller.DAL.defaultIdentifier] = pRequestState.Record[this._Controller.DAL.defaultIdentifier];
17
+ }
18
+ if (pRequestState.Record.hasOwnProperty(this._Controller.DAL.defaultGUIdentifier))
19
+ {
20
+ pLogData[this._Controller.DAL.defaultGUIdentifier] = pRequestState.Record[this._Controller.DAL.defaultGUIdentifier];
21
+ }
22
+ }
23
+ if (pRequestState.hasOwnProperty('UpdatedRecords'))
24
+ {
25
+ pLogData.UpdatedRecordCount = pRequestState.UpdatedRecords.length;
26
+ }
27
+ if (pRequestState.hasOwnProperty('CreatedRecords'))
28
+ {
29
+ pLogData.UpdatedRecordCount = pRequestState.CreatedRecords.length;
30
+ }
31
+ if (pRequestState.hasOwnProperty('UpsertedRecords'))
32
+ {
33
+ pLogData.UpdatedRecordCount = pRequestState.UpsertedRecords.length;
34
+ }
35
+ return pLogData;
36
+ }
37
+
38
+ // This is called whenever an endpoint is completed successfully
39
+ requestCompletedSuccessfully(pRequest, pRequestState, pActionSummary)
40
+ {
41
+ let tmpLogData = (
42
+ {
43
+ SessionID: pRequestState.SessionData.SessionID,
44
+ RequestID: pRequest.RequestUUID,
45
+ RequestURL: pRequest.url,
46
+ Scope: this._Controller.DAL.scope,
47
+ Action: `${this._Controller.DAL.scope}-${pRequestState.Verb}`,
48
+ Verb: pRequestState.Verb
49
+ });
50
+
51
+ this._Controller.log.info(pActionSummary, this.prepareLogData(pRequest, pRequestState, tmpLogData));
52
+ }
53
+
54
+ // This is called whenever an endpoint is completed successfully
55
+ logRequestError(pRequest, pRequestState, pError)
56
+ {
57
+ let tmpErrorLogData = (
58
+ {
59
+ SessionID: pRequestState.SessionData.SessionID,
60
+ RequestID: pRequest.RequestUUID,
61
+ RequestURL: pRequest.url,
62
+ Scope: this._Controller.DAL.scope,
63
+ Action: `${this._Controller.DAL.scope}-${pRequestState.Verb}`,
64
+ Verb: pRequestState.Verb,
65
+ });
66
+
67
+ tmpErrorLogData = this._Controller.ErrorHandler.prepareRequestContextOutputObject(tmpErrorLogData, pRequest, pRequestState, pError);
68
+
69
+ this._Controller.log.error(pError.message, this.prepareLogData(pRequest, pRequestState, tmpErrorLogData));
70
+ }
71
+
72
+ trace(pLogText, pLogObject)
73
+ {
74
+ this._Controller.DAL.log.trace(pLogText, pLogObject);
75
+ }
76
+
77
+ debug(pLogText, pLogObject)
78
+ {
79
+ this._Controller.DAL.log.debug(pLogText, pLogObject);
80
+ }
81
+
82
+ info(pLogText, pLogObject)
83
+ {
84
+ this._Controller.DAL.log.info(pLogText, pLogObject);
85
+ }
86
+
87
+ warn(pLogText, pLogObject)
88
+ {
89
+ this._Controller.DAL.log.warn(pLogText, pLogObject);
90
+ }
91
+
92
+ error(pLogText, pLogObject)
93
+ {
94
+ this._Controller.DAL.log.error(pLogText, pLogObject);
95
+ }
96
+
97
+ fatal(pLogText, pLogObject)
98
+ {
99
+ this._Controller.DAL.log.fatal(pLogText, pLogObject);
100
+ }
101
+ }
102
+
103
+ module.exports = MeadowEndpointsControllerLogBase;
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Meadow Endpoint Utility Class - Parse a Filter String and put it into a Query.
3
+ *
4
+ * @license MIT
5
+ *
6
+ * @author Steven Velozo <steven@velozo.com>
7
+ * @module Meadow
8
+ */
9
+ /**
10
+ * Parse GET-passed Filter Strings, turn the results into proper Meadow query stanzas
11
+
12
+ Take the filter and return an array of filter instructions
13
+ Basic instruction anatomy:
14
+ INSTRUCTION~FIELD~OPERATOR~VALUE
15
+ FOP - Filter Open Paren
16
+ FOP~0~(~0
17
+ FCP - Filter Close Paren
18
+ FCP~0~)~0
19
+ FBV - Filter By Value (left-side AND connected)
20
+ FBV~Category~EQ~Books
21
+ Possible comparisons:
22
+ * EQ - Equals To (=)
23
+ * NE - Not Equals To (!=)
24
+ * GT - Greater Than (>)
25
+ * GE - Greater Than or Equals To (>=)
26
+ * LT - Less Than (<)
27
+ * LE - Less Than or Equals To (<=)
28
+ * LK - Like (Like)
29
+ * IN - Is NULL
30
+ * NN - Is NOT NULL
31
+ * INN - IN list
32
+ FBVOR - Filter By Value (left-side OR connected)
33
+ FBL - Filter By List (value list, separated by commas)
34
+ FBL~Category~EQ~Books,Movies
35
+ FBD - Filter by Date (exclude time)
36
+ FBD~UpdateDate~EQ~2015-10-01
37
+ FSF - Filter Sort Field
38
+ FSF~Category~ASC~0
39
+ FSF~Category~DESC~0
40
+ FDST - Filter by Distinct (adds distinct keyword to Read and Count queries)
41
+ FDST~0~0~0~
42
+
43
+ This means: FBV~Category~EQ~Books~FBV~PublishedYear~GT~2000~FSF~PublishedYear~DESC~0
44
+ Filters down to ALL BOOKS PUBLUSHED AFTER 2000 IN DESCENDING ORDER
45
+ */
46
+
47
+ class MeadowEndpointsFilterParser
48
+ {
49
+ constructor(pController)
50
+ {
51
+ this._Controller = pController;
52
+ }
53
+
54
+ // Get the comparison operator for use in a query stanza
55
+ getFilterComparisonOperator(pFilterOperator)
56
+ {
57
+ let tmpOperator = '=';
58
+ switch(pFilterOperator)
59
+ {
60
+ case 'EQ':
61
+ tmpOperator = '=';
62
+ break;
63
+ case 'NE':
64
+ tmpOperator = '!=';
65
+ break;
66
+ case 'GT':
67
+ tmpOperator = '>';
68
+ break;
69
+ case 'GE':
70
+ tmpOperator = '>=';
71
+ break;
72
+ case 'LT':
73
+ tmpOperator = '<';
74
+ break;
75
+ case 'LE':
76
+ tmpOperator = '<=';
77
+ break;
78
+ case 'LK':
79
+ tmpOperator = 'LIKE';
80
+ break;
81
+ case 'NLK':
82
+ tmpOperator = 'NOT LIKE';
83
+ break;
84
+ case 'IN':
85
+ tmpOperator = 'IS NULL';
86
+ break;
87
+ case 'NN':
88
+ tmpOperator = 'IS NOT NULL';
89
+ break;
90
+ case 'INN':
91
+ tmpOperator = 'IN';
92
+ break;
93
+ case 'FOP':
94
+ tmpOperator = '(';
95
+ break;
96
+ case 'FCP':
97
+ tmpOperator = ')';
98
+ break;
99
+ }
100
+ return tmpOperator;
101
+ }
102
+
103
+ addFilterStanzaToQuery(pFilterStanza, pQuery)
104
+ {
105
+ if (!pFilterStanza.Instruction)
106
+ {
107
+ return false;
108
+ }
109
+
110
+ switch(pFilterStanza.Instruction)
111
+ {
112
+ case 'FBV': // Filter by Value (left-side AND)
113
+ pQuery.addFilter(pFilterStanza.Field, pFilterStanza.Value, this.getFilterComparisonOperator(pFilterStanza.Operator), 'AND');
114
+ break;
115
+
116
+ case 'FBVOR': // Filter by Value (left-side OR)
117
+ pQuery.addFilter(pFilterStanza.Field, pFilterStanza.Value, this.getFilterComparisonOperator(pFilterStanza.Operator), 'OR');
118
+ break;
119
+
120
+ case 'FBL': // Filter by List (left-side AND)
121
+ // Just split the value by comma for now. May want to revisit better characters or techniques later.
122
+ pQuery.addFilter(pFilterStanza.Field, pFilterStanza.Value.split(','), this.getFilterComparisonOperator(pFilterStanza.Operator), 'AND');
123
+ break;
124
+
125
+ case 'FBLOR': // Filter by List (left-side OR)
126
+ // Just split the value by comma for now. May want to revisit better characters or techniques later.
127
+ pQuery.addFilter(pFilterStanza.Field, pFilterStanza.Value.split(','), this.getFilterComparisonOperator(pFilterStanza.Operator), 'OR');
128
+ break;
129
+
130
+ case 'FBD': // Filter by Date (exclude time)
131
+ pQuery.addFilter(`DATE(${pFilterStanza.Field})`, pFilterStanza.Value.split(','), this.getFilterComparisonOperator(pFilterStanza.Operator), 'AND', pFilterStanza.Field);
132
+ break;
133
+
134
+ case 'FBDOR': // Filter by Date (exclude time)
135
+ pQuery.addFilter(`DATE(${pFilterStanza.Field})`, pFilterStanza.Value.split(','), this.getFilterComparisonOperator(pFilterStanza.Operator), 'OR', pFilterStanza.Field);
136
+ break;
137
+
138
+ case 'FSF': // Filter Sort Field
139
+ const tmpSortDirection = (pFilterStanza.Operator === 'DESC') ? 'Descending' : 'Ascending';
140
+ pQuery.addSort({ Column: pFilterStanza.Field, Direction: tmpSortDirection });
141
+ break;
142
+
143
+ case 'FOP': // Filter Open Paren
144
+ pQuery.addFilter('', '', '(');
145
+ break;
146
+
147
+ case 'FCP': // Filter Close Paren
148
+ pQuery.addFilter('', '', ')');
149
+ break;
150
+
151
+ case 'FDST': // Filter Distinct
152
+ // ensure we don't break if using an older foxhound version
153
+ if (pQuery.setDistinct)
154
+ {
155
+ pQuery.setDistinct(true);
156
+ }
157
+ break;
158
+
159
+ default:
160
+ //console.log('Unparsable filter stanza.');
161
+ return false;
162
+ break;
163
+ }
164
+
165
+ // Be paranoid about the instruction
166
+ pFilterStanza.Instruction = false;
167
+ return true;
168
+ };
169
+
170
+ parseFilter(pFilterString, pQuery)
171
+ {
172
+ if (typeof(pFilterString) !== 'string')
173
+ {
174
+ return false;
175
+ }
176
+
177
+ const tmpFilterTerms = pFilterString.split('~');
178
+
179
+ if (tmpFilterTerms.length < 4)
180
+ {
181
+ return true;
182
+ }
183
+
184
+ let tmpFilterStanza = { Instruction: false };
185
+
186
+ for (let i = 0; i < tmpFilterTerms.length; i++)
187
+ {
188
+ switch(i % 4)
189
+ {
190
+ case 0: // INSTRUCTION
191
+ this.addFilterStanzaToQuery(tmpFilterStanza, pQuery);
192
+ //console.log(i+' Instruction: '+tmpFilterTerms[i]);
193
+ tmpFilterStanza = (
194
+ {
195
+ Instruction: tmpFilterTerms[i],
196
+ Field: '',
197
+ Operator: '',
198
+ Value: ''
199
+ });
200
+ break;
201
+
202
+ case 1: // FIELD
203
+ //console.log(i+' Field: '+tmpFilterTerms[i]);
204
+ tmpFilterStanza.Field = tmpFilterTerms[i];
205
+ break;
206
+
207
+ case 2: // OPERATOR
208
+ //console.log(i+' Operator: '+tmpFilterTerms[i]);
209
+ tmpFilterStanza.Operator = tmpFilterTerms[i];
210
+ break;
211
+
212
+ case 3: // VALUE
213
+ //console.log(i+' Value: '+tmpFilterTerms[i]);
214
+ tmpFilterStanza.Value = tmpFilterTerms[i];
215
+ break;
216
+ }
217
+ }
218
+
219
+ this.addFilterStanzaToQuery(tmpFilterStanza, pQuery);
220
+
221
+ return true;
222
+ };
223
+ }
224
+
225
+ module.exports = MeadowEndpointsFilterParser;
@@ -0,0 +1,48 @@
1
+ class MeadowEndpointsSessionMarshaler
2
+ {
3
+ constructor(pController)
4
+ {
5
+ this._Controller = pController;
6
+ }
7
+
8
+ getSessionData(pRequest)
9
+ {
10
+ let tmpSession = Object.assign({}, this._Controller.settings.MeadowEndpointsDefaultSessionObject);
11
+
12
+ switch (this._Controller.settings.MeadowEndpointsSessionDataSource || 'Request')
13
+ {
14
+ default:
15
+ this._LogController.warn(`Unknown session source configured: ${_SessionDataSource} - defaulting to Request for backward compatibility`);
16
+ case 'Request':
17
+ // noop - already set by orator-session
18
+ tmpSession = this._Controller.extend(tmpSession, pRequest.UserSession);
19
+ break;
20
+ case 'None':
21
+ break;
22
+ case 'Header':
23
+ try
24
+ {
25
+ const tmpHeaderSessionString = pRequest.headers['x-trusted-session'];
26
+ if (!tmpHeaderSessionString)
27
+ {
28
+ break;
29
+ }
30
+ tmpHeaderSession = JSON.parse(tmpHeaderSessionString);
31
+ tmpSession = this._Controller.extend(tmpSession, pRequest.tmpHeaderSession);
32
+ }
33
+ catch (pError)
34
+ {
35
+ this._LogController.error(`Meadow Endpoints attempted to process a Header Session String with value [${tmpHeaderSessionString}] and failed -- likely culprit is bad JSON.`)
36
+ }
37
+ break;
38
+ }
39
+
40
+ // Do we keep this here for backwards compatibility?
41
+ // Yes this makes sense here.
42
+ pRequest.UserSession = tmpSession;
43
+
44
+ return tmpSession;
45
+ }
46
+ }
47
+
48
+ module.exports = MeadowEndpointsSessionMarshaler;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Meadow Endpoint Streamer - Stream an array of recods as JSON to an output stream.
3
+ */
4
+ const libAsyncEachSeries = require('async/eachSeries');
5
+ const JSONStream = require('JSONStream');
6
+
7
+ class MeadowEndpointsStreamRecordArray
8
+ {
9
+ constructor(pController)
10
+ {
11
+ this._Controller = pController;
12
+ }
13
+
14
+ chunk(pInput, pChunkSize, pChunkCache)
15
+ {
16
+ let tmpInputArray = [...pInput];
17
+ // Note lodash defaults to 1, underscore defaults to 0
18
+ let tmpChunkSize = (typeof(pChunkSize) == 'number') ? pChunkSize : 0;
19
+ let tmpChunkCache = (typeof(pChunkCache) != 'undefined') ? pChunkCache : [];
20
+
21
+ if (tmpChunkSize <= 0)
22
+ {
23
+ return tmpChunkCache;
24
+ }
25
+
26
+ while (tmpInputArray.length)
27
+ {
28
+ tmpChunkCache.push(tmpInputArray.splice(0, tmpChunkSize));
29
+ }
30
+
31
+ return tmpChunkCache;
32
+ }
33
+
34
+ streamRecordArray(pResponse, pRecords, fCallback)
35
+ {
36
+ // for meadow invoke, writeHead isn't provided, so just call send(), which is the shim it uses...
37
+ // also, for small arrays, don't bother with the async serialization; this threshold could use tuning
38
+ if (!pResponse.writeHead || !Array.isArray(pRecords) || pRecords.length < 2500)
39
+ {
40
+ pResponse.send(pRecords);
41
+ return fCallback();
42
+ }
43
+
44
+ pResponse.writeHead(200,
45
+ {
46
+ 'content-type': 'application/json',
47
+ });
48
+
49
+ const recordJsonMarshaller = JSONStream.stringify();
50
+ recordJsonMarshaller.pipe(pResponse);
51
+
52
+ // we write the records in chunks; doing one per loop is very inefficient, doing all is the same as not doing this at all
53
+ libAsyncEachSeries(this.chunk(pRecords, 1000), (pRecordChunk, fNext) =>
54
+ {
55
+ pRecordChunk.forEach(recordJsonMarshaller.write);
56
+ setImmediate(fNext);
57
+ },
58
+ (error) =>
59
+ {
60
+ recordJsonMarshaller.end();
61
+ fCallback(error);
62
+ });
63
+ }
64
+ }
65
+
66
+ module.exports = MeadowEndpointsStreamRecordArray;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Simple browser shim loader - assign the npm module to a window global automatically
3
+ *
4
+ * @license MIT
5
+ * @author <steven@velozo.com>
6
+ */
7
+ var libNPMModuleWrapper = require('./Meadow-Endpoints.js');
8
+
9
+ if ((typeof(window) === 'object') && !window.hasOwnProperty('MeadowEndpoints'))
10
+ {
11
+ window.MeadowEndpoints = libNPMModuleWrapper;
12
+ }
13
+
14
+ module.exports = libNPMModuleWrapper;