fable 3.0.45 → 3.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.browserslistrc +1 -1
- package/.config/configstore/update-notifier-npm.json +1 -1
- package/.config/vscode-sqltools/runningInfo.json +1 -1
- package/Dockerfile_LUXURYCode +4 -5
- package/dist/fable.compatible.js +277 -4005
- package/dist/fable.compatible.min.js +18 -30
- package/dist/fable.compatible.min.js.map +1 -1
- package/dist/fable.js +208 -3936
- package/dist/fable.min.js +18 -30
- package/dist/fable.min.js.map +1 -1
- package/gulpfile-config.json +2 -2
- package/package.json +7 -7
- package/retold-harness/bookstore-serve-api.js +41 -0
- package/retold-harness/configuration-bookstore-serve-api.js +30 -0
- package/retold-harness/model/manual_scripts/MySQL-Laden-Entry.sh +17 -0
- package/retold-harness/model/manual_scripts/my.cnf +4 -0
- package/retold-harness/model/sql_create/BookStore-DeleteAndRepopulateTables.sql +194 -0
- package/retold-harness/model/sql_create/MySQL-Security.sql +5 -0
- package/source/services/Fable-Service-MetaTemplate/MetaTemplate-StringParser.js +281 -0
- package/source/services/Fable-Service-MetaTemplate/MetaTemplate-WordTree.js +97 -0
- package/source/services/Fable-Service-MetaTemplate.js +20 -6
- package/source/services/Fable-Service-Operation-DefaultSettings.js +1 -1
- package/source/services/Fable-Service-Operation.js +4 -11
- package/test/MetaTemplating_tests.js +241 -29
- package/test/RestClient_test.js +1 -1
- package/retold-harness/Bookstore-Import-Books.sh +0 -4
- package/retold-harness/bookstore-configuration.json +0 -28
- package/retold-harness/bookstore-import-books-run.js +0 -9
- package/retold-harness/bookstore-import-books.js +0 -214
- package/retold-harness/bookstore-serve-meadow-endpoint-apis-IPC.js +0 -137
- package/retold-harness/bookstore-serve-meadow-endpoint-apis-run.js +0 -6
- package/retold-harness/bookstore-serve-meadow-endpoint-apis.js +0 -129
- package/retold-harness/data/books.csv +0 -10001
- package/retold-harness/model/json_schema/README.md +0 -1
- package/retold-harness/package.json +0 -22
- package/retold-harness/test_old/Tests.js +0 -3243
- package/retold-harness/test_old/untitled.js +0 -88
- /package/retold-harness/{MySQL-Laden-Entry.sh → docker_scripts/MySQL-Laden-Entry.sh} +0 -0
- /package/retold-harness/model/{json_schema/BookStore-Extended.json → Model-Extended.json} +0 -0
- /package/retold-harness/model/{json_schema/BookStore-PICT.json → Model-PICT.json} +0 -0
- /package/retold-harness/model/{json_schema/BookStore.json → Model.json} +0 -0
- /package/retold-harness/{bookstore-api-endpoint-exercises.paw → model/bookstore-api-endpoint-exercises.paw} +0 -0
- /package/retold-harness/{MySQL-Security.sql → model/manual_scripts/MySQL-Security.sql} +0 -0
- /package/retold-harness/model/{meadow_schema/BookStore-MeadowSchema-Author.json → meadow/Model-MeadowSchema-Author.json} +0 -0
- /package/retold-harness/model/{meadow_schema/BookStore-MeadowSchema-Book.json → meadow/Model-MeadowSchema-Book.json} +0 -0
- /package/retold-harness/model/{meadow_schema/BookStore-MeadowSchema-BookAuthorJoin.json → meadow/Model-MeadowSchema-BookAuthorJoin.json} +0 -0
- /package/retold-harness/model/{meadow_schema/BookStore-MeadowSchema-BookPrice.json → meadow/Model-MeadowSchema-BookPrice.json} +0 -0
- /package/retold-harness/model/{meadow_schema/BookStore-MeadowSchema-Review.json → meadow/Model-MeadowSchema-Review.json} +0 -0
- /package/retold-harness/model/{meadow_schema → meadow}/README.md +0 -0
|
@@ -6,42 +6,46 @@
|
|
|
6
6
|
* @author Steven Velozo <steven@velozo.com>
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const libFable = require('../source/Fable.js');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const Chai = require("chai");
|
|
12
|
+
const Expect = Chai.expect;
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const loadMetaTemplateModule = () =>
|
|
16
16
|
{
|
|
17
17
|
let tmpFable = new libFable();
|
|
18
18
|
return tmpFable.serviceManager.instantiateServiceProviderWithoutRegistration('MetaTemplate', {});
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
const configMetaTemplate = (pModule) =>
|
|
22
22
|
{
|
|
23
|
+
|
|
24
|
+
|
|
23
25
|
pModule.addPattern('<%', '%>', 'JUNKED_THIS_DATA');
|
|
24
26
|
// This one gets the count of the inner string...
|
|
25
27
|
pModule.addPattern('<%#', '%>', (pData)=>{return pData.length});
|
|
26
28
|
// Replaces the string with the settings object...
|
|
27
29
|
pModule.addPattern('<%=', '%>', (pData)=>{return JSON.stringify(pModule.settings);});
|
|
30
|
+
// Custom expression hashes
|
|
31
|
+
pModule.addPattern('<*', '*>', (pHash, pData)=>{return `pData is [${pData}] with a hash of [${pHash}]`});
|
|
32
|
+
pModule.addPattern('<^', '^>', (pHash, pData)=>{return `hash of [${pHash}] from pData is ${pData[pHash]}`});
|
|
28
33
|
// This just escapes out pairs of $
|
|
29
34
|
pModule.addPattern('$');
|
|
35
|
+
pModule.addPatternAsync('<%Async', '%>',
|
|
36
|
+
(pHash, pData, fCallback)=>
|
|
37
|
+
{
|
|
38
|
+
return fCallback(null, `ASYNC DATA IS [${pHash}]`);
|
|
39
|
+
});
|
|
40
|
+
|
|
30
41
|
};
|
|
31
42
|
|
|
32
43
|
suite
|
|
33
44
|
(
|
|
34
45
|
'Fable MetaTemplating',
|
|
35
|
-
|
|
46
|
+
() =>
|
|
36
47
|
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
setup
|
|
40
|
-
(
|
|
41
|
-
function()
|
|
42
|
-
{
|
|
43
|
-
}
|
|
44
|
-
);
|
|
48
|
+
setup (() => {});
|
|
45
49
|
|
|
46
50
|
suite
|
|
47
51
|
(
|
|
@@ -53,11 +57,11 @@ suite
|
|
|
53
57
|
'No Matches...',
|
|
54
58
|
(fDone) =>
|
|
55
59
|
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
let tmpTestString = 'ABC123';
|
|
61
|
+
let tmpExpectedResult = tmpTestString;
|
|
62
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
63
|
+
configMetaTemplate(testMetaTemplate);
|
|
64
|
+
let tmpResult = testMetaTemplate.parseString(tmpTestString);
|
|
61
65
|
Expect(tmpResult).to.equal(tmpExpectedResult);
|
|
62
66
|
fDone();
|
|
63
67
|
}
|
|
@@ -67,11 +71,11 @@ suite
|
|
|
67
71
|
'Count function...',
|
|
68
72
|
(fDone) =>
|
|
69
73
|
{
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
let tmpTestString = 'There are <%#0123456789%> characters in here';
|
|
75
|
+
let tmpExpectedResult = 'There are 10 characters in here';
|
|
76
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
77
|
+
configMetaTemplate(testMetaTemplate);
|
|
78
|
+
let tmpResult = testMetaTemplate.parseString(tmpTestString);
|
|
75
79
|
Expect(tmpResult).to.equal(tmpExpectedResult);
|
|
76
80
|
fDone();
|
|
77
81
|
}
|
|
@@ -81,15 +85,223 @@ suite
|
|
|
81
85
|
'Multiple terms...',
|
|
82
86
|
(fDone) =>
|
|
83
87
|
{
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
let tmpTestString = 'There are <%#12345%> characters in here and a $comment$ as well. And we <% Some data in here %> right up.';
|
|
89
|
+
let tmpExpectedResult = 'There are 5 characters in here and a comment as well. And we JUNKED_THIS_DATA right up.';
|
|
90
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
91
|
+
configMetaTemplate(testMetaTemplate);
|
|
92
|
+
let tmpResult = testMetaTemplate.parseString(tmpTestString);
|
|
93
|
+
Expect(tmpResult).to.equal(tmpExpectedResult);
|
|
94
|
+
fDone();
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
test
|
|
98
|
+
(
|
|
99
|
+
'Basic pattern replacement...',
|
|
100
|
+
(fDone) =>
|
|
101
|
+
{
|
|
102
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
103
|
+
|
|
104
|
+
Expect(Object.keys(testMetaTemplate.ParseTree).length).to.equal(0, 'There should be an empty tree on initialization.');
|
|
105
|
+
configMetaTemplate(testMetaTemplate);
|
|
106
|
+
Expect(Object.keys(testMetaTemplate.ParseTree).length).to.equal(2, 'The tree should grow properly.');
|
|
107
|
+
|
|
108
|
+
//console.log(JSON.stringify(testMetaTemplate.tree,null,4));
|
|
109
|
+
|
|
110
|
+
let tmpResult = testMetaTemplate.parseString('');
|
|
111
|
+
Expect(tmpResult.length).to.equal(0, 'Parsing Empty Strings should Work...');
|
|
112
|
+
|
|
113
|
+
fDone();
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
test
|
|
118
|
+
(
|
|
119
|
+
'Leveraging pData a bit...',
|
|
120
|
+
(fDone) =>
|
|
121
|
+
{
|
|
122
|
+
let tmpTestString = 'The <*SomeValue*> pData up in here and a $comment$ as well.';
|
|
123
|
+
let tmpExpectedResult = 'The pData is [Yikes] with a hash of [SomeValue] pData up in here and a comment as well.';
|
|
124
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
125
|
+
configMetaTemplate(testMetaTemplate);
|
|
126
|
+
let tmpResult = testMetaTemplate.parseString(tmpTestString, 'Yikes');
|
|
127
|
+
Expect(tmpResult).to.equal(tmpExpectedResult);
|
|
128
|
+
fDone();
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
test
|
|
132
|
+
(
|
|
133
|
+
'Leveraging pData a using subobjects...',
|
|
134
|
+
(fDone) =>
|
|
135
|
+
{
|
|
136
|
+
let tmpTestString = 'The <^SomeValue^> pData up in here and a $comment$ as well.';
|
|
137
|
+
let tmpExpectedResult = 'The hash of [SomeValue] from pData is AirbornLight pData up in here and a comment as well.';
|
|
138
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
139
|
+
configMetaTemplate(testMetaTemplate);
|
|
140
|
+
let tmpResult = testMetaTemplate.parseString(tmpTestString, {SomeValue:'AirbornLight'});
|
|
89
141
|
Expect(tmpResult).to.equal(tmpExpectedResult);
|
|
90
142
|
fDone();
|
|
91
143
|
}
|
|
92
144
|
);
|
|
145
|
+
test
|
|
146
|
+
(
|
|
147
|
+
'Async Function',
|
|
148
|
+
(fDone) =>
|
|
149
|
+
{
|
|
150
|
+
let tmpTestString = 'The <^SomeValue^> pData and Async <%AsyncThe Funny String%> up in here and a $comment$ as well.';
|
|
151
|
+
let tmpExpectedResult = 'The hash of [SomeValue] from pData is AirbornLight pData up in here and a comment as well.';
|
|
152
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
153
|
+
configMetaTemplate(testMetaTemplate);
|
|
154
|
+
let tmpResult = testMetaTemplate.parseString(tmpTestString, {SomeValue:'AirbornLight'},
|
|
155
|
+
(pError, pValue) =>
|
|
156
|
+
{
|
|
157
|
+
Expect(pValue).to.equal('The hash of [SomeValue] from pData is AirbornLight pData and Async ASYNC DATA IS [The Funny String] up in here and a comment as well.');
|
|
158
|
+
return fDone();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
test
|
|
163
|
+
(
|
|
164
|
+
'Bad pattern start parameter...',
|
|
165
|
+
(fDone) =>
|
|
166
|
+
{
|
|
167
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
168
|
+
configMetaTemplate(testMetaTemplate);
|
|
169
|
+
Expect(testMetaTemplate.addPattern('', '>', 'SHORTEST_MATCH')).to.equal(false);
|
|
170
|
+
fDone();
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
test
|
|
174
|
+
(
|
|
175
|
+
'Bad pattern end parameter...',
|
|
176
|
+
(fDone) =>
|
|
177
|
+
{
|
|
178
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
179
|
+
configMetaTemplate(testMetaTemplate);
|
|
180
|
+
Expect(testMetaTemplate.addPattern('<', '', 'SHORTEST_MATCH')).to.equal(false);
|
|
181
|
+
fDone();
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
test
|
|
185
|
+
(
|
|
186
|
+
'Identifier fallback...',
|
|
187
|
+
(fDone) =>
|
|
188
|
+
{
|
|
189
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
190
|
+
testMetaTemplate.addPattern('<', '>', 'SHORTEST_MATCH');
|
|
191
|
+
testMetaTemplate.addPattern('<<', '>', 'MEDIUM_MATCH');
|
|
192
|
+
testMetaTemplate.addPattern('<<EXTRALONG', '>', 'EXTRA_LONG_MATCH');
|
|
193
|
+
|
|
194
|
+
let tmpTestStrings = [
|
|
195
|
+
'Match this <> and this <here> please.',
|
|
196
|
+
'Match this SHORTEST_MATCH and this SHORTEST_MATCH please.',
|
|
197
|
+
|
|
198
|
+
'Match this <<> and this <<here> please.',
|
|
199
|
+
'Match this MEDIUM_MATCH and this MEDIUM_MATCH please.',
|
|
200
|
+
|
|
201
|
+
'Match this <<EXTRA> and this <<here> please.',
|
|
202
|
+
'Match this MEDIUM_MATCH and this MEDIUM_MATCH please.',
|
|
203
|
+
|
|
204
|
+
'Match this <<EXTRALONG> and this <<here> please.',
|
|
205
|
+
'Match this EXTRA_LONG_MATCH and this MEDIUM_MATCH please.',
|
|
206
|
+
|
|
207
|
+
'Match this <<<<> and this <here> please.',
|
|
208
|
+
'Match this MEDIUM_MATCH and this SHORTEST_MATCH please.'
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
let tmpResult = '';
|
|
212
|
+
// Test every pair in TestStrings
|
|
213
|
+
for (let i = 0; i < tmpTestStrings.length; i+=2)
|
|
214
|
+
{
|
|
215
|
+
tmpResult = testMetaTemplate.parseString(tmpTestStrings[i]);
|
|
216
|
+
Expect(tmpResult).to.equal(tmpTestStrings[i+1]);
|
|
217
|
+
}
|
|
218
|
+
fDone();
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
test
|
|
222
|
+
(
|
|
223
|
+
'Config magic example...',
|
|
224
|
+
(fDone) =>
|
|
225
|
+
{
|
|
226
|
+
// Use case is take a string with the following template expressions and translate them into the value from the environment variable if a default isn't passed in:
|
|
227
|
+
// 'Expressions like ${VariableWithDefault|DefaultValue} have a Default value after the pipe; others like ${VariableWithoutDefault} expressions do not have a Default value after the pipe. but should be processed properly.',
|
|
228
|
+
// 'Expressions like DefaultValue have a Default value after the pipe; others like VariableWithoutDefault expressions do not have a Default value after the pipe. but should be processed properly.',
|
|
229
|
+
|
|
230
|
+
// The usual case is just expressions in the string, but composability is fine.
|
|
231
|
+
|
|
232
|
+
let testMetaTemplate = loadMetaTemplateModule();
|
|
233
|
+
|
|
234
|
+
testMetaTemplate.addPattern('${', '}',
|
|
235
|
+
(pTemplateValue)=>
|
|
236
|
+
{
|
|
237
|
+
let tmpTemplateValue = pTemplateValue.trim();
|
|
238
|
+
|
|
239
|
+
let tmpSeparatorIndex = tmpTemplateValue.indexOf('|');
|
|
240
|
+
|
|
241
|
+
// If there is no pipe, the default value will end up being whatever the variable name is.
|
|
242
|
+
let tmpDefaultValue = tmpTemplateValue.substring(tmpSeparatorIndex+1);
|
|
243
|
+
|
|
244
|
+
let tmpEnvironmentVariableName = (tmpSeparatorIndex > -1) ? tmpTemplateValue.substring(0, tmpSeparatorIndex) : tmpTemplateValue;
|
|
245
|
+
|
|
246
|
+
if (process.env.hasOwnProperty(tmpEnvironmentVariableName))
|
|
247
|
+
{
|
|
248
|
+
return process.env[tmpEnvironmentVariableName];
|
|
249
|
+
}
|
|
250
|
+
else
|
|
251
|
+
{
|
|
252
|
+
return tmpDefaultValue;
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
let tmpTestStrings = [
|
|
257
|
+
'Expressions like ${VariableWithDefault|DefaultValue} have a Default value after the pipe; others like ${VariableWithoutDefault} expressions do not have a Default value after the pipe. but should be processed properly.',
|
|
258
|
+
'Expressions like DefaultValue have a Default value after the pipe; others like VariableWithoutDefault expressions do not have a Default value after the pipe. but should be processed properly.',
|
|
259
|
+
|
|
260
|
+
'${PATH}',
|
|
261
|
+
process.env.PATH,
|
|
262
|
+
|
|
263
|
+
'AAA ${PATH}',
|
|
264
|
+
'AAA '+process.env.PATH,
|
|
265
|
+
|
|
266
|
+
' ${PATH} AAA ${PATH}',
|
|
267
|
+
' '+process.env.PATH+' AAA '+process.env.PATH,
|
|
268
|
+
|
|
269
|
+
'AAA ${PATH} BBB',
|
|
270
|
+
'AAA '+process.env.PATH+' BBB',
|
|
271
|
+
|
|
272
|
+
'AAA ${PATH} } BBB',
|
|
273
|
+
'AAA '+process.env.PATH+' } BBB',
|
|
274
|
+
|
|
275
|
+
'AAA ${ ${PATH} BBB',
|
|
276
|
+
// Two start parameters isn't okay ---
|
|
277
|
+
// ...it passes the pattern processor the following (without quotes):
|
|
278
|
+
// " ${PATH"
|
|
279
|
+
// Which is not going to match an environment variable. With the second
|
|
280
|
+
'AAA ${PATH BBB',
|
|
281
|
+
|
|
282
|
+
'${PATH|Malarky Default Value} ZZZ',
|
|
283
|
+
process.env.PATH+' ZZZ',
|
|
284
|
+
|
|
285
|
+
'${THISISNOTANENVIRONMENTVARIABLE|Real Default Value} ZZZed',
|
|
286
|
+
'Real Default Value ZZZed',
|
|
287
|
+
|
|
288
|
+
'${ THISISNOTANENVIRONMENTVARIABLETRIMMED|Real Trimmed Default Value } ZZZed',
|
|
289
|
+
'Real Trimmed Default Value ZZZed',
|
|
290
|
+
|
|
291
|
+
'${PATH} BBB',
|
|
292
|
+
process.env.PATH+' BBB'
|
|
293
|
+
];
|
|
294
|
+
|
|
295
|
+
let tmpResult = '';
|
|
296
|
+
// Test every pair in TestStrings
|
|
297
|
+
for (let i = 0; i < tmpTestStrings.length; i+=2)
|
|
298
|
+
{
|
|
299
|
+
tmpResult = testMetaTemplate.parseString(tmpTestStrings[i]);
|
|
300
|
+
Expect(tmpResult).to.equal(tmpTestStrings[i+1]);
|
|
301
|
+
}
|
|
302
|
+
fDone();
|
|
303
|
+
}
|
|
304
|
+
);
|
|
93
305
|
}
|
|
94
306
|
);
|
|
95
307
|
}
|
package/test/RestClient_test.js
CHANGED
|
@@ -1,28 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Import Books directly from CSV to SQL.
|
|
3
|
-
|
|
4
|
-
An example of how to use the Meadow DALs directly.
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
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
|
-
// Official MySQL Client
|
|
15
|
-
const libMySQL = require('mysql2');
|
|
16
|
-
// Meadow is the DAL
|
|
17
|
-
const libMeadow = require('meadow');
|
|
18
|
-
|
|
19
|
-
const libAsync = require('async');
|
|
20
|
-
|
|
21
|
-
let _Fable = libFable.new(_Settings);
|
|
22
|
-
let _Meadow = libMeadow.new(_Fable);
|
|
23
|
-
|
|
24
|
-
_Fable.log.info("Application is starting up...");
|
|
25
|
-
|
|
26
|
-
_Fable.log.info("...Creating SQL Connection pools at "+_Fable.settings.MySQL.Server+"...");
|
|
27
|
-
// Setup SQL Connection Pool
|
|
28
|
-
_Fable.MeadowMySQLConnectionPool = libMySQL.createPool
|
|
29
|
-
(
|
|
30
|
-
{
|
|
31
|
-
connectionLimit: _Fable.settings.MySQL.ConnectionPoolLimit,
|
|
32
|
-
host: _Fable.settings.MySQL.Server,
|
|
33
|
-
port: _Fable.settings.MySQL.Port,
|
|
34
|
-
user: _Fable.settings.MySQL.User,
|
|
35
|
-
password: _Fable.settings.MySQL.Password,
|
|
36
|
-
database: _Fable.settings.MySQL.Database,
|
|
37
|
-
namedPlaceholders: true
|
|
38
|
-
}
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
// Create DAL objects
|
|
42
|
-
let _DAL = {};
|
|
43
|
-
const _BookStoreModel = require (__dirname+'/model/json_schema/BookStore-Extended.json');
|
|
44
|
-
const _BookStoreTableList = Object.keys(_BookStoreModel.Tables);
|
|
45
|
-
_Fable.log.info(`...Creating ${_BookStoreTableList.length} DAL entries...`);
|
|
46
|
-
for (let i = 0; i < _BookStoreTableList.length; i++)
|
|
47
|
-
{
|
|
48
|
-
let tmpDALEntityName = _BookStoreTableList[i];
|
|
49
|
-
_Fable.log.info(` -> Creating the ${tmpDALEntityName} DAL...`);
|
|
50
|
-
_DAL[tmpDALEntityName] = _Meadow.loadFromPackage(__dirname+'/model/meadow_schema/BookStore-MeadowSchema-'+tmpDALEntityName+'.json');
|
|
51
|
-
_DAL[tmpDALEntityName].setProvider('MySQL');
|
|
52
|
-
_DAL[tmpDALEntityName].setIDUser(99999);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const libPapa = require('papaparse');
|
|
56
|
-
const libFS = require('fs');
|
|
57
|
-
|
|
58
|
-
const _BookData = libFS.readFileSync(`${__dirname}/data/books.csv`, 'utf8');
|
|
59
|
-
|
|
60
|
-
let tmpBookMap = {};
|
|
61
|
-
let tmpAuthorMap = {};
|
|
62
|
-
|
|
63
|
-
let fImportBooks = (fCallback) =>
|
|
64
|
-
{
|
|
65
|
-
console.log('Import operation executing...');
|
|
66
|
-
let tmpCallback = (typeof(fCallback) == 'function') ? fCallback : ()=>{};
|
|
67
|
-
|
|
68
|
-
libPapa.parse(_BookData,
|
|
69
|
-
{
|
|
70
|
-
delimiter: ",",
|
|
71
|
-
header: true,
|
|
72
|
-
complete:
|
|
73
|
-
(pResults) =>
|
|
74
|
-
{
|
|
75
|
-
libAsync.waterfall([
|
|
76
|
-
(fStageComplete) =>
|
|
77
|
-
{
|
|
78
|
-
// Enumerate and insert each book
|
|
79
|
-
libAsync.eachLimit(pResults.data, 10,
|
|
80
|
-
(pBookDataRow, fCallback) =>
|
|
81
|
-
{
|
|
82
|
-
let tmpRecordToCreate = (
|
|
83
|
-
{
|
|
84
|
-
Title: pBookDataRow.original_title,
|
|
85
|
-
PublicationYear: isNaN(parseInt(pBookDataRow.original_publication_year, 10)) ? 0 : parseInt(pBookDataRow.original_publication_year, 10),
|
|
86
|
-
ISBN: pBookDataRow.isbn,
|
|
87
|
-
Type: 'Paper',
|
|
88
|
-
Genre: 'UNKNOWN',
|
|
89
|
-
Language: pBookDataRow.language_code,
|
|
90
|
-
ImageURL: pBookDataRow.image_url
|
|
91
|
-
});
|
|
92
|
-
let tmpQuery = _DAL.Book.query;
|
|
93
|
-
//tmpQuery.setLogLevel(5);
|
|
94
|
-
tmpQuery.addRecord(tmpRecordToCreate);
|
|
95
|
-
_DAL.Book.doCreate(tmpQuery,
|
|
96
|
-
(pError, pQuery, pQueryRead, pRecord)=>
|
|
97
|
-
{
|
|
98
|
-
// Add it to the book map
|
|
99
|
-
if (!pError)
|
|
100
|
-
{
|
|
101
|
-
tmpBookMap[pBookDataRow.id] = pRecord.IDBook;
|
|
102
|
-
//_Fable.log.info('Imported book ID '+pRecord.IDBook+' title ['+pRecord.Title+']');
|
|
103
|
-
}
|
|
104
|
-
fCallback(pError);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
},
|
|
108
|
-
(pError)=>
|
|
109
|
-
{
|
|
110
|
-
_Fable.log.info('...Book Import operation complete!');
|
|
111
|
-
fStageComplete()
|
|
112
|
-
});
|
|
113
|
-
},
|
|
114
|
-
(fStageComplete) =>
|
|
115
|
-
{
|
|
116
|
-
// Enumerate and insert each author
|
|
117
|
-
libAsync.eachLimit(pResults.data, 10,
|
|
118
|
-
(pBookDataRow, fCallback) =>
|
|
119
|
-
{
|
|
120
|
-
if (!pBookDataRow.hasOwnProperty('authors'))
|
|
121
|
-
return fCallback();
|
|
122
|
-
|
|
123
|
-
let tmpAuthorsToCreate = pBookDataRow.authors.split(',');
|
|
124
|
-
|
|
125
|
-
libAsync.eachLimit(tmpAuthorsToCreate, 1,
|
|
126
|
-
(pAuthor, fAuthorInsertCallback)=>
|
|
127
|
-
{
|
|
128
|
-
if (tmpAuthorMap.hasOwnProperty(pAuthor))
|
|
129
|
-
{
|
|
130
|
-
return fAuthorInsertCallback();
|
|
131
|
-
}
|
|
132
|
-
else
|
|
133
|
-
{
|
|
134
|
-
tmpAuthorMap[pAuthor] = false;
|
|
135
|
-
}
|
|
136
|
-
let tmpRecordToCreate = (
|
|
137
|
-
{
|
|
138
|
-
Name: pAuthor
|
|
139
|
-
});
|
|
140
|
-
let tmpQuery = _DAL.Author.query.addRecord(tmpRecordToCreate);
|
|
141
|
-
_DAL.Author.doCreate(tmpQuery,
|
|
142
|
-
(pError, pQuery, pQueryRead, pRecord)=>
|
|
143
|
-
{
|
|
144
|
-
if (!pError)
|
|
145
|
-
{
|
|
146
|
-
tmpAuthorMap[pRecord.Name] = pRecord.IDAuthor;
|
|
147
|
-
//_Fable.log.info('Imported Author ID '+pRecord.IDAuthor+' named ['+pRecord.Name+']');
|
|
148
|
-
}
|
|
149
|
-
return fAuthorInsertCallback(pError);
|
|
150
|
-
});
|
|
151
|
-
},
|
|
152
|
-
(pError)=>
|
|
153
|
-
{
|
|
154
|
-
return fCallback(pError);
|
|
155
|
-
});
|
|
156
|
-
},
|
|
157
|
-
(pError)=>
|
|
158
|
-
{
|
|
159
|
-
_Fable.log.info('...Author Import operation complete!');
|
|
160
|
-
fStageComplete();
|
|
161
|
-
});
|
|
162
|
-
},
|
|
163
|
-
(fStageComplete) =>
|
|
164
|
-
{
|
|
165
|
-
// Create Book->Author joins
|
|
166
|
-
libAsync.eachLimit(pResults.data, 10,
|
|
167
|
-
(pBookDataRow, fCallback) =>
|
|
168
|
-
{
|
|
169
|
-
if (!pBookDataRow.hasOwnProperty('authors'))
|
|
170
|
-
return fCallback();
|
|
171
|
-
|
|
172
|
-
let tmpAuthorJoinsToCreate = pBookDataRow.authors.split(',');
|
|
173
|
-
|
|
174
|
-
libAsync.eachLimit(tmpAuthorJoinsToCreate, 1,
|
|
175
|
-
(pAuthor, fAuthorJoinInsertCallback)=>
|
|
176
|
-
{
|
|
177
|
-
let tmpRecordToCreate = (
|
|
178
|
-
{
|
|
179
|
-
IDBook: tmpBookMap[pBookDataRow.id],
|
|
180
|
-
IDAuthor: tmpAuthorMap[pAuthor]
|
|
181
|
-
});
|
|
182
|
-
let tmpQuery = _DAL.BookAuthorJoin.query.addRecord(tmpRecordToCreate);
|
|
183
|
-
_DAL.BookAuthorJoin.doCreate(tmpQuery,
|
|
184
|
-
(pError, pQuery, pQueryRead, pRecord)=>
|
|
185
|
-
{
|
|
186
|
-
if (!pError)
|
|
187
|
-
{
|
|
188
|
-
//_Fable.log.info(`Joined author ${pAuthor} ID ${pRecord.IDAuthor} to book ID ${pRecord.IDBook}`);
|
|
189
|
-
}
|
|
190
|
-
return fAuthorJoinInsertCallback(pError);
|
|
191
|
-
});
|
|
192
|
-
},
|
|
193
|
-
(pError)=>
|
|
194
|
-
{
|
|
195
|
-
return fCallback(pError);
|
|
196
|
-
});
|
|
197
|
-
},
|
|
198
|
-
(pError)=>
|
|
199
|
-
{
|
|
200
|
-
_Fable.log.info('...Join Import operation complete!');
|
|
201
|
-
return fStageComplete(pError);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
],
|
|
205
|
-
(pError)=>
|
|
206
|
-
{
|
|
207
|
-
_Fable.log.info('Full import operation has completed!')
|
|
208
|
-
tmpCallback(pError);
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
module.exports = fImportBooks;
|