fable 3.1.32 → 3.1.33
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/dist/fable.js +463 -370
- package/dist/fable.js.map +1 -1
- package/dist/fable.min.js +2 -2
- package/dist/fable.min.js.map +1 -1
- package/example_applications/mathematical_playground/README.md +27 -0
- package/package.json +2 -2
- package/source/Fable.js +0 -1
- package/source/services/Fable-Service-CSVParser.js +177 -177
- package/source/services/Fable-Service-DataFormat.js +22 -22
- package/source/services/Fable-Service-DataGeneration.js +161 -161
- package/source/services/Fable-Service-DateManipulation.js +209 -209
- package/source/services/Fable-Service-EnvironmentData-Web.js +3 -3
- package/source/services/Fable-Service-EnvironmentData.js +3 -3
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer-DirectiveMutation.js +136 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js +6 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +39 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js +2 -2
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json +9 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ValueMarshal.js +2 -2
- package/source/services/Fable-Service-ExpressionParser.js +124 -22
- package/source/services/Fable-Service-FilePersistence.js +2 -2
- package/source/services/Fable-Service-Logic.js +1 -1
- package/source/services/Fable-Service-Math.js +293 -57
- package/source/services/Fable-Service-MetaTemplate.js +2 -2
- package/source/services/Fable-Service-Operation.js +7 -7
- package/source/services/Fable-Service-ProgressTime.js +3 -3
- package/source/services/Fable-Service-RestClient.js +2 -2
- package/source/services/Fable-Service-Template.js +4 -4
- package/source/services/Fable-Service-Utility.js +6 -6
- package/test/ExpressionParser_tests.js +53 -0
- package/test/Math_test.js +81 -1
- package/source/services/Fable-Service-ExpressionParser/RNI_Randy.json +0 -1
- package/source/services/Fable-Service-ExpressionParser/RNI_Tool.json +0 -1
|
@@ -294,6 +294,11 @@
|
|
|
294
294
|
"Address": "fable.Math.cleanValueObject"
|
|
295
295
|
},
|
|
296
296
|
|
|
297
|
+
"polynomialregression": {
|
|
298
|
+
"Name": "Perform an nth degree Polynomial Regression on a Set of X and Y Values",
|
|
299
|
+
"Address": "fable.Math.polynomialRegression"
|
|
300
|
+
},
|
|
301
|
+
|
|
297
302
|
"randominteger": {
|
|
298
303
|
"Name": "Random Integer",
|
|
299
304
|
"Address": "fable.DataGeneration.randomInteger"
|
|
@@ -397,5 +402,39 @@
|
|
|
397
402
|
"createvalueobjectbyhashes": {
|
|
398
403
|
"Name": "Create Value Object by Hashes",
|
|
399
404
|
"Address": "fable.Utility.createValueObjectByHashes"
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
"polynomialregression": {
|
|
408
|
+
"Name": "Perform an nth degree Polynomial Regression on a Set of X and Y Values",
|
|
409
|
+
"Address": "fable.Math.polynomialRegression"
|
|
410
|
+
},
|
|
411
|
+
"leastsquares": {
|
|
412
|
+
"Name": "Perform a Least Squares Regression on a Set of Independent Variable Vectors and a Dependent Variable Vector",
|
|
413
|
+
"Address": "fable.Math.leastSquares"
|
|
414
|
+
},
|
|
415
|
+
"linest": {
|
|
416
|
+
"Name": "Perform a Least Squares Regression on a Set of Independent Variable Vectors and a Dependent Variable Vector",
|
|
417
|
+
"Address": "fable.Math.leastSquares"
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
"matrixtranspose": {
|
|
421
|
+
"Name": "Transpose a Matrix",
|
|
422
|
+
"Address": "fable.Math.matrixTranspose"
|
|
423
|
+
},
|
|
424
|
+
"matrixmultiply": {
|
|
425
|
+
"Name": "Multiply Two Matrices",
|
|
426
|
+
"Address": "fable.Math.matrixMultiply"
|
|
427
|
+
},
|
|
428
|
+
"matrixvectormultiply": {
|
|
429
|
+
"Name": "Multiply a Matrix by a Vector",
|
|
430
|
+
"Address": "fable.Math.matrixVectorMultiply"
|
|
431
|
+
},
|
|
432
|
+
"matrixinverse": {
|
|
433
|
+
"Name": "Inverse a Matrix",
|
|
434
|
+
"Address": "fable.Math.matrixInverse"
|
|
435
|
+
},
|
|
436
|
+
"gaussianelimination": {
|
|
437
|
+
"Name": "Solve a System of Linear Equations using Gaussian Elimination",
|
|
438
|
+
"Address": "fable.Math.gaussianElimination"
|
|
400
439
|
}
|
|
401
440
|
}
|
|
@@ -135,7 +135,7 @@ class ExpressionParserSolver extends libExpressionParserOperationBase
|
|
|
135
135
|
catch (pError)
|
|
136
136
|
{
|
|
137
137
|
tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ${i} with function ${tmpStepResultObject.ExpressionStep.Operation.Token}: ${pError}`);
|
|
138
|
-
this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
138
|
+
this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1], { Stack: pError.stack });
|
|
139
139
|
return false;
|
|
140
140
|
}
|
|
141
141
|
}
|
|
@@ -151,7 +151,7 @@ class ExpressionParserSolver extends libExpressionParserOperationBase
|
|
|
151
151
|
catch (pError)
|
|
152
152
|
{
|
|
153
153
|
tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ${i} with function ${tmpStepResultObject.ExpressionStep.Operation.Token}: ${pError}`);
|
|
154
|
-
this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
154
|
+
this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1], { Stack: pError.stack });
|
|
155
155
|
return false;
|
|
156
156
|
}
|
|
157
157
|
}
|
package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json
CHANGED
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
"Type": "Assignment"
|
|
9
9
|
},
|
|
10
10
|
|
|
11
|
+
":":
|
|
12
|
+
{
|
|
13
|
+
"Name": "Expression Begin",
|
|
14
|
+
"Token": ":",
|
|
15
|
+
"Function": "fable.Math.expressionBegin",
|
|
16
|
+
"Precedence": 0,
|
|
17
|
+
"Type": "Assignment"
|
|
18
|
+
},
|
|
19
|
+
|
|
11
20
|
"?=":
|
|
12
21
|
{
|
|
13
22
|
"Name": "Null or Empty Coalescing Assign Value",
|
|
@@ -10,7 +10,7 @@ class ExpressionParserValueMarshal extends libExpressionParserOperationBase
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Substitutes values in tokenized objects based on the provided data source and manifest.
|
|
13
|
-
*
|
|
13
|
+
*
|
|
14
14
|
* TODO: Move this to its own file in the "Fable-Service-ExpressionParser" directory.
|
|
15
15
|
*
|
|
16
16
|
* @param {Array} pTokenizedObjects - The array of tokenized objects.
|
|
@@ -154,4 +154,4 @@ class ExpressionParserValueMarshal extends libExpressionParserOperationBase
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
module.exports = ExpressionParserValueMarshal;
|
|
157
|
+
module.exports = ExpressionParserValueMarshal;
|
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
const { PE } = require('big.js');
|
|
2
1
|
const libFableServiceBase = require('fable-serviceproviderbase');
|
|
3
2
|
|
|
4
3
|
/* Trying a different pattern for this service ...
|
|
5
4
|
*
|
|
6
5
|
* This service is a simple expression parser that can handle math expressions, with magic(tm) lookup of addresses with a manifest.
|
|
7
|
-
*
|
|
6
|
+
*
|
|
8
7
|
* Each method works multiple ways.
|
|
9
|
-
*
|
|
8
|
+
*
|
|
10
9
|
* 1. You can pass in a results object, and, it will put the state for that step outcome into the results object.
|
|
11
10
|
* 2. It always returns the state, and works without the results object.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
*
|
|
12
|
+
*
|
|
14
13
|
* Learned a lot from this npm package: https://www.npmjs.com/package/math-expression-evaluator
|
|
15
14
|
* And its related code at github: https://github.com/bugwheels94/math-expression-evaluator
|
|
16
|
-
*
|
|
15
|
+
*
|
|
17
16
|
* There were two problems with the codebase above...
|
|
18
|
-
*
|
|
17
|
+
*
|
|
19
18
|
* First, the code was very unreadable and determining it was correct or extending it
|
|
20
19
|
* was out of the question.
|
|
21
|
-
*
|
|
20
|
+
*
|
|
22
21
|
* Second, and this is a larger issue, is that we need the expressions to be parsed as
|
|
23
22
|
* arbitrary precision. When I determined that extending the library to use string-based
|
|
24
23
|
* numbers and an arbitrary precision library as the back-end would have taken a significantly
|
|
@@ -37,6 +36,11 @@ class FableServiceExpressionParser extends libFableServiceBase
|
|
|
37
36
|
{
|
|
38
37
|
super(pFable, pOptions, pServiceHash);
|
|
39
38
|
|
|
39
|
+
/** @type {import('../Fable.js') & { Math: import('./Fable-Service-Math.js') }} */
|
|
40
|
+
this.fable;
|
|
41
|
+
/** @type {any} */
|
|
42
|
+
this.log;
|
|
43
|
+
|
|
40
44
|
// The configuration for tokens that the solver recognizes, with precedence and friendly names.
|
|
41
45
|
this.tokenMap = require('./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json');
|
|
42
46
|
|
|
@@ -88,6 +92,7 @@ class FableServiceExpressionParser extends libFableServiceBase
|
|
|
88
92
|
|
|
89
93
|
// These are sub-services for the tokenizer, linter, compiler, marshaler and solver.
|
|
90
94
|
this.fable.addServiceTypeIfNotExists('ExpressionParser-Tokenizer', require('./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js'));
|
|
95
|
+
this.fable.addServiceTypeIfNotExists('ExpressionParser-TokenizerDirectiveMutation', require('./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer-DirectiveMutation.js'));
|
|
91
96
|
this.fable.addServiceTypeIfNotExists('ExpressionParser-Linter', require('./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Linter.js'));
|
|
92
97
|
this.fable.addServiceTypeIfNotExists('ExpressionParser-Postfix', require('./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Postfix.js'));
|
|
93
98
|
this.fable.addServiceTypeIfNotExists('ExpressionParser-ValueMarshal', require('./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ValueMarshal.js'));
|
|
@@ -98,6 +103,7 @@ class FableServiceExpressionParser extends libFableServiceBase
|
|
|
98
103
|
|
|
99
104
|
// This code instantitates these fable services to child objects of this service, but does not pollute the main fable with them.
|
|
100
105
|
this.Tokenizer = this.fable.instantiateServiceProviderWithoutRegistration('ExpressionParser-Tokenizer');
|
|
106
|
+
this.Tokenizer.TokenizerDirectiveMutation = this.fable.instantiateServiceProviderWithoutRegistration('ExpressionParser-TokenizerDirectiveMutation');
|
|
101
107
|
this.Linter = this.fable.instantiateServiceProviderWithoutRegistration('ExpressionParser-Linter');
|
|
102
108
|
this.Postfix = this.fable.instantiateServiceProviderWithoutRegistration('ExpressionParser-Postfix');
|
|
103
109
|
this.ValueMarshal = this.fable.instantiateServiceProviderWithoutRegistration('ExpressionParser-ValueMarshal');
|
|
@@ -113,7 +119,7 @@ class FableServiceExpressionParser extends libFableServiceBase
|
|
|
113
119
|
this.Messaging.connectExpressionParser(this);
|
|
114
120
|
|
|
115
121
|
this.GenericManifest = this.fable.newManyfest();
|
|
116
|
-
|
|
122
|
+
|
|
117
123
|
// This will look for a LogNoisiness on fable (or one that falls in from pict) and if it doesn't exist, set one for this service.
|
|
118
124
|
this.LogNoisiness = ('LogNoisiness' in this.fable) ? this.fable.LogNoisiness : 0;
|
|
119
125
|
}
|
|
@@ -156,7 +162,7 @@ class FableServiceExpressionParser extends libFableServiceBase
|
|
|
156
162
|
|
|
157
163
|
/**
|
|
158
164
|
* Substitutes values in tokenized objects.
|
|
159
|
-
*
|
|
165
|
+
*
|
|
160
166
|
* This means marshaling data from pDataSource into the array of objects with the passed in Manifest (or a generic manifest) to prepare for solving.
|
|
161
167
|
*
|
|
162
168
|
* @param {Array} pTokenizedObjects - The array of tokenized objects.
|
|
@@ -186,12 +192,12 @@ class FableServiceExpressionParser extends libFableServiceBase
|
|
|
186
192
|
|
|
187
193
|
/**
|
|
188
194
|
* Solves the given expression using the provided data and manifest.
|
|
189
|
-
*
|
|
195
|
+
*
|
|
190
196
|
* @param {string} pExpression - The expression to solve.
|
|
191
|
-
* @param {
|
|
192
|
-
* @param {
|
|
193
|
-
* @param {
|
|
194
|
-
* @param {
|
|
197
|
+
* @param {Record<string, any>} [pDataSourceObject] - (optional) The data source object (e.g. AppData).
|
|
198
|
+
* @param {Record<string, any>} [pResultObject] - (optional) The result object containing the full postfix expression list, internal variables and solver history.
|
|
199
|
+
* @param {import('manyfest')} [pManifest] - (optional) The manifest object for dereferencing variables.
|
|
200
|
+
* @param {Record<string, any>} [pDataDestinationObject] - (optional) The data destination object for where to marshal the result into.
|
|
195
201
|
* @returns {any} - The result of solving the expression.
|
|
196
202
|
*/
|
|
197
203
|
solve(pExpression, pDataSourceObject, pResultObject, pManifest, pDataDestinationObject)
|
|
@@ -202,15 +208,111 @@ class FableServiceExpressionParser extends libFableServiceBase
|
|
|
202
208
|
|
|
203
209
|
// This is technically a "pre-compile" and we can keep this Results Object around to reuse for better performance. Not required.
|
|
204
210
|
this.tokenize(pExpression, tmpResultsObject);
|
|
211
|
+
|
|
212
|
+
// Lint the tokenized expression to make sure it's valid
|
|
205
213
|
this.lintTokenizedExpression(tmpResultsObject.RawTokens, tmpResultsObject);
|
|
206
214
|
this.buildPostfixedSolveList(tmpResultsObject.RawTokens, tmpResultsObject);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
215
|
+
|
|
216
|
+
if (tmpResultsObject.SolverDirectives.Code == 'SERIES')
|
|
217
|
+
{
|
|
218
|
+
// Make sure tmpResultsObject.SolverDirective values for From: null, To: null, Step: null are all numeric and non-zero where applicable
|
|
219
|
+
let tmpFrom = this.fable.Math.parsePrecise(tmpResultsObject.SolverDirectives.From, NaN);
|
|
220
|
+
let tmpTo = this.fable.Math.parsePrecise(tmpResultsObject.SolverDirectives.To, NaN);
|
|
221
|
+
let tmpStep = this.fable.Math.parsePrecise(tmpResultsObject.SolverDirectives.Step, NaN);
|
|
222
|
+
|
|
223
|
+
if (isNaN(tmpStep))
|
|
224
|
+
{
|
|
225
|
+
tmpStep = '1';
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (isNaN(tmpFrom) || isNaN(tmpTo))
|
|
229
|
+
{
|
|
230
|
+
tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. FROM, TO must be numeric.`);
|
|
231
|
+
this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Make sure from/to are not equal
|
|
236
|
+
if (this.fable.Math.comparePrecise(tmpFrom, tmpTo) == 0)
|
|
237
|
+
{
|
|
238
|
+
tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. FROM and TO cannot be equal.`);
|
|
239
|
+
this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Make sure that Step is the correct positive/negative based on From and To
|
|
244
|
+
if (this.fable.Math.comparePrecise(tmpStep, '0') == 0)
|
|
245
|
+
{
|
|
246
|
+
tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. STEP cannot be zero.`);
|
|
247
|
+
this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
if (this.fable.Math.comparePrecise(tmpFrom, tmpTo) < 0)
|
|
251
|
+
{
|
|
252
|
+
// From < To so Step must be positive
|
|
253
|
+
if (this.fable.Math.comparePrecise(tmpStep, '0') < 0)
|
|
254
|
+
{
|
|
255
|
+
tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. STEP must be positive when FROM < TO.`);
|
|
256
|
+
this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
else
|
|
261
|
+
{
|
|
262
|
+
// From >= To so Step must be negative
|
|
263
|
+
if (this.fable.Math.comparePrecise(tmpStep, '0') > 0)
|
|
264
|
+
{
|
|
265
|
+
tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. STEP must be negative when FROM >= TO.`);
|
|
266
|
+
this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Get the number of iterations we need to perform
|
|
272
|
+
let tmpIterations = parseInt(this.fable.Math.floorPrecise(this.fable.Math.dividePrecise(this.fable.Math.subtractPrecise(tmpTo, tmpFrom), tmpStep)));
|
|
273
|
+
|
|
274
|
+
let tmpValueArray = [];
|
|
275
|
+
|
|
276
|
+
for (let i = 0; i <= tmpIterations; i++)
|
|
277
|
+
{
|
|
278
|
+
let tmpCurrentValueOfN = this.fable.Math.addPrecise(tmpFrom, this.fable.Math.multiplyPrecise(tmpStep, i.toString()));
|
|
279
|
+
|
|
280
|
+
// Jimmy up the data source with the current N value, stepIndex and all the other data from the source object
|
|
281
|
+
// This generates a data source object every time on purpose so we can remarshal in values that changed in the destination
|
|
282
|
+
let tmpSeriesStepDataSourceObject = Object.assign({}, tmpDataSourceObject);
|
|
283
|
+
tmpSeriesStepDataSourceObject.n = tmpCurrentValueOfN;
|
|
284
|
+
tmpSeriesStepDataSourceObject.stepIndex = i;
|
|
285
|
+
|
|
286
|
+
let tmpMutatedValues = this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects, tmpSeriesStepDataSourceObject, tmpResultsObject, pManifest);
|
|
287
|
+
|
|
288
|
+
tmpValueArray.push( this.solvePostfixedExpression( tmpResultsObject.PostfixSolveList, tmpDataDestinationObject, tmpResultsObject, pManifest) );
|
|
289
|
+
|
|
290
|
+
for (let j = 0; j < tmpMutatedValues.length; j++)
|
|
291
|
+
{
|
|
292
|
+
tmpMutatedValues[j].Resolved = false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Do the assignment
|
|
297
|
+
let tmpAssignmentManifestHash = tmpResultsObject.PostfixedAssignmentAddress;
|
|
298
|
+
if ((tmpResultsObject.OriginalRawTokens[1] === '=') && (typeof(tmpResultsObject.OriginalRawTokens[0]) === 'string') && (tmpResultsObject.OriginalRawTokens[0].length > 0))
|
|
299
|
+
{
|
|
300
|
+
tmpAssignmentManifestHash = tmpResultsObject.OriginalRawTokens[0];
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
let tmpManifest = (typeof(pManifest) === 'object') ? pManifest : this.fable.newManyfest();
|
|
304
|
+
tmpManifest.setValueByHash(tmpDataDestinationObject, tmpAssignmentManifestHash, tmpValueArray);
|
|
305
|
+
|
|
306
|
+
return tmpValueArray;
|
|
307
|
+
}
|
|
308
|
+
else // For 'SOLVE' or anything else that didn't work
|
|
309
|
+
{
|
|
310
|
+
// This is where the data from variables gets marshaled into their symbols (from AppData or the like)
|
|
311
|
+
this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects, tmpDataSourceObject, tmpResultsObject, pManifest);
|
|
312
|
+
// Finally this is the expr solving method, which returns a string and also marshals it into tmpDataDestinationObject
|
|
313
|
+
return this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList, tmpDataDestinationObject, tmpResultsObject, pManifest);
|
|
314
|
+
}
|
|
213
315
|
}
|
|
214
316
|
}
|
|
215
317
|
|
|
216
|
-
module.exports = FableServiceExpressionParser;
|
|
318
|
+
module.exports = FableServiceExpressionParser;
|
|
@@ -86,7 +86,7 @@ class FableServiceFilePersistence extends libFableServiceBase
|
|
|
86
86
|
{
|
|
87
87
|
this.fable.log.error(`CSV Read of ${pFilePath} Error: ${pError}`, pError);
|
|
88
88
|
};
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
return this.lineReaderFactory(pFilePath,
|
|
91
91
|
(pLine) =>
|
|
92
92
|
{
|
|
@@ -265,4 +265,4 @@ class FableServiceFilePersistence extends libFableServiceBase
|
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
-
module.exports = FableServiceFilePersistence;
|
|
268
|
+
module.exports = FableServiceFilePersistence;
|