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,28 @@
1
+ {
2
+ "Product": "MeadowEndpointsTestBookStore",
3
+ "ProductVersion": "1.0.0",
4
+
5
+ "UUID":
6
+ {
7
+ "DataCenter": 0,
8
+ "Worker": 0
9
+ },
10
+ "LogStreams":
11
+ [
12
+ {
13
+ "streamtype": "console"
14
+ }
15
+ ],
16
+
17
+ "APIServerPort": 8086,
18
+
19
+ "MySQL":
20
+ {
21
+ "Server": "127.0.0.1",
22
+ "Port": 3306,
23
+ "User": "root",
24
+ "Password": "123456789",
25
+ "Database": "bookstore",
26
+ "ConnectionPoolLimit": 20
27
+ }
28
+ }
@@ -0,0 +1 @@
1
+ let tmpRun = require('./bookstore-import-books.js')();
@@ -0,0 +1,215 @@
1
+ /*
2
+ Import Books directly from CSV to SQL.
3
+
4
+ An example of how to use the Meadow DALs directly.
5
+ */
6
+ /**
7
+ * @license MIT
8
+ * @author <steven@velozo.com>
9
+ */
10
+
11
+ // Server Settings
12
+ const _Settings = require('./bookstore-configuration.json');
13
+ // Fable is logging and settings
14
+ const libFable = require('fable');
15
+ // Official MySQL Client
16
+ const libMySQL = require('mysql2');
17
+ // Meadow is the DAL
18
+ const libMeadow = require('meadow');
19
+
20
+ const libAsync = require('async');
21
+
22
+ let _Fable = libFable.new(_Settings);
23
+ let _Meadow = libMeadow.new(_Fable);
24
+
25
+ _Fable.log.info("Application is starting up...");
26
+
27
+ _Fable.log.info("...Creating SQL Connection pools at "+_Fable.settings.MySQL.Server+"...");
28
+ // Setup SQL Connection Pool
29
+ _Fable.MeadowMySQLConnectionPool = libMySQL.createPool
30
+ (
31
+ {
32
+ connectionLimit: _Fable.settings.MySQL.ConnectionPoolLimit,
33
+ host: _Fable.settings.MySQL.Server,
34
+ port: _Fable.settings.MySQL.Port,
35
+ user: _Fable.settings.MySQL.User,
36
+ password: _Fable.settings.MySQL.Password,
37
+ database: _Fable.settings.MySQL.Database,
38
+ namedPlaceholders: true
39
+ }
40
+ );
41
+
42
+ // Create DAL objects
43
+ let _DAL = {};
44
+ const _BookStoreModel = require (__dirname+'/model/json_schema/BookStore-Extended.json');
45
+ const _BookStoreTableList = Object.keys(_BookStoreModel.Tables);
46
+ _Fable.log.info(`...Creating ${_BookStoreTableList.length} DAL entries...`);
47
+ for (let i = 0; i < _BookStoreTableList.length; i++)
48
+ {
49
+ let tmpDALEntityName = _BookStoreTableList[i];
50
+ _Fable.log.info(` -> Creating the ${tmpDALEntityName} DAL...`);
51
+ _DAL[tmpDALEntityName] = _Meadow.loadFromPackage(__dirname+'/model/meadow_schema/BookStore-MeadowSchema-'+tmpDALEntityName+'.json');
52
+ _DAL[tmpDALEntityName].setProvider('MySQL');
53
+ _DAL[tmpDALEntityName].setIDUser(99999);
54
+ }
55
+
56
+ const libPapa = require('papaparse');
57
+ const libFS = require('fs');
58
+
59
+ const _BookData = libFS.readFileSync(`${__dirname}/data/books.csv`, 'utf8');
60
+
61
+ let tmpBookMap = {};
62
+ let tmpAuthorMap = {};
63
+
64
+ let fImportBooks = (fCallback) =>
65
+ {
66
+ console.log('Import operation executing...');
67
+ let tmpCallback = (typeof(fCallback) == 'function') ? fCallback : ()=>{};
68
+
69
+ libPapa.parse(_BookData,
70
+ {
71
+ delimiter: ",",
72
+ header: true,
73
+ complete:
74
+ (pResults) =>
75
+ {
76
+ libAsync.waterfall([
77
+ (fStageComplete) =>
78
+ {
79
+ // Enumerate and insert each book
80
+ libAsync.eachLimit(pResults.data, 10,
81
+ (pBookDataRow, fCallback) =>
82
+ {
83
+ let tmpRecordToCreate = (
84
+ {
85
+ Title: pBookDataRow.original_title,
86
+ PublicationYear: isNaN(parseInt(pBookDataRow.original_publication_year, 10)) ? 0 : parseInt(pBookDataRow.original_publication_year, 10),
87
+ ISBN: pBookDataRow.isbn,
88
+ Type: 'Paper',
89
+ Genre: 'UNKNOWN',
90
+ Language: pBookDataRow.language_code,
91
+ ImageURL: pBookDataRow.image_url
92
+ });
93
+ let tmpQuery = _DAL.Book.query;
94
+ //tmpQuery.setLogLevel(5);
95
+ tmpQuery.addRecord(tmpRecordToCreate);
96
+ _DAL.Book.doCreate(tmpQuery,
97
+ (pError, pQuery, pQueryRead, pRecord)=>
98
+ {
99
+ // Add it to the book map
100
+ if (!pError)
101
+ {
102
+ tmpBookMap[pBookDataRow.id] = pRecord.IDBook;
103
+ //_Fable.log.info('Imported book ID '+pRecord.IDBook+' title ['+pRecord.Title+']');
104
+ }
105
+ fCallback(pError);
106
+ });
107
+
108
+ },
109
+ (pError)=>
110
+ {
111
+ _Fable.log.info('...Book Import operation complete!');
112
+ fStageComplete()
113
+ });
114
+ },
115
+ (fStageComplete) =>
116
+ {
117
+ // Enumerate and insert each author
118
+ libAsync.eachLimit(pResults.data, 10,
119
+ (pBookDataRow, fCallback) =>
120
+ {
121
+ if (!pBookDataRow.hasOwnProperty('authors'))
122
+ return fCallback();
123
+
124
+ let tmpAuthorsToCreate = pBookDataRow.authors.split(',');
125
+
126
+ libAsync.eachLimit(tmpAuthorsToCreate, 1,
127
+ (pAuthor, fAuthorInsertCallback)=>
128
+ {
129
+ if (tmpAuthorMap.hasOwnProperty(pAuthor))
130
+ {
131
+ return fAuthorInsertCallback();
132
+ }
133
+ else
134
+ {
135
+ tmpAuthorMap[pAuthor] = false;
136
+ }
137
+ let tmpRecordToCreate = (
138
+ {
139
+ Name: pAuthor
140
+ });
141
+ let tmpQuery = _DAL.Author.query.addRecord(tmpRecordToCreate);
142
+ _DAL.Author.doCreate(tmpQuery,
143
+ (pError, pQuery, pQueryRead, pRecord)=>
144
+ {
145
+ if (!pError)
146
+ {
147
+ tmpAuthorMap[pRecord.Name] = pRecord.IDAuthor;
148
+ //_Fable.log.info('Imported Author ID '+pRecord.IDAuthor+' named ['+pRecord.Name+']');
149
+ }
150
+ return fAuthorInsertCallback(pError);
151
+ });
152
+ },
153
+ (pError)=>
154
+ {
155
+ return fCallback(pError);
156
+ });
157
+ },
158
+ (pError)=>
159
+ {
160
+ _Fable.log.info('...Author Import operation complete!');
161
+ fStageComplete();
162
+ });
163
+ },
164
+ (fStageComplete) =>
165
+ {
166
+ // Create Book->Author joins
167
+ libAsync.eachLimit(pResults.data, 10,
168
+ (pBookDataRow, fCallback) =>
169
+ {
170
+ if (!pBookDataRow.hasOwnProperty('authors'))
171
+ return fCallback();
172
+
173
+ let tmpAuthorJoinsToCreate = pBookDataRow.authors.split(',');
174
+
175
+ libAsync.eachLimit(tmpAuthorJoinsToCreate, 1,
176
+ (pAuthor, fAuthorJoinInsertCallback)=>
177
+ {
178
+ let tmpRecordToCreate = (
179
+ {
180
+ IDBook: tmpBookMap[pBookDataRow.id],
181
+ IDAuthor: tmpAuthorMap[pAuthor]
182
+ });
183
+ let tmpQuery = _DAL.BookAuthorJoin.query.addRecord(tmpRecordToCreate);
184
+ _DAL.BookAuthorJoin.doCreate(tmpQuery,
185
+ (pError, pQuery, pQueryRead, pRecord)=>
186
+ {
187
+ if (!pError)
188
+ {
189
+ //_Fable.log.info(`Joined author ${pAuthor} ID ${pRecord.IDAuthor} to book ID ${pRecord.IDBook}`);
190
+ }
191
+ return fAuthorJoinInsertCallback(pError);
192
+ });
193
+ },
194
+ (pError)=>
195
+ {
196
+ return fCallback(pError);
197
+ });
198
+ },
199
+ (pError)=>
200
+ {
201
+ _Fable.log.info('...Join Import operation complete!');
202
+ return fStageComplete(pError);
203
+ });
204
+ }
205
+ ],
206
+ (pError)=>
207
+ {
208
+ _Fable.log.info('Full import operation has completed!')
209
+ tmpCallback(pError);
210
+ });
211
+ }
212
+ });
213
+ }
214
+
215
+ module.exports = fImportBooks;
@@ -0,0 +1,138 @@
1
+ /*
2
+ An example of Meadow Endpoints, Fable and Orator
3
+ */
4
+ const libWhyMe = require('why-is-node-running');
5
+ /**
6
+ * @license MIT
7
+ * @author <steven@velozo.com>
8
+ */
9
+
10
+ // Server Settings
11
+ const _Settings = require('./bookstore-configuration.json');
12
+ // Fable is logging and settings
13
+ const libFable = require('fable');
14
+ // Orator is the web server
15
+ const libOrator = require('orator');
16
+ // Official MySQL Client
17
+ const libMySQL = require('mysql2');
18
+ // Meadow is the DAL
19
+ const libMeadow = require('meadow');
20
+ // Meadow-endpoints maps the DAL to restify endpoints automagically
21
+ const libMeadowEndpoints = require('../source/Meadow-Endpoints.js');
22
+
23
+ let _Fable = new libFable(_Settings);
24
+ let _Orator = new libOrator(_Fable);
25
+
26
+ let fStartServiceServer = (fInitializeCallback) =>
27
+ {
28
+ _Orator.initializeServiceServer((pError) =>
29
+ {
30
+ let _Meadow = libMeadow.new(_Fable);
31
+
32
+ _Fable.log.info("Application is starting up...");
33
+
34
+ _Fable.log.info("...Creating SQL Connection pools at "+_Fable.settings.MySQL.Server+"...");
35
+ _Fable.MeadowMySQLConnectionPool = libMySQL.createPool
36
+ (
37
+ {
38
+ connectionLimit: _Fable.settings.MySQL.ConnectionPoolLimit,
39
+ host: _Fable.settings.MySQL.Server,
40
+ port: _Fable.settings.MySQL.Port,
41
+ user: _Fable.settings.MySQL.User,
42
+ password: _Fable.settings.MySQL.Password,
43
+ database: _Fable.settings.MySQL.Database,
44
+ namedPlaceholders: true
45
+ }
46
+ );
47
+
48
+ // Create DAL objects for each table in the schema
49
+ let _DAL = {};
50
+ let _MeadowEndpoints = {};
51
+
52
+ // 1. Load full compiled schema of the model from stricture
53
+ _Fable.log.info(`...Loading stricture schemas...`);
54
+ const _BookStoreModel = require (__dirname+'/model/json_schema/BookStore-Extended.json');
55
+
56
+ // 2. Extract an array of each table in the schema
57
+ const _BookStoreTableList = Object.keys(_BookStoreModel.Tables);
58
+
59
+ // 3. Enumerate each entry in the compiled model and load a DAL for that table
60
+ _Fable.log.info(`...Creating ${_BookStoreTableList.length} DAL entries...`);
61
+ for (let i = 0; i < _BookStoreTableList.length; i++)
62
+ {
63
+ let tmpDALEntityName = _BookStoreTableList[i];
64
+ _Fable.log.info(` -> Creating the ${tmpDALEntityName} DAL...`);
65
+ // 4. Create the DAL for each entry (e.g. it would be at _DAL.Book or _DAL.Author)
66
+ _DAL[tmpDALEntityName] = _Meadow.loadFromPackage(__dirname+'/model/meadow_schema/BookStore-MeadowSchema-'+tmpDALEntityName+'.json');
67
+ // 5. Tell this DAL object to use MySQL
68
+ _DAL[tmpDALEntityName].setProvider('MySQL');
69
+ // 6. Set the User ID to 10 just for fun
70
+ _DAL[tmpDALEntityName].setIDUser(1);
71
+ // 7. Create a Meadow Endpoints class for this DAL
72
+ _MeadowEndpoints[tmpDALEntityName] = libMeadowEndpoints.new(_DAL[tmpDALEntityName]);
73
+ // 8. Expose the meadow endpoints on Orator
74
+ _MeadowEndpoints[tmpDALEntityName].connectRoutes(_Orator.webServer);
75
+ }
76
+
77
+ // 100. Add a post processing hook to the Book DAL on single reads
78
+ /*
79
+ This post processing step will look for all book author joins then
80
+ load all appropriate authors and stuff them in the book record before
81
+ returning it.
82
+ */
83
+ _MeadowEndpoints.Book.controller.BehaviorInjection.setBehavior('Read-PostOperation',
84
+ (pRequest, pRequestState, fComplete) =>
85
+ {
86
+ // Get the join records
87
+ _DAL.BookAuthorJoin.doReads(_DAL.BookAuthorJoin.query.addFilter('IDBook', pRequestState.Record.IDBook),
88
+ (pJoinReadError, pJoinReadQuery, pJoinRecords)=>
89
+ {
90
+ let tmpAuthorList = [];
91
+ for (let j = 0; j < pJoinRecords.length; j++)
92
+ {
93
+ tmpAuthorList.push(pJoinRecords[j].IDAuthor);
94
+ }
95
+ if (tmpAuthorList.length < 1)
96
+ {
97
+ pRequestState.Record.Authors = [];
98
+ return fComplete();
99
+ }
100
+ else
101
+ {
102
+ _DAL.Author.doReads(_DAL.Author.query.addFilter('IDAuthor', tmpAuthorList, 'IN'),
103
+ (pReadsError, pReadsQuery, pAuthors)=>
104
+ {
105
+ pRequestState.Record.Authors = pAuthors;
106
+ return fComplete();
107
+ });
108
+ }
109
+ });
110
+ });
111
+
112
+ // Static site mapping
113
+ _Orator.log.info("...Mapping static route for web site...");
114
+
115
+ //_Orator.addStaticRoute(__dirname+'/../web/');
116
+
117
+ // Start the web server (ctrl+c to end it)
118
+ _Orator.startWebServer(
119
+ (pError) =>
120
+ {
121
+ // Now do a GET!
122
+ let tmpURI = `/1.0/Book/1`;
123
+ _Orator.invoke('GET', tmpURI, null,
124
+ (pError, pResponseData) =>
125
+ {
126
+ _Orator.log.info(`Response to [${tmpURI}] came back from IPC resulting in [${pResponseData}]!`);
127
+ _Fable.MeadowMySQLConnectionPool.end();
128
+ libWhyMe();
129
+ return true;
130
+ });
131
+ fInitializeCallback(pError);
132
+ }
133
+ );
134
+ });
135
+ return _Orator;
136
+ }
137
+
138
+ module.exports = fStartServiceServer;
@@ -0,0 +1,6 @@
1
+ const libServer = require('./bookstore-serve-meadow-endpoint-apis.js');
2
+ let _Orator = libServer(
3
+ ()=>
4
+ {
5
+ console.log('API service is started!');
6
+ });
@@ -0,0 +1,129 @@
1
+ /*
2
+ An example of Meadow Endpoints, Fable and Orator
3
+ */
4
+
5
+ /**
6
+ * @license MIT
7
+ * @author <steven@velozo.com>
8
+ */
9
+
10
+ // Server Settings
11
+ const _Settings = require('./bookstore-configuration.json');
12
+ // Fable is logging and settings
13
+ const libFable = require('fable');
14
+ // Orator is the web server
15
+ const libOrator = require('orator');
16
+ const libOratorServiceServerRestify = require('orator-serviceserver-restify');
17
+ // Official MySQL Client
18
+ const libMySQL = require('mysql2');
19
+ // Meadow is the DAL
20
+ const libMeadow = require('meadow');
21
+ // Meadow-endpoints maps the DAL to restify endpoints automagically
22
+ const libMeadowEndpoints = require('../source/Meadow-Endpoints.js');
23
+
24
+ let _Fable = new libFable(_Settings);
25
+ let _Orator = new libOrator(_Fable, libOratorServiceServerRestify);
26
+
27
+ let fStartServiceServer = (fInitializeCallback) =>
28
+ {
29
+ _Orator.initializeServiceServer(() =>
30
+ {
31
+ let _Meadow = libMeadow.new(_Fable);
32
+
33
+ _Fable.log.info("Application is starting up...");
34
+
35
+ _Fable.log.info("...Creating SQL Connection pools at "+_Fable.settings.MySQL.Server+"...");
36
+ _Fable.MeadowMySQLConnectionPool = libMySQL.createPool
37
+ (
38
+ {
39
+ connectionLimit: _Fable.settings.MySQL.ConnectionPoolLimit,
40
+ host: _Fable.settings.MySQL.Server,
41
+ port: _Fable.settings.MySQL.Port,
42
+ user: _Fable.settings.MySQL.User,
43
+ password: _Fable.settings.MySQL.Password,
44
+ database: _Fable.settings.MySQL.Database,
45
+ namedPlaceholders: true
46
+ }
47
+ );
48
+
49
+ // Create DAL objects for each table in the schema
50
+ let _DAL = {};
51
+ let _MeadowEndpoints = {};
52
+
53
+ // 1. Load full compiled schema of the model from stricture
54
+ _Fable.log.info(`...Loading stricture schemas...`);
55
+ const _BookStoreModel = require (__dirname+'/model/json_schema/BookStore-Extended.json');
56
+
57
+ // 2. Extract an array of each table in the schema
58
+ const _BookStoreTableList = Object.keys(_BookStoreModel.Tables);
59
+
60
+ // 3. Enumerate each entry in the compiled model and load a DAL for that table
61
+ _Fable.log.info(`...Creating ${_BookStoreTableList.length} DAL entries...`);
62
+ for (let i = 0; i < _BookStoreTableList.length; i++)
63
+ {
64
+ let tmpDALEntityName = _BookStoreTableList[i];
65
+ _Fable.log.info(` -> Creating the ${tmpDALEntityName} DAL...`);
66
+ // 4. Create the DAL for each entry (e.g. it would be at _DAL.Book or _DAL.Author)
67
+ _DAL[tmpDALEntityName] = _Meadow.loadFromPackage(__dirname+'/model/meadow_schema/BookStore-MeadowSchema-'+tmpDALEntityName+'.json');
68
+ // 5. Tell this DAL object to use MySQL
69
+ _DAL[tmpDALEntityName].setProvider('MySQL');
70
+ // 6. Set the User ID to 10 just for fun
71
+ _DAL[tmpDALEntityName].setIDUser(1);
72
+ // 7. Create a Meadow Endpoints class for this DAL
73
+ _MeadowEndpoints[tmpDALEntityName] = libMeadowEndpoints.new(_DAL[tmpDALEntityName]);
74
+ // 8. Expose the meadow endpoints on Orator
75
+ _MeadowEndpoints[tmpDALEntityName].connectRoutes(_Orator.webServer);
76
+ }
77
+
78
+ // 100. Add a post processing hook to the Book DAL on single reads
79
+ /*
80
+ This post processing step will look for all book author joins then
81
+ load all appropriate authors and stuff them in the book record before
82
+ returning it.
83
+ */
84
+ _MeadowEndpoints.Book.controller.BehaviorInjection.setBehavior('Read-PostOperation',
85
+ (pRequest, pRequestState, fComplete) =>
86
+ {
87
+ // Get the join records
88
+ _DAL.BookAuthorJoin.doReads(_DAL.BookAuthorJoin.query.addFilter('IDBook', pRequestState.Record.IDBook),
89
+ (pJoinReadError, pJoinReadQuery, pJoinRecords)=>
90
+ {
91
+ let tmpAuthorList = [];
92
+ for (let j = 0; j < pJoinRecords.length; j++)
93
+ {
94
+ tmpAuthorList.push(pJoinRecords[j].IDAuthor);
95
+ }
96
+ if (tmpAuthorList.length < 1)
97
+ {
98
+ pRequestState.Record.Authors = [];
99
+ return fComplete();
100
+ }
101
+ else
102
+ {
103
+ _DAL.Author.doReads(_DAL.Author.query.addFilter('IDAuthor', tmpAuthorList, 'IN'),
104
+ (pReadsError, pReadsQuery, pAuthors)=>
105
+ {
106
+ pRequestState.Record.Authors = pAuthors;
107
+ return fComplete();
108
+ });
109
+ }
110
+ });
111
+ });
112
+
113
+ // Static site mapping
114
+ _Orator.log.info("...Mapping static route for web site...");
115
+
116
+ //_Orator.addStaticRoute(__dirname+'/../web/');
117
+
118
+ // Start the web server (ctrl+c to end it)
119
+ _Orator.startWebServer(
120
+ (pError) =>
121
+ {
122
+ fInitializeCallback(pError);
123
+ }
124
+ );
125
+ });
126
+ return _Orator;
127
+ }
128
+
129
+ module.exports = fStartServiceServer;