manyfest 1.0.43 → 1.0.46

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.
@@ -1,3010 +0,0 @@
1
- "use strict";
2
-
3
- function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
4
- function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
5
- function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
6
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
7
- function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
8
- function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
9
- function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
10
- function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
11
- function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
12
- function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
13
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
14
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
15
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
16
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
17
- (function (f) {
18
- if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object" && typeof module !== "undefined") {
19
- module.exports = f();
20
- } else if (typeof define === "function" && define.amd) {
21
- define([], f);
22
- } else {
23
- var g;
24
- if (typeof window !== "undefined") {
25
- g = window;
26
- } else if (typeof global !== "undefined") {
27
- g = global;
28
- } else if (typeof self !== "undefined") {
29
- g = self;
30
- } else {
31
- g = this;
32
- }
33
- g.Manyfest = f();
34
- }
35
- })(function () {
36
- var define, module, exports;
37
- return function () {
38
- function r(e, n, t) {
39
- function o(i, f) {
40
- if (!n[i]) {
41
- if (!e[i]) {
42
- var c = "function" == typeof require && require;
43
- if (!f && c) return c(i, !0);
44
- if (u) return u(i, !0);
45
- var a = new Error("Cannot find module '" + i + "'");
46
- throw a.code = "MODULE_NOT_FOUND", a;
47
- }
48
- var p = n[i] = {
49
- exports: {}
50
- };
51
- e[i][0].call(p.exports, function (r) {
52
- var n = e[i][1][r];
53
- return o(n || r);
54
- }, p, p.exports, r, e, n, t);
55
- }
56
- return n[i].exports;
57
- }
58
- for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]);
59
- return o;
60
- }
61
- return r;
62
- }()({
63
- 1: [function (require, module, exports) {
64
- module.exports = {
65
- "name": "fable-serviceproviderbase",
66
- "version": "3.0.15",
67
- "description": "Simple base classes for fable services.",
68
- "main": "source/Fable-ServiceProviderBase.js",
69
- "scripts": {
70
- "start": "node source/Fable-ServiceProviderBase.js",
71
- "test": "npx mocha -u tdd -R spec",
72
- "tests": "npx mocha -u tdd --exit -R spec --grep",
73
- "coverage": "npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec",
74
- "build": "npx quack build"
75
- },
76
- "mocha": {
77
- "diff": true,
78
- "extension": ["js"],
79
- "package": "./package.json",
80
- "reporter": "spec",
81
- "slow": "75",
82
- "timeout": "5000",
83
- "ui": "tdd",
84
- "watch-files": ["source/**/*.js", "test/**/*.js"],
85
- "watch-ignore": ["lib/vendor"]
86
- },
87
- "repository": {
88
- "type": "git",
89
- "url": "https://github.com/stevenvelozo/fable-serviceproviderbase.git"
90
- },
91
- "keywords": ["entity", "behavior"],
92
- "author": "Steven Velozo <steven@velozo.com> (http://velozo.com/)",
93
- "license": "MIT",
94
- "bugs": {
95
- "url": "https://github.com/stevenvelozo/fable-serviceproviderbase/issues"
96
- },
97
- "homepage": "https://github.com/stevenvelozo/fable-serviceproviderbase",
98
- "devDependencies": {
99
- "fable": "^3.0.143",
100
- "quackage": "^1.0.33"
101
- }
102
- };
103
- }, {}],
104
- 2: [function (require, module, exports) {
105
- /**
106
- * Fable Service Base
107
- * @author <steven@velozo.com>
108
- */
109
-
110
- var libPackage = require('../package.json');
111
- var FableServiceProviderBase = /*#__PURE__*/function () {
112
- // The constructor can be used in two ways:
113
- // 1) With a fable, options object and service hash (the options object and service hash are optional)
114
- // 2) With an object or nothing as the first parameter, where it will be treated as the options object
115
- function FableServiceProviderBase(pFable, pOptions, pServiceHash) {
116
- _classCallCheck(this, FableServiceProviderBase);
117
- // Check if a fable was passed in; connect it if so
118
- if (_typeof(pFable) === 'object' && pFable.isFable) {
119
- this.connectFable(pFable);
120
- } else {
121
- this.fable = false;
122
- }
123
-
124
- // Initialize the services map if it wasn't passed in
125
- /** @type {Object} */
126
- this._PackageFableServiceProvider = libPackage;
127
-
128
- // initialize options and UUID based on whether the fable was passed in or not.
129
- if (this.fable) {
130
- this.UUID = pFable.getUUID();
131
- this.options = _typeof(pOptions) === 'object' ? pOptions : {};
132
- } else {
133
- // With no fable, check to see if there was an object passed into either of the first two
134
- // Parameters, and if so, treat it as the options object
135
- this.options = _typeof(pFable) === 'object' && !pFable.isFable ? pFable : _typeof(pOptions) === 'object' ? pOptions : {};
136
- this.UUID = "CORE-SVC-".concat(Math.floor(Math.random() * (99999 - 10000) + 10000));
137
- }
138
-
139
- // It's expected that the deriving class will set this
140
- this.serviceType = "Unknown-".concat(this.UUID);
141
-
142
- // The service hash is used to identify the specific instantiation of the service in the services map
143
- this.Hash = typeof pServiceHash === 'string' ? pServiceHash : !this.fable && typeof pOptions === 'string' ? pOptions : "".concat(this.UUID);
144
- }
145
- return _createClass(FableServiceProviderBase, [{
146
- key: "connectFable",
147
- value: function connectFable(pFable) {
148
- if (_typeof(pFable) !== 'object' || !pFable.isFable) {
149
- var tmpErrorMessage = "Fable Service Provider Base: Cannot connect to Fable, invalid Fable object passed in. The pFable parameter was a [".concat(_typeof(pFable), "].}");
150
- console.log(tmpErrorMessage);
151
- return new Error(tmpErrorMessage);
152
- }
153
- if (!this.fable) {
154
- this.fable = pFable;
155
- }
156
- if (!this.log) {
157
- this.log = this.fable.Logging;
158
- }
159
- if (!this.services) {
160
- this.services = this.fable.services;
161
- }
162
- if (!this.servicesMap) {
163
- this.servicesMap = this.fable.servicesMap;
164
- }
165
- return true;
166
- }
167
- }]);
168
- }();
169
- _defineProperty(FableServiceProviderBase, "isFableService", true);
170
- module.exports = FableServiceProviderBase;
171
-
172
- // This is left here in case we want to go back to having different code/base class for "core" services
173
- module.exports.CoreServiceProviderBase = FableServiceProviderBase;
174
- }, {
175
- "../package.json": 1
176
- }],
177
- 3: [function (require, module, exports) {
178
- // When a boxed property is passed in, it should have quotes of some
179
- // kind around it.
180
- //
181
- // For instance:
182
- // MyValues['Name']
183
- // MyValues["Age"]
184
- // MyValues[`Cost`]
185
- //
186
- // This function removes the wrapping quotes.
187
- //
188
- // Please note it *DOES NOT PARSE* template literals, so backticks just
189
- // end up doing the same thing as other quote types.
190
- //
191
- // TODO: Should template literals be processed? If so what state do they have access to? That should happen here if so.
192
- // TODO: Make a simple class include library with these
193
- /**
194
- * @param {string} pCharacter - The character to remove from the start and end of the string
195
- * @param {string} pString - The string to clean
196
- *
197
- * @return {string} The cleaned string
198
- */
199
- var cleanWrapCharacters = function cleanWrapCharacters(pCharacter, pString) {
200
- if (pString.startsWith(pCharacter) && pString.endsWith(pCharacter)) {
201
- return pString.substring(1, pString.length - 1);
202
- } else {
203
- return pString;
204
- }
205
- };
206
- module.exports = cleanWrapCharacters;
207
- }, {}],
208
- 4: [function (require, module, exports) {
209
- /**
210
- * @author <steven@velozo.com>
211
- */
212
- var libSimpleLog = require('./Manyfest-LogToConsole.js');
213
-
214
- /**
215
- * Hash Translation
216
- *
217
- * This is a very simple translation table for hashes, which allows the same schema to resolve
218
- * differently based on a loaded translation table.
219
- *
220
- * This is to prevent the requirement for mutating schemas over and over again when we want to
221
- * reuse the structure but look up data elements by different addresses.
222
- *
223
- * One side-effect of this is that a translation table can "override" the built-in hashes, since
224
- * this is always used to resolve hashes before any of the functionCallByHash(pHash, ...) perform
225
- * their lookups by hash.
226
- *
227
- * @class ManyfestHashTranslation
228
- */
229
- var ManyfestHashTranslation = /*#__PURE__*/function () {
230
- /**
231
- * @param {function} [pInfoLog] - (optional) A logging function for info messages
232
- * @param {function} [pErrorLog] - (optional) A logging function for error messages
233
- */
234
- function ManyfestHashTranslation(pInfoLog, pErrorLog) {
235
- _classCallCheck(this, ManyfestHashTranslation);
236
- // Wire in logging
237
- this.logInfo = typeof pInfoLog === 'function' ? pInfoLog : libSimpleLog;
238
- this.logError = typeof pErrorLog === 'function' ? pErrorLog : libSimpleLog;
239
- this.translationTable = {};
240
- }
241
-
242
- /**
243
- * @return {number} The number of translations in the table
244
- */
245
- return _createClass(ManyfestHashTranslation, [{
246
- key: "translationCount",
247
- value: function translationCount() {
248
- return Object.keys(this.translationTable).length;
249
- }
250
-
251
- /**
252
- * @param {object} pTranslation - An object containing source:destination hash pairs to add to the translation table
253
- */
254
- }, {
255
- key: "addTranslation",
256
- value: function addTranslation(pTranslation) {
257
- var _this = this;
258
- // This adds a translation in the form of:
259
- // { "SourceHash": "DestinationHash", "SecondSourceHash":"SecondDestinationHash" }
260
- if (_typeof(pTranslation) != 'object') {
261
- this.logError("Hash translation addTranslation expected a translation be type object but was passed in ".concat(_typeof(pTranslation)));
262
- return false;
263
- }
264
- var tmpTranslationSources = Object.keys(pTranslation);
265
- tmpTranslationSources.forEach(function (pTranslationSource) {
266
- if (typeof pTranslation[pTranslationSource] != 'string') {
267
- _this.logError("Hash translation addTranslation expected a translation destination hash for [".concat(pTranslationSource, "] to be a string but the referrant was a ").concat(_typeof(pTranslation[pTranslationSource])));
268
- } else {
269
- _this.translationTable[pTranslationSource] = pTranslation[pTranslationSource];
270
- }
271
- });
272
- }
273
-
274
- /**
275
- * @param {string} pTranslationHash - The source hash to remove from the translation table
276
- */
277
- }, {
278
- key: "removeTranslationHash",
279
- value: function removeTranslationHash(pTranslationHash) {
280
- delete this.translationTable[pTranslationHash];
281
- }
282
-
283
- /**
284
- * This removes translations.
285
- * If passed a string, just removes the single one.
286
- * If passed an object, it does all the source keys.
287
- *
288
- * @param {string|object} pTranslation - Either a source hash string to remove, or an object containing source:destination hash pairs to remove
289
- *
290
- * @return {boolean} True if the removal was successful, false otherwise
291
- */
292
- }, {
293
- key: "removeTranslation",
294
- value: function removeTranslation(pTranslation) {
295
- var _this2 = this;
296
- if (typeof pTranslation == 'string') {
297
- this.removeTranslationHash(pTranslation);
298
- return true;
299
- } else if (_typeof(pTranslation) == 'object') {
300
- var tmpTranslationSources = Object.keys(pTranslation);
301
- tmpTranslationSources.forEach(function (pTranslationSource) {
302
- _this2.removeTranslation(pTranslationSource);
303
- });
304
- return true;
305
- } else {
306
- this.logError("Hash translation removeTranslation expected either a string or an object but the passed-in translation was type ".concat(_typeof(pTranslation)));
307
- return false;
308
- }
309
- }
310
- }, {
311
- key: "clearTranslations",
312
- value: function clearTranslations() {
313
- this.translationTable = {};
314
- }
315
-
316
- /**
317
- * @param {string} pTranslation - The source hash to translate
318
- *
319
- * @return {string} The translated hash, or the original if no translation exists
320
- */
321
- }, {
322
- key: "translate",
323
- value: function translate(pTranslation) {
324
- if (pTranslation in this.translationTable) {
325
- return this.translationTable[pTranslation];
326
- } else {
327
- return pTranslation;
328
- }
329
- }
330
- }]);
331
- }();
332
- module.exports = ManyfestHashTranslation;
333
- }, {
334
- "./Manyfest-LogToConsole.js": 5
335
- }],
336
- 5: [function (require, module, exports) {
337
- /**
338
- * @author <steven@velozo.com>
339
- */
340
-
341
- /**
342
- * Manyfest simple logging shim (for browser and dependency-free running)
343
- */
344
-
345
- var logToConsole = function logToConsole(pLogLine, pLogObject) {
346
- var tmpLogLine = typeof pLogLine === 'string' ? pLogLine : '';
347
- console.log("[Manyfest] ".concat(tmpLogLine));
348
- if (pLogObject) console.log(JSON.stringify(pLogObject));
349
- };
350
- module.exports = logToConsole;
351
- }, {}],
352
- 6: [function (require, module, exports) {
353
- /**
354
- * @author <steven@velozo.com>
355
- */
356
- var libSimpleLog = require('./Manyfest-LogToConsole.js');
357
- // This is for resolving functions mid-address
358
- var libGetObjectValue = require('./Manyfest-ObjectAddress-GetValue.js');
359
- var fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');
360
-
361
- // TODO: Just until this is a fable service.
362
- var _MockFable = {
363
- DataFormat: require('./Manyfest-ObjectAddress-Parser.js')
364
- };
365
-
366
- /**
367
- * Object Address Resolver
368
- *
369
- * IMPORTANT NOTE: This code is intentionally more verbose than necessary, to
370
- * be extremely clear what is going on in the recursion for
371
- * each of the three address resolution functions.
372
- *
373
- * Although there is some opportunity to repeat ourselves a
374
- * bit less in this codebase (e.g. with detection of arrays
375
- * versus objects versus direct properties), it can make
376
- * debugging.. challenging. The minified version of the code
377
- * optimizes out almost anything repeated in here. So please
378
- * be kind and rewind... meaning please keep the codebase less
379
- * terse and more verbose so humans can comprehend it.
380
- *
381
- *
382
- * @class ManyfestObjectAddressResolverCheckAddressExists
383
- */
384
- var ManyfestObjectAddressResolverCheckAddressExists = /*#__PURE__*/function () {
385
- /**
386
- * @param {function} [pInfoLog] - (optional) Function to use for info logging
387
- * @param {function} [pErrorLog] - (optional) Function to use for error logging
388
- */
389
- function ManyfestObjectAddressResolverCheckAddressExists(pInfoLog, pErrorLog) {
390
- _classCallCheck(this, ManyfestObjectAddressResolverCheckAddressExists);
391
- // Wire in logging
392
- this.logInfo = typeof pInfoLog == 'function' ? pInfoLog : libSimpleLog;
393
- this.logError = typeof pErrorLog == 'function' ? pErrorLog : libSimpleLog;
394
- this.getObjectValueClass = new libGetObjectValue(this.logInfo, this.logError);
395
- this.cleanWrapCharacters = fCleanWrapCharacters;
396
- }
397
-
398
- /**
399
- * Check if an address exists.
400
- *
401
- * This is necessary because the getValueAtAddress function is ambiguous on
402
- * whether the element/property is actually there or not (it returns
403
- * undefined whether the property exists or not). This function checks for
404
- * existance and returns true or false dependent.
405
- *
406
- * @param {object} pObject - The object to check within
407
- * @param {string} pAddress - The address to check for
408
- * @param {object} [pRootObject] - (optional) The root object for function resolution context
409
- *
410
- * @return {boolean} - True if the address exists, false if it does not
411
- */
412
- return _createClass(ManyfestObjectAddressResolverCheckAddressExists, [{
413
- key: "checkAddressExists",
414
- value: function checkAddressExists(pObject, pAddress, pRootObject) {
415
- // TODO: Should these throw an error?
416
- // Make sure pObject is an object
417
- if (_typeof(pObject) != 'object') return false;
418
- // Make sure pAddress is a string
419
- if (typeof pAddress != 'string') return false;
420
-
421
- // Set the root object to the passed-in object if it isn't set yet. This is expected to be the root object.
422
- // NOTE: This was added to support functions mid-stream
423
- var tmpRootObject = typeof pRootObject == 'undefined' ? pObject : pRootObject;
424
-
425
- // DONE: Make this work for things like SomeRootObject.Metadata["Some.People.Use.Bad.Object.Property.Names"]
426
- var tmpAddressPartBeginning = _MockFable.DataFormat.stringGetFirstSegment(pAddress);
427
-
428
- // This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)
429
- if (tmpAddressPartBeginning.length == pAddress.length) {
430
- // Check if the address refers to a boxed property
431
- var tmpBracketStartIndex = pAddress.indexOf('[');
432
- var tmpBracketStopIndex = pAddress.indexOf(']');
433
-
434
- // Check if there is a function somewhere in the address... parenthesis start should only be in a function
435
- var tmpFunctionStartIndex = pAddress.indexOf('(');
436
-
437
- // NOTE THAT FUNCTIONS MUST RESOLVE FIRST
438
- // Functions look like this
439
- // MyFunction()
440
- // MyFunction(Some.Address)
441
- // MyFunction(Some.Address,Some.Other.Address)
442
- // MyFunction(Some.Address,Some.Other.Address,Some.Third.Address)
443
- //
444
- // This could be enhanced to allow purely numeric and string values to be passed to the function. For now,
445
- // To heck with that. This is a simple function call.
446
- //
447
- // The requirements to detect a function are:
448
- // 1) The start bracket is after character 0
449
- if (tmpFunctionStartIndex > 0
450
- // 2) The end bracket is after the start bracket
451
- && _MockFable.DataFormat.stringCountEnclosures(pAddress) > 0) {
452
- var tmpFunctionAddress = pAddress.substring(0, tmpFunctionStartIndex).trim();
453
- if (tmpFunctionAddress in pObject && typeof pObject[tmpFunctionAddress] == 'function') {
454
- return true;
455
- } else {
456
- // The address suggests it is a function, but it is not.
457
- return false;
458
- }
459
- }
460
- // Boxed elements look like this:
461
- // MyValues[10]
462
- // MyValues['Name']
463
- // MyValues["Age"]
464
- // MyValues[`Cost`]
465
- //
466
- // When we are passed SomeObject["Name"] this code below recurses as if it were SomeObject.Name
467
- // The requirements to detect a boxed element are:
468
- // 1) The start bracket is after character 0
469
- else if (tmpBracketStartIndex > 0
470
- // 2) The end bracket has something between them
471
- && tmpBracketStopIndex > tmpBracketStartIndex
472
- // 3) There is data
473
- && tmpBracketStopIndex - tmpBracketStartIndex > 1) {
474
- // The "Name" of the Object contained too the left of the bracket
475
- var tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();
476
-
477
- // If the subproperty doesn't test as a proper Object, none of the rest of this is possible.
478
- // This is a rare case where Arrays testing as Objects is useful
479
- if (_typeof(pObject[tmpBoxedPropertyName]) !== 'object') {
480
- return false;
481
- }
482
-
483
- // The "Reference" to the property within it, either an array element or object property
484
- var tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex + 1, tmpBracketStopIndex).trim();
485
- // Attempt to parse the reference as a number, which will be used as an array element
486
- var tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);
487
-
488
- // Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
489
- // This seems confusing to me at first read, so explaination:
490
- // Is the Boxed Object an Array? TRUE
491
- // And is the Reference inside the boxed Object not a number? TRUE
492
- // --> So when these are in agreement, it's an impossible access state
493
- if (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber)) {
494
- return false;
495
- }
496
-
497
- // 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,
498
- // otherwise we will try to treat it as a dynamic object property.
499
- if (isNaN(tmpBoxedPropertyNumber)) {
500
- // This isn't a number ... let's treat it as a dynamic object property.
501
- // We would expect the property to be wrapped in some kind of quotes so strip them
502
- tmpBoxedPropertyReference = this.cleanWrapCharacters('"', tmpBoxedPropertyReference);
503
- tmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);
504
- tmpBoxedPropertyReference = this.cleanWrapCharacters("'", tmpBoxedPropertyReference);
505
-
506
- // Check if the property exists.
507
- return tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName];
508
- } else {
509
- // Use the new in operator to see if the element is in the array
510
- return tmpBoxedPropertyNumber in pObject[tmpBoxedPropertyName];
511
- }
512
- } else {
513
- // Check if the property exists
514
- return pAddress in pObject;
515
- }
516
- } else {
517
- var tmpSubObjectName = tmpAddressPartBeginning;
518
- var tmpNewAddress = pAddress.substring(tmpAddressPartBeginning.length + 1);
519
-
520
- // Test if the tmpNewAddress is an array or object
521
- // Check if it's a boxed property
522
- var _tmpBracketStartIndex = tmpSubObjectName.indexOf('[');
523
- var _tmpBracketStopIndex = tmpSubObjectName.indexOf(']');
524
-
525
- // Check if there is a function somewhere in the address... parenthesis start should only be in a function
526
- var _tmpFunctionStartIndex = tmpSubObjectName.indexOf('(');
527
-
528
- // NOTE THAT FUNCTIONS MUST RESOLVE FIRST
529
- // Functions look like this
530
- // MyFunction()
531
- // MyFunction(Some.Address)
532
- // MyFunction(Some.Address,Some.Other.Address)
533
- // MyFunction(Some.Address,Some.Other.Address,Some.Third.Address)
534
- //
535
- // This could be enhanced to allow purely numeric and string values to be passed to the function. For now,
536
- // To heck with that. This is a simple function call.
537
- //
538
- // The requirements to detect a function are:
539
- // 1) The start bracket is after character 0
540
- if (_tmpFunctionStartIndex > 0
541
- // 2) The end bracket is after the start bracket
542
- && _MockFable.DataFormat.stringCountEnclosures(tmpSubObjectName) > 0) {
543
- var _tmpFunctionAddress = tmpSubObjectName.substring(0, _tmpFunctionStartIndex).trim();
544
- //tmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;
545
-
546
- if (typeof pObject[_tmpFunctionAddress] !== 'function') {
547
- // The address suggests it is a function, but it is not.
548
- return false;
549
- }
550
-
551
- // Now see if the function has arguments.
552
- // Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *
553
- var tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(tmpSubObjectName.substring(_tmpFunctionAddress.length), 0), ',');
554
- if (tmpFunctionArguments.length == 0 || tmpFunctionArguments[0] == '') {
555
- // No arguments... just call the function (bound to the scope of the object it is contained withing)
556
- if (_tmpFunctionAddress in pObject) {
557
- try {
558
- return this.checkAddressExists(pObject[_tmpFunctionAddress].apply(pObject), tmpNewAddress, tmpRootObject);
559
- } catch (pError) {
560
- // The function call failed, so the address doesn't exist
561
- libSimpleLog("Error calling function ".concat(_tmpFunctionAddress, " (address [").concat(pAddress, "]): ").concat(pError.message));
562
- return false;
563
- }
564
- } else {
565
- // The function doesn't exist, so the address doesn't exist
566
- libSimpleLog("Function ".concat(_tmpFunctionAddress, " does not exist (address [").concat(pAddress, "])"));
567
- return false;
568
- }
569
- } else {
570
- var tmpArgumentValues = [];
571
- var _tmpRootObject = typeof pRootObject == 'undefined' ? pObject : pRootObject;
572
-
573
- // Now get the value for each argument
574
- for (var i = 0; i < tmpFunctionArguments.length; i++) {
575
- // Resolve the values for each subsequent entry
576
- // NOTE: This is where the resolves get really tricky. Recursion within recursion. Programming gom jabbar, yo.
577
- tmpArgumentValues.push(this.getObjectValueClass.getValueAtAddress(_tmpRootObject, tmpFunctionArguments[i]));
578
- }
579
-
580
- //return this.checkAddressExists(pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues), tmpNewAddress, tmpRootObject);
581
- if (_tmpFunctionAddress in pObject) {
582
- try {
583
- return this.checkAddressExists(pObject[_tmpFunctionAddress].apply(pObject, tmpArgumentValues), tmpNewAddress, _tmpRootObject);
584
- } catch (pError) {
585
- // The function call failed, so the address doesn't exist
586
- libSimpleLog("Error calling function ".concat(_tmpFunctionAddress, " (address [").concat(pAddress, "]): ").concat(pError.message));
587
- return false;
588
- }
589
- } else {
590
- // The function doesn't exist, so the address doesn't exist
591
- libSimpleLog("Function ".concat(_tmpFunctionAddress, " does not exist (address [").concat(pAddress, "])"));
592
- return false;
593
- }
594
- }
595
- }
596
- // Boxed elements look like this:
597
- // MyValues[42]
598
- // MyValues['Color']
599
- // MyValues["Weight"]
600
- // MyValues[`Diameter`]
601
- //
602
- // When we are passed SomeObject["Name"] this code below recurses as if it were SomeObject.Name
603
- // The requirements to detect a boxed element are:
604
- // 1) The start bracket is after character 0
605
- else if (_tmpBracketStartIndex > 0
606
- // 2) The end bracket has something between them
607
- && _tmpBracketStopIndex > _tmpBracketStartIndex
608
- // 3) There is data
609
- && _tmpBracketStopIndex - _tmpBracketStartIndex > 1) {
610
- var _tmpBoxedPropertyName = tmpSubObjectName.substring(0, _tmpBracketStartIndex).trim();
611
- var _tmpBoxedPropertyReference = tmpSubObjectName.substring(_tmpBracketStartIndex + 1, _tmpBracketStopIndex).trim();
612
- var _tmpBoxedPropertyNumber = parseInt(_tmpBoxedPropertyReference, 10);
613
-
614
- // Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
615
- // This seems confusing to me at first read, so explaination:
616
- // Is the Boxed Object an Array? TRUE
617
- // And is the Reference inside the boxed Object not a number? TRUE
618
- // --> So when these are in agreement, it's an impossible access state
619
- // This could be a failure in the recursion chain because they passed something like this in:
620
- // StudentData.Sections.Algebra.Students[1].Tardy
621
- // BUT
622
- // StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access
623
- // This could be a failure in the recursion chain because they passed something like this in:
624
- // StudentData.Sections.Algebra.Students["JaneDoe"].Grade
625
- // BUT
626
- // StudentData.Sections.Algebra.Students is an array, so the ["JaneDoe"].Grade is not possible to access
627
- // TODO: Should this be an error or something? Should we keep a log of failures like this?
628
- if (Array.isArray(pObject[_tmpBoxedPropertyName]) == isNaN(_tmpBoxedPropertyNumber)) {
629
- // Because this is an impossible address, the property doesn't exist
630
- // TODO: Should we throw an error in this condition?
631
- return false;
632
- }
633
-
634
- //This is a bracketed value
635
- // 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,
636
- // otherwise we will try to reat it as a dynamic object property.
637
- if (isNaN(_tmpBoxedPropertyNumber)) {
638
- // This isn't a number ... let's treat it as a dynanmic object property.
639
- _tmpBoxedPropertyReference = this.cleanWrapCharacters('"', _tmpBoxedPropertyReference);
640
- _tmpBoxedPropertyReference = this.cleanWrapCharacters('`', _tmpBoxedPropertyReference);
641
- _tmpBoxedPropertyReference = this.cleanWrapCharacters("'", _tmpBoxedPropertyReference);
642
-
643
- // Recurse directly into the subobject
644
- return this.checkAddressExists(pObject[_tmpBoxedPropertyName][_tmpBoxedPropertyReference], tmpNewAddress, tmpRootObject);
645
- } else {
646
- // We parsed a valid number out of the boxed property name, so recurse into the array
647
- return this.checkAddressExists(pObject[_tmpBoxedPropertyName][_tmpBoxedPropertyNumber], tmpNewAddress, tmpRootObject);
648
- }
649
- }
650
-
651
- // If there is an object property already named for the sub object, but it isn't an object
652
- // then the system can't set the value in there. Error and abort!
653
- if (tmpSubObjectName in pObject && _typeof(pObject[tmpSubObjectName]) !== 'object') {
654
- return false;
655
- } else if (tmpSubObjectName in pObject) {
656
- // If there is already a subobject pass that to the recursive thingy
657
- return this.checkAddressExists(pObject[tmpSubObjectName], tmpNewAddress, tmpRootObject);
658
- } else {
659
- // Create a subobject and then pass that
660
- pObject[tmpSubObjectName] = {};
661
- return this.checkAddressExists(pObject[tmpSubObjectName], tmpNewAddress, tmpRootObject);
662
- }
663
- }
664
- }
665
- }]);
666
- }();
667
- module.exports = ManyfestObjectAddressResolverCheckAddressExists;
668
- }, {
669
- "./Manyfest-CleanWrapCharacters.js": 3,
670
- "./Manyfest-LogToConsole.js": 5,
671
- "./Manyfest-ObjectAddress-GetValue.js": 8,
672
- "./Manyfest-ObjectAddress-Parser.js": 9
673
- }],
674
- 7: [function (require, module, exports) {
675
- /**
676
- * @author <steven@velozo.com>
677
- */
678
- var libSimpleLog = require('./Manyfest-LogToConsole.js');
679
- var fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');
680
- var fParseConditionals = require("../source/Manyfest-ParseConditionals.js");
681
-
682
- /**
683
- * Object Address Resolver - DeleteValue
684
- *
685
- * IMPORTANT NOTE: This code is intentionally more verbose than necessary, to
686
- * be extremely clear what is going on in the recursion for
687
- * each of the three address resolution functions.
688
- *
689
- * Although there is some opportunity to repeat ourselves a
690
- * bit less in this codebase (e.g. with detection of arrays
691
- * versus objects versus direct properties), it can make
692
- * debugging.. challenging. The minified version of the code
693
- * optimizes out almost anything repeated in here. So please
694
- * be kind and rewind... meaning please keep the codebase less
695
- * terse and more verbose so humans can comprehend it.
696
- *
697
- * TODO: Once we validate this pattern is good to go, break these out into
698
- * three separate modules.
699
- *
700
- * @class ManyfestObjectAddressResolverDeleteValue
701
- */
702
- var ManyfestObjectAddressResolverDeleteValue = /*#__PURE__*/function () {
703
- /**
704
- * @param {function} [pInfoLog] - (optional) A logging function for info messages
705
- * @param {function} [pErrorLog] - (optional) A logging function for error messages
706
- */
707
- function ManyfestObjectAddressResolverDeleteValue(pInfoLog, pErrorLog) {
708
- _classCallCheck(this, ManyfestObjectAddressResolverDeleteValue);
709
- // Wire in logging
710
- this.logInfo = typeof pInfoLog == 'function' ? pInfoLog : libSimpleLog;
711
- this.logError = typeof pErrorLog == 'function' ? pErrorLog : libSimpleLog;
712
- this.cleanWrapCharacters = fCleanWrapCharacters;
713
- }
714
-
715
- // TODO: Dry me
716
- /**
717
- * @param {string} pAddress - The address being evaluated
718
- * @param {object} pRecord - The record being evaluated
719
- *
720
- * @return {boolean} True if the record passes the filters, false if it does not
721
- */
722
- return _createClass(ManyfestObjectAddressResolverDeleteValue, [{
723
- key: "checkRecordFilters",
724
- value: function checkRecordFilters(pAddress, pRecord) {
725
- return fParseConditionals(this, pAddress, pRecord);
726
- }
727
-
728
- /**
729
- * Delete the value of an element at an address
730
- *
731
- * @param {object} pObject - The object to delete the value from
732
- * @param {string} pAddress - The address to delete the value at
733
- * @param {string} [pParentAddress] - (optional) The parent address for recursion
734
- *
735
- * @return {boolean|object|undefined} - True if the value was deleted, false if it could not be deleted, undefined on error
736
- */
737
- }, {
738
- key: "deleteValueAtAddress",
739
- value: function deleteValueAtAddress(pObject, pAddress, pParentAddress) {
740
- // Make sure pObject (the object we are meant to be recursing) is an object (which could be an array or object)
741
- if (_typeof(pObject) != 'object') return undefined;
742
- // Make sure pAddress (the address we are resolving) is a string
743
- if (typeof pAddress != 'string') return undefined;
744
- // Stash the parent address for later resolution
745
- var tmpParentAddress = "";
746
- if (typeof pParentAddress == 'string') {
747
- tmpParentAddress = pParentAddress;
748
- }
749
-
750
- // TODO: Make this work for things like SomeRootObject.Metadata["Some.People.Use.Bad.Object.Property.Names"]
751
- var tmpSeparatorIndex = pAddress.indexOf('.');
752
-
753
- // This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)
754
- if (tmpSeparatorIndex == -1) {
755
- // Check if the address refers to a boxed property
756
- var tmpBracketStartIndex = pAddress.indexOf('[');
757
- var tmpBracketStopIndex = pAddress.indexOf(']');
758
-
759
- // Check for the Object Set Type marker.
760
- // Note this will not work with a bracket in the same address box set
761
- var tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');
762
-
763
- // Boxed elements look like this:
764
- // MyValues[10]
765
- // MyValues['Name']
766
- // MyValues["Age"]
767
- // MyValues[`Cost`]
768
- //
769
- // When we are passed SomeObject["Name"] this code below recurses as if it were SomeObject.Name
770
- // The requirements to detect a boxed element are:
771
- // 1) The start bracket is after character 0
772
- if (tmpBracketStartIndex > 0
773
- // 2) The end bracket has something between them
774
- && tmpBracketStopIndex > tmpBracketStartIndex
775
- // 3) There is data
776
- && tmpBracketStopIndex - tmpBracketStartIndex > 1) {
777
- // The "Name" of the Object contained too the left of the bracket
778
- var tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();
779
-
780
- // If the subproperty doesn't test as a proper Object, none of the rest of this is possible.
781
- // This is a rare case where Arrays testing as Objects is useful
782
- if (_typeof(pObject[tmpBoxedPropertyName]) !== 'object') {
783
- return false;
784
- }
785
-
786
- // The "Reference" to the property within it, either an array element or object property
787
- var tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex + 1, tmpBracketStopIndex).trim();
788
- // Attempt to parse the reference as a number, which will be used as an array element
789
- var tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);
790
-
791
- // Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
792
- // This seems confusing to me at first read, so explaination:
793
- // Is the Boxed Object an Array? TRUE
794
- // And is the Reference inside the boxed Object not a number? TRUE
795
- // --> So when these are in agreement, it's an impossible access state
796
- if (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber)) {
797
- return false;
798
- }
799
-
800
- // 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,
801
- // otherwise we will try to treat it as a dynamic object property.
802
- if (isNaN(tmpBoxedPropertyNumber)) {
803
- // This isn't a number ... let's treat it as a dynamic object property.
804
- // We would expect the property to be wrapped in some kind of quotes so strip them
805
- tmpBoxedPropertyReference = this.cleanWrapCharacters('"', tmpBoxedPropertyReference);
806
- tmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);
807
- tmpBoxedPropertyReference = this.cleanWrapCharacters("'", tmpBoxedPropertyReference);
808
-
809
- // Return the value in the property
810
- delete pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference];
811
- return true;
812
- } else {
813
- delete pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber];
814
- return true;
815
- }
816
- }
817
- // The requirements to detect a boxed set element are:
818
- // 1) The start bracket is after character 0
819
- else if (tmpBracketStartIndex > 0
820
- // 2) The end bracket is after the start bracket
821
- && tmpBracketStopIndex > tmpBracketStartIndex
822
- // 3) There is nothing in the brackets
823
- && tmpBracketStopIndex - tmpBracketStartIndex == 1) {
824
- var _tmpBoxedPropertyName2 = pAddress.substring(0, tmpBracketStartIndex).trim();
825
- if (!Array.isArray(pObject[_tmpBoxedPropertyName2])) {
826
- // We asked for a set from an array but it isnt' an array.
827
- return false;
828
- }
829
- var tmpInputArray = pObject[_tmpBoxedPropertyName2];
830
- // Count from the end to the beginning so splice doesn't %&%#$ up the array
831
- for (var i = tmpInputArray.length - 1; i >= 0; i--) {
832
- // The filtering is complex but allows config-based metaprogramming directly from schema
833
- var tmpKeepRecord = this.checkRecordFilters(pAddress, tmpInputArray[i]);
834
- if (tmpKeepRecord) {
835
- // Delete elements end to beginning
836
- tmpInputArray.splice(i, 1);
837
- }
838
- }
839
- return true;
840
- }
841
- // The object has been flagged as an object set, so treat it as such
842
- else if (tmpObjectTypeMarkerIndex > 0) {
843
- var tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();
844
- if (_typeof(pObject[tmpObjectPropertyName]) != 'object') {
845
- // We asked for a set from an array but it isnt' an array.
846
- return false;
847
- }
848
- delete pObject[tmpObjectPropertyName];
849
- return true;
850
- } else {
851
- // Now is the point in recursion to return the value in the address
852
- delete pObject[pAddress];
853
- return true;
854
- }
855
- } else {
856
- var tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);
857
- var tmpNewAddress = pAddress.substring(tmpSeparatorIndex + 1);
858
-
859
- // BOXED ELEMENTS
860
- // Test if the tmpNewAddress is an array or object
861
- // Check if it's a boxed property
862
- var _tmpBracketStartIndex2 = tmpSubObjectName.indexOf('[');
863
- var _tmpBracketStopIndex2 = tmpSubObjectName.indexOf(']');
864
- // Boxed elements look like this:
865
- // MyValues[42]
866
- // MyValues['Color']
867
- // MyValues["Weight"]
868
- // MyValues[`Diameter`]
869
- //
870
- // When we are passed SomeObject["Name"] this code below recurses as if it were SomeObject.Name
871
- // The requirements to detect a boxed element are:
872
- // 1) The start bracket is after character 0
873
- if (_tmpBracketStartIndex2 > 0
874
- // 2) The end bracket has something between them
875
- && _tmpBracketStopIndex2 > _tmpBracketStartIndex2
876
- // 3) There is data
877
- && _tmpBracketStopIndex2 - _tmpBracketStartIndex2 > 1) {
878
- var _tmpBoxedPropertyName3 = tmpSubObjectName.substring(0, _tmpBracketStartIndex2).trim();
879
- var _tmpBoxedPropertyReference2 = tmpSubObjectName.substring(_tmpBracketStartIndex2 + 1, _tmpBracketStopIndex2).trim();
880
- var _tmpBoxedPropertyNumber2 = parseInt(_tmpBoxedPropertyReference2, 10);
881
-
882
- // Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
883
- // This seems confusing to me at first read, so explaination:
884
- // Is the Boxed Object an Array? TRUE
885
- // And is the Reference inside the boxed Object not a number? TRUE
886
- // --> So when these are in agreement, it's an impossible access state
887
- // This could be a failure in the recursion chain because they passed something like this in:
888
- // StudentData.Sections.Algebra.Students[1].Tardy
889
- // BUT
890
- // StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access
891
- // This could be a failure in the recursion chain because they passed something like this in:
892
- // StudentData.Sections.Algebra.Students["JaneDoe"].Grade
893
- // BUT
894
- // StudentData.Sections.Algebra.Students is an array, so the ["JaneDoe"].Grade is not possible to access
895
- // TODO: Should this be an error or something? Should we keep a log of failures like this?
896
- if (Array.isArray(pObject[_tmpBoxedPropertyName3]) == isNaN(_tmpBoxedPropertyNumber2)) {
897
- return false;
898
- }
899
- // Check if the boxed property is an object.
900
- if (_typeof(pObject[_tmpBoxedPropertyName3]) != 'object') {
901
- return false;
902
- }
903
- //This is a bracketed value
904
- // 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,
905
- // otherwise we will try to reat it as a dynamic object property.
906
- if (isNaN(_tmpBoxedPropertyNumber2)) {
907
- // This isn't a number ... let's treat it as a dynanmic object property.
908
- _tmpBoxedPropertyReference2 = this.cleanWrapCharacters('"', _tmpBoxedPropertyReference2);
909
- _tmpBoxedPropertyReference2 = this.cleanWrapCharacters('`', _tmpBoxedPropertyReference2);
910
- _tmpBoxedPropertyReference2 = this.cleanWrapCharacters("'", _tmpBoxedPropertyReference2);
911
-
912
- // Continue to manage the parent address for recursion
913
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
914
- // Recurse directly into the subobject
915
- return this.deleteValueAtAddress(pObject[_tmpBoxedPropertyName3][_tmpBoxedPropertyReference2], tmpNewAddress, tmpParentAddress);
916
- } else {
917
- // Continue to manage the parent address for recursion
918
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
919
- // We parsed a valid number out of the boxed property name, so recurse into the array
920
- return this.deleteValueAtAddress(pObject[_tmpBoxedPropertyName3][_tmpBoxedPropertyNumber2], tmpNewAddress, tmpParentAddress);
921
- }
922
- }
923
- // The requirements to detect a boxed set element are:
924
- // 1) The start bracket is after character 0
925
- else if (_tmpBracketStartIndex2 > 0
926
- // 2) The end bracket is after the start bracket
927
- && _tmpBracketStopIndex2 > _tmpBracketStartIndex2
928
- // 3) There is nothing in the brackets
929
- && _tmpBracketStopIndex2 - _tmpBracketStartIndex2 == 1) {
930
- var _tmpBoxedPropertyName4 = pAddress.substring(0, _tmpBracketStartIndex2).trim();
931
- if (!Array.isArray(pObject[_tmpBoxedPropertyName4])) {
932
- // We asked for a set from an array but it isnt' an array.
933
- return false;
934
- }
935
-
936
- // We need to enumerate the array and grab the addresses from there.
937
- var tmpArrayProperty = pObject[_tmpBoxedPropertyName4];
938
- // Managing the parent address is a bit more complex here -- the box will be added for each element.
939
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(_tmpBoxedPropertyName4);
940
- // The container object is where we have the "Address":SOMEVALUE pairs
941
- var tmpContainerObject = {};
942
- for (var _i = 0; _i < tmpArrayProperty.length; _i++) {
943
- var tmpPropertyParentAddress = "".concat(tmpParentAddress, "[").concat(_i, "]");
944
- var tmpValue = this.deleteValueAtAddress(pObject[_tmpBoxedPropertyName4][_i], tmpNewAddress, tmpPropertyParentAddress);
945
- tmpContainerObject["".concat(tmpPropertyParentAddress, ".").concat(tmpNewAddress)] = tmpValue;
946
- }
947
- return tmpContainerObject;
948
- }
949
-
950
- // OBJECT SET
951
- // Note this will not work with a bracket in the same address box set
952
- var _tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');
953
- if (_tmpObjectTypeMarkerIndex > 0) {
954
- var _tmpObjectPropertyName = pAddress.substring(0, _tmpObjectTypeMarkerIndex).trim();
955
- if (_typeof(pObject[_tmpObjectPropertyName]) != 'object') {
956
- // We asked for a set from an array but it isnt' an array.
957
- return false;
958
- }
959
-
960
- // We need to enumerate the Object and grab the addresses from there.
961
- var tmpObjectProperty = pObject[_tmpObjectPropertyName];
962
- var tmpObjectPropertyKeys = Object.keys(tmpObjectProperty);
963
- // Managing the parent address is a bit more complex here -- the box will be added for each element.
964
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(_tmpObjectPropertyName);
965
- // The container object is where we have the "Address":SOMEVALUE pairs
966
- var _tmpContainerObject = {};
967
- for (var _i2 = 0; _i2 < tmpObjectPropertyKeys.length; _i2++) {
968
- var _tmpPropertyParentAddress = "".concat(tmpParentAddress, ".").concat(tmpObjectPropertyKeys[_i2]);
969
- var _tmpValue = this.deleteValueAtAddress(pObject[_tmpObjectPropertyName][tmpObjectPropertyKeys[_i2]], tmpNewAddress, _tmpPropertyParentAddress);
970
-
971
- // The filtering is complex but allows config-based metaprogramming directly from schema
972
- var _tmpKeepRecord = this.checkRecordFilters(pAddress, _tmpValue);
973
- if (_tmpKeepRecord) {
974
- _tmpContainerObject["".concat(_tmpPropertyParentAddress, ".").concat(tmpNewAddress)] = _tmpValue;
975
- }
976
- }
977
- return _tmpContainerObject;
978
- }
979
-
980
- // If there is an object property already named for the sub object, but it isn't an object
981
- // then the system can't set the value in there. Error and abort!
982
- if (tmpSubObjectName in pObject && _typeof(pObject[tmpSubObjectName]) !== 'object') {
983
- return undefined;
984
- } else if (tmpSubObjectName in pObject) {
985
- // If there is already a subobject pass that to the recursive thingy
986
- // Continue to manage the parent address for recursion
987
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
988
- return this.deleteValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress);
989
- } else {
990
- // Create a subobject and then pass that
991
- // Continue to manage the parent address for recursion
992
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
993
- pObject[tmpSubObjectName] = {};
994
- return this.deleteValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress);
995
- }
996
- }
997
- }
998
- }]);
999
- }();
1000
- ;
1001
- module.exports = ManyfestObjectAddressResolverDeleteValue;
1002
- }, {
1003
- "../source/Manyfest-ParseConditionals.js": 12,
1004
- "./Manyfest-CleanWrapCharacters.js": 3,
1005
- "./Manyfest-LogToConsole.js": 5
1006
- }],
1007
- 8: [function (require, module, exports) {
1008
- /**
1009
- * @author <steven@velozo.com>
1010
- */
1011
- var libSimpleLog = require('./Manyfest-LogToConsole.js');
1012
- var fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');
1013
- var fParseConditionals = require("../source/Manyfest-ParseConditionals.js");
1014
- var _MockFable = {
1015
- DataFormat: require('./Manyfest-ObjectAddress-Parser.js')
1016
- };
1017
-
1018
- /**
1019
- * Object Address Resolver - GetValue
1020
- *
1021
- * IMPORTANT NOTE: This code is intentionally more verbose than necessary, to
1022
- * be extremely clear what is going on in the recursion for
1023
- * each of the three address resolution functions.
1024
- *
1025
- * Although there is some opportunity to repeat ourselves a
1026
- * bit less in this codebase (e.g. with detection of arrays
1027
- * versus objects versus direct properties), it can make
1028
- * debugging.. challenging. The minified version of the code
1029
- * optimizes out almost anything repeated in here. So please
1030
- * be kind and rewind... meaning please keep the codebase less
1031
- * terse and more verbose so humans can comprehend it.
1032
- *
1033
- * TODO: Once we validate this pattern is good to go, break these out into
1034
- * three separate modules.
1035
- *
1036
- * @class ManyfestObjectAddressResolverGetValue
1037
- */
1038
- var ManyfestObjectAddressResolverGetValue = /*#__PURE__*/function () {
1039
- /**
1040
- * @param {function} [pInfoLog] - (optional) A logging function for info messages
1041
- * @param {function} [pErrorLog] - (optional) A logging function for error messages
1042
- */
1043
- function ManyfestObjectAddressResolverGetValue(pInfoLog, pErrorLog) {
1044
- _classCallCheck(this, ManyfestObjectAddressResolverGetValue);
1045
- // Wire in logging
1046
- this.logInfo = typeof pInfoLog == 'function' ? pInfoLog : libSimpleLog;
1047
- this.logError = typeof pErrorLog == 'function' ? pErrorLog : libSimpleLog;
1048
- this.cleanWrapCharacters = fCleanWrapCharacters;
1049
- }
1050
-
1051
- /**
1052
- * @param {string} pAddress - The address of the record to check
1053
- * @param {object} pRecord - The record to check against the filters
1054
- *
1055
- * @return {boolean} - True if the record passes the filters, false otherwise
1056
- */
1057
- return _createClass(ManyfestObjectAddressResolverGetValue, [{
1058
- key: "checkRecordFilters",
1059
- value: function checkRecordFilters(pAddress, pRecord) {
1060
- return fParseConditionals(this, pAddress, pRecord);
1061
- }
1062
-
1063
- /**
1064
- * Get the value of an element at an address
1065
- *
1066
- * @param {object} pObject - The object to resolve the address against
1067
- * @param {string} pAddress - The address to resolve
1068
- * @param {string} [pParentAddress] - (optional) The parent address for back-navigation
1069
- * @param {object} [pRootObject] - (optional) The root object for function argument resolution
1070
- *
1071
- * @return {any} The value at the address, or undefined if not found
1072
- */
1073
- }, {
1074
- key: "getValueAtAddress",
1075
- value: function getValueAtAddress(pObject, pAddress, pParentAddress, pRootObject) {
1076
- // Make sure pObject (the object we are meant to be recursing) is an object (which could be an array or object)
1077
- if (_typeof(pObject) != 'object') {
1078
- return undefined;
1079
- }
1080
- if (pObject === null) {
1081
- return undefined;
1082
- }
1083
- // Make sure pAddress (the address we are resolving) is a string
1084
- if (typeof pAddress != 'string') {
1085
- return undefined;
1086
- }
1087
- // Stash the parent address for later resolution
1088
- var tmpParentAddress = "";
1089
- if (typeof pParentAddress == 'string') {
1090
- tmpParentAddress = pParentAddress;
1091
- }
1092
-
1093
- // Set the root object to the passed-in object if it isn't set yet. This is expected to be the root object.
1094
- var tmpRootObject = typeof pRootObject == 'undefined' ? pObject : pRootObject;
1095
-
1096
- // DONE: Make this work for things like SomeRootObject.Metadata["Some.People.Use.Bad.Object.Property.Names"]
1097
- var tmpAddressPartBeginning = _MockFable.DataFormat.stringGetFirstSegment(pAddress);
1098
-
1099
- // Adding simple back-navigation in objects
1100
- if (tmpAddressPartBeginning == '') {
1101
- // Given an address of "Bundle.Contract.IDContract...Project.IDProject" the ... would be interpreted as two back-navigations from IDContract.
1102
- // When the address is passed in, though, the first . is already eliminated. So we can count the dots.
1103
- var tmpParentAddressParts = _MockFable.DataFormat.stringGetSegments(tmpParentAddress);
1104
- var tmpBackNavigationCount = 0;
1105
-
1106
- // Count the number of dots
1107
- for (var i = 0; i < pAddress.length; i++) {
1108
- if (pAddress.charAt(i) != '.') {
1109
- break;
1110
- }
1111
- tmpBackNavigationCount++;
1112
- }
1113
- var tmpParentAddressLength = tmpParentAddressParts.length - tmpBackNavigationCount;
1114
- if (tmpParentAddressLength < 0) {
1115
- // We are trying to back navigate more than we can.
1116
- // TODO: Should this be undefined or should we bank out at the bottom and try to go forward?
1117
- // This seems safest for now.
1118
- return undefined;
1119
- } else {
1120
- // We are trying to back navigate to a parent object.
1121
- // Recurse with the back-propagated parent address, and, the new address without the back-navigation dots.
1122
- var tmpRecurseAddress = pAddress.slice(tmpBackNavigationCount);
1123
- if (tmpParentAddressLength > 0) {
1124
- tmpRecurseAddress = "".concat(tmpParentAddressParts.slice(0, tmpParentAddressLength).join('.'), ".").concat(tmpRecurseAddress);
1125
- }
1126
- this.logInfo("Back-navigation detected. Recursing back to address [".concat(tmpRecurseAddress, "]"));
1127
- return this.getValueAtAddress(tmpRootObject, tmpRecurseAddress);
1128
- }
1129
- }
1130
-
1131
- // This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)
1132
- if (tmpAddressPartBeginning.length == pAddress.length) {
1133
- // TODO: Optimize this by having these calls only happen when the previous fails.
1134
- // TODO: Alternatively look for all markers in one pass?
1135
- // Check if the address refers to a boxed property
1136
- var tmpBracketStartIndex = pAddress.indexOf('[');
1137
- var tmpBracketStopIndex = pAddress.indexOf(']');
1138
-
1139
- // Check for the Object Set Type marker.
1140
- // Note this will not work with a bracket in the same address box set
1141
- var tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');
1142
-
1143
- // Check if there is a function somewhere in the address... parenthesis start should only be in a function
1144
- var tmpFunctionStartIndex = pAddress.indexOf('(');
1145
-
1146
- // NOTE THAT FUNCTIONS MUST RESOLVE FIRST
1147
- // Functions look like this
1148
- // MyFunction()
1149
- // MyFunction(Some.Address)
1150
- // MyFunction(Some.Address,Some.Other.Address)
1151
- // MyFunction(Some.Address,Some.Other.Address,Some.Third.Address)
1152
- //
1153
- // This could be enhanced to allow purely numeric and string values to be passed to the function. For now,
1154
- // To heck with that. This is a simple function call.
1155
- //
1156
- // The requirements to detect a function are:
1157
- // 1) The start bracket is after character 0
1158
- if (tmpFunctionStartIndex > 0
1159
- // 2) The end bracket is after the start bracket
1160
- && _MockFable.DataFormat.stringCountEnclosures(pAddress) > 0) {
1161
- var tmpFunctionAddress = pAddress.substring(0, tmpFunctionStartIndex).trim();
1162
- if (typeof pObject[tmpFunctionAddress] !== 'function') {
1163
- // The address suggests it is a function, but it is not.
1164
- return false;
1165
- }
1166
-
1167
- // Now see if the function has arguments.
1168
- // Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *
1169
- var tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(pAddress.substring(tmpFunctionAddress.length), 0), ',');
1170
- if (tmpFunctionArguments.length == 0 || tmpFunctionArguments[0] == '') {
1171
- // No arguments... just call the function (bound to the scope of the object it is contained withing)
1172
- if (tmpFunctionAddress in pObject) {
1173
- try {
1174
- return pObject[tmpFunctionAddress].apply(pObject);
1175
- } catch (pError) {
1176
- // The function call failed, so the address doesn't exist
1177
- console.log("Error in getValueAtAddress calling function ".concat(tmpFunctionAddress, " (address [").concat(pAddress, "]): ").concat(pError.message));
1178
- return false;
1179
- }
1180
- } else {
1181
- // The function doesn't exist, so the address doesn't exist
1182
- console.log("Function ".concat(tmpFunctionAddress, " does not exist (address [").concat(pAddress, "])"));
1183
- return false;
1184
- }
1185
- } else {
1186
- var tmpArgumentValues = [];
1187
- var _tmpRootObject2 = typeof pRootObject == 'undefined' ? pObject : pRootObject;
1188
-
1189
- // Now get the value for each argument
1190
- for (var _i3 = 0; _i3 < tmpFunctionArguments.length; _i3++) {
1191
- // Resolve the values for each subsequent entry
1192
- // Check if the argument value is a string literal or a reference to an address
1193
- if (tmpFunctionArguments[_i3].length >= 2 && (tmpFunctionArguments[_i3].charAt(0) == '"' || tmpFunctionArguments[_i3].charAt(0) == "'" || tmpFunctionArguments[_i3].charAt(0) == "`") && (tmpFunctionArguments[_i3].charAt(tmpFunctionArguments[_i3].length - 1) == '"' || tmpFunctionArguments[_i3].charAt(tmpFunctionArguments[_i3].length - 1) == "'" || tmpFunctionArguments[_i3].charAt(tmpFunctionArguments[_i3].length - 1) == "`")) {
1194
- // This is a string literal
1195
- tmpArgumentValues.push(tmpFunctionArguments[_i3].substring(1, tmpFunctionArguments[_i3].length - 1));
1196
- } else {
1197
- // This is a hash address
1198
- tmpArgumentValues.push(this.getValueAtAddress(_tmpRootObject2, tmpFunctionArguments[_i3]));
1199
- }
1200
- }
1201
- if (tmpFunctionAddress in pObject) {
1202
- try {
1203
- return pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues);
1204
- } catch (pError) {
1205
- // The function call failed, so the address doesn't exist
1206
- console.log("Error in getValueAtAddress calling function ".concat(tmpFunctionAddress, " (address [").concat(pAddress, "]): ").concat(pError.message));
1207
- return false;
1208
- }
1209
- } else {
1210
- // The function doesn't exist, so the address doesn't exist
1211
- console.log("Function ".concat(tmpFunctionAddress, " does not exist (address [").concat(pAddress, "])"));
1212
- return false;
1213
- }
1214
- }
1215
- }
1216
- // Boxed elements look like this:
1217
- // MyValues[10]
1218
- // MyValues['Name']
1219
- // MyValues["Age"]
1220
- // MyValues[`Cost`]
1221
- //
1222
- // When we are passed SomeObject["Name"] this code below recurses as if it were SomeObject.Name
1223
- // The requirements to detect a boxed element are:
1224
- // 1) The start bracket is after character 0
1225
- else if (tmpBracketStartIndex > 0
1226
- // 2) The end bracket has something between them
1227
- && tmpBracketStopIndex > tmpBracketStartIndex
1228
- // 3) There is data
1229
- && tmpBracketStopIndex - tmpBracketStartIndex > 1) {
1230
- // The "Name" of the Object contained too the left of the bracket
1231
- var tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();
1232
-
1233
- // If the subproperty doesn't test as a proper Object, none of the rest of this is possible.
1234
- // This is a rare case where Arrays testing as Objects is useful
1235
- if (_typeof(pObject[tmpBoxedPropertyName]) !== 'object') {
1236
- return undefined;
1237
- }
1238
-
1239
- // The "Reference" to the property within it, either an array element or object property
1240
- var tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex + 1, tmpBracketStopIndex).trim();
1241
- // Attempt to parse the reference as a number, which will be used as an array element
1242
- var tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);
1243
-
1244
- // Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
1245
- // This seems confusing to me at first read, so explaination:
1246
- // Is the Boxed Object an Array? TRUE
1247
- // And is the Reference inside the boxed Object not a number? TRUE
1248
- // --> So when these are in agreement, it's an impossible access state
1249
- if (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber)) {
1250
- return undefined;
1251
- }
1252
-
1253
- // 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,
1254
- // otherwise we will try to treat it as a dynamic object property.
1255
- if (isNaN(tmpBoxedPropertyNumber)) {
1256
- // This isn't a number ... let's treat it as a dynamic object property.
1257
- // We would expect the property to be wrapped in some kind of quotes so strip them
1258
- tmpBoxedPropertyReference = this.cleanWrapCharacters('"', tmpBoxedPropertyReference);
1259
- tmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);
1260
- tmpBoxedPropertyReference = this.cleanWrapCharacters("'", tmpBoxedPropertyReference);
1261
-
1262
- // Return the value in the property
1263
- return pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference];
1264
- } else {
1265
- return pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber];
1266
- }
1267
- }
1268
- // The requirements to detect a boxed set element are:
1269
- // 1) The start bracket is after character 0
1270
- else if (tmpBracketStartIndex > 0
1271
- // 2) The end bracket is after the start bracket
1272
- && tmpBracketStopIndex > tmpBracketStartIndex
1273
- // 3) There is nothing in the brackets
1274
- && tmpBracketStopIndex - tmpBracketStartIndex == 1) {
1275
- var _tmpBoxedPropertyName5 = pAddress.substring(0, tmpBracketStartIndex).trim();
1276
- if (!Array.isArray(pObject[_tmpBoxedPropertyName5])) {
1277
- // We asked for a set from an array but it isnt' an array.
1278
- return false;
1279
- }
1280
- var tmpInputArray = pObject[_tmpBoxedPropertyName5];
1281
- var tmpOutputArray = [];
1282
- for (var _i4 = 0; _i4 < tmpInputArray.length; _i4++) {
1283
- // The filtering is complex but allows config-based metaprogramming directly from schema
1284
- var tmpKeepRecord = this.checkRecordFilters(pAddress, tmpInputArray[_i4]);
1285
- if (tmpKeepRecord) {
1286
- tmpOutputArray.push(tmpInputArray[_i4]);
1287
- }
1288
- }
1289
- return tmpOutputArray;
1290
- }
1291
- // The object has been flagged as an object set, so treat it as such
1292
- else if (tmpObjectTypeMarkerIndex > 0) {
1293
- var tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();
1294
- if (_typeof(pObject[tmpObjectPropertyName]) != 'object') {
1295
- // We asked for a set from an array but it isnt' an array.
1296
- return false;
1297
- }
1298
- return pObject[tmpObjectPropertyName];
1299
- } else {
1300
- // Now is the point in recursion to return the value in the address
1301
- if (_typeof(pObject[pAddress]) != null) {
1302
- return pObject[pAddress];
1303
- } else {
1304
- return null;
1305
- }
1306
- }
1307
- } else {
1308
- //let tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);
1309
- //let tmpNewAddress = pAddress.substring(tmpSeparatorIndex+1);
1310
- var tmpSubObjectName = tmpAddressPartBeginning;
1311
- var tmpNewAddress = pAddress.substring(tmpAddressPartBeginning.length + 1);
1312
-
1313
- // BOXED ELEMENTS
1314
- // Test if the tmpNewAddress is an array or object
1315
- // Check if it's a boxed property
1316
- var _tmpBracketStartIndex3 = tmpSubObjectName.indexOf('[');
1317
- var _tmpBracketStopIndex3 = tmpSubObjectName.indexOf(']');
1318
-
1319
- // Check if there is a function somewhere in the address... parenthesis start should only be in a function
1320
- var _tmpFunctionStartIndex2 = tmpSubObjectName.indexOf('(');
1321
-
1322
- // NOTE THAT FUNCTIONS MUST RESOLVE FIRST
1323
- // Functions look like this
1324
- // MyFunction()
1325
- // MyFunction(Some.Address)
1326
- // MyFunction(Some.Address,Some.Other.Address)
1327
- // MyFunction(Some.Address,Some.Other.Address,Some.Third.Address)
1328
- //
1329
- // This could be enhanced to allow purely numeric and string values to be passed to the function. For now,
1330
- // To heck with that. This is a simple function call.
1331
- //
1332
- // The requirements to detect a function are:
1333
- // 1) The start bracket is after character 0
1334
- if (_tmpFunctionStartIndex2 > 0
1335
- // 2) The end bracket is after the start bracket
1336
- && _MockFable.DataFormat.stringCountEnclosures(tmpSubObjectName) > 0) {
1337
- var _tmpFunctionAddress2 = tmpSubObjectName.substring(0, _tmpFunctionStartIndex2).trim();
1338
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
1339
- if (typeof pObject[_tmpFunctionAddress2] !== 'function') {
1340
- // The address suggests it is a function, but it is not.
1341
- return false;
1342
- }
1343
-
1344
- // Now see if the function has arguments.
1345
- // Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *
1346
- var _tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(tmpSubObjectName.substring(_tmpFunctionAddress2.length), 0), ',');
1347
- if (_tmpFunctionArguments.length == 0 || _tmpFunctionArguments[0] == '') {
1348
- // No arguments... just call the function (bound to the scope of the object it is contained withing)
1349
- if (_tmpFunctionAddress2 in pObject) {
1350
- try {
1351
- return this.getValueAtAddress(pObject[_tmpFunctionAddress2].apply(pObject), tmpNewAddress, tmpParentAddress, tmpRootObject);
1352
- } catch (pError) {
1353
- // The function call failed, so the address doesn't exist
1354
- console.log("Error in getValueAtAddress calling function ".concat(_tmpFunctionAddress2, " (address [").concat(pAddress, "]): ").concat(pError.message));
1355
- return false;
1356
- }
1357
- } else {
1358
- // The function doesn't exist, so the address doesn't exist
1359
- console.log("Function ".concat(_tmpFunctionAddress2, " does not exist (address [").concat(pAddress, "])"));
1360
- return false;
1361
- }
1362
- } else {
1363
- var _tmpArgumentValues = [];
1364
- var _tmpRootObject3 = typeof pRootObject == 'undefined' ? pObject : pRootObject;
1365
-
1366
- // Now get the value for each argument
1367
- for (var _i5 = 0; _i5 < _tmpFunctionArguments.length; _i5++) {
1368
- // Resolve the values for each subsequent entry
1369
- // Check if the argument value is a string literal or a reference to an address
1370
- if (_tmpFunctionArguments[_i5].length >= 2 && (_tmpFunctionArguments[_i5].charAt(0) == '"' || _tmpFunctionArguments[_i5].charAt(0) == "'" || _tmpFunctionArguments[_i5].charAt(0) == "`") && (_tmpFunctionArguments[_i5].charAt(_tmpFunctionArguments[_i5].length - 1) == '"' || _tmpFunctionArguments[_i5].charAt(_tmpFunctionArguments[_i5].length - 1) == "'" || _tmpFunctionArguments[_i5].charAt(_tmpFunctionArguments[_i5].length - 1) == "`")) {
1371
- // This is a string literal
1372
- _tmpArgumentValues.push(_tmpFunctionArguments[_i5].substring(1, _tmpFunctionArguments[_i5].length - 1));
1373
- } else {
1374
- // This is a hash address
1375
- _tmpArgumentValues.push(this.getValueAtAddress(_tmpRootObject3, _tmpFunctionArguments[_i5]));
1376
- }
1377
- }
1378
- if (_tmpFunctionAddress2 in pObject) {
1379
- try {
1380
- return this.getValueAtAddress(pObject[_tmpFunctionAddress2].apply(pObject, _tmpArgumentValues), tmpNewAddress, tmpParentAddress, _tmpRootObject3);
1381
- } catch (pError) {
1382
- // The function call failed, so the address doesn't exist
1383
- console.log("Error in getValueAtAddress calling function ".concat(_tmpFunctionAddress2, " (address [").concat(pAddress, "]): ").concat(pError.message));
1384
- return false;
1385
- }
1386
- } else {
1387
- // The function doesn't exist, so the address doesn't exist
1388
- console.log("Function ".concat(_tmpFunctionAddress2, " does not exist (address [").concat(pAddress, "])"));
1389
- return false;
1390
- }
1391
- }
1392
- }
1393
- // Boxed elements look like this:
1394
- // MyValues[42]
1395
- // MyValues['Color']
1396
- // MyValues["Weight"]
1397
- // MyValues[`Diameter`]
1398
- //
1399
- // When we are passed SomeObject["Name"] this code below recurses as if it were SomeObject.Name
1400
- // The requirements to detect a boxed element are:
1401
- // 1) The start bracket is after character 0
1402
- else if (_tmpBracketStartIndex3 > 0
1403
- // 2) The end bracket has something between them
1404
- && _tmpBracketStopIndex3 > _tmpBracketStartIndex3
1405
- // 3) There is data
1406
- && _tmpBracketStopIndex3 - _tmpBracketStartIndex3 > 1) {
1407
- var _tmpBoxedPropertyName6 = tmpSubObjectName.substring(0, _tmpBracketStartIndex3).trim();
1408
- var _tmpBoxedPropertyReference3 = tmpSubObjectName.substring(_tmpBracketStartIndex3 + 1, _tmpBracketStopIndex3).trim();
1409
- var _tmpBoxedPropertyNumber3 = parseInt(_tmpBoxedPropertyReference3, 10);
1410
-
1411
- // Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
1412
- // This seems confusing to me at first read, so explaination:
1413
- // Is the Boxed Object an Array? TRUE
1414
- // And is the Reference inside the boxed Object not a number? TRUE
1415
- // --> So when these are in agreement, it's an impossible access state
1416
- // This could be a failure in the recursion chain because they passed something like this in:
1417
- // StudentData.Sections.Algebra.Students[1].Tardy
1418
- // BUT
1419
- // StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access
1420
- // This could be a failure in the recursion chain because they passed something like this in:
1421
- // StudentData.Sections.Algebra.Students["JaneDoe"].Grade
1422
- // BUT
1423
- // StudentData.Sections.Algebra.Students is an array, so the ["JaneDoe"].Grade is not possible to access
1424
- // TODO: Should this be an error or something? Should we keep a log of failures like this?
1425
- if (Array.isArray(pObject[_tmpBoxedPropertyName6]) == isNaN(_tmpBoxedPropertyNumber3)) {
1426
- return undefined;
1427
- }
1428
- // Check if the boxed property is an object.
1429
- if (_typeof(pObject[_tmpBoxedPropertyName6]) != 'object') {
1430
- return undefined;
1431
- }
1432
-
1433
- //This is a bracketed value
1434
- // 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,
1435
- // otherwise we will try to reat it as a dynamic object property.
1436
- if (isNaN(_tmpBoxedPropertyNumber3)) {
1437
- // This isn't a number ... let's treat it as a dynanmic object property.
1438
- _tmpBoxedPropertyReference3 = this.cleanWrapCharacters('"', _tmpBoxedPropertyReference3);
1439
- _tmpBoxedPropertyReference3 = this.cleanWrapCharacters('`', _tmpBoxedPropertyReference3);
1440
- _tmpBoxedPropertyReference3 = this.cleanWrapCharacters("'", _tmpBoxedPropertyReference3);
1441
-
1442
- // Continue to manage the parent address for recursion
1443
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
1444
- // Recurse directly into the subobject
1445
- return this.getValueAtAddress(pObject[_tmpBoxedPropertyName6][_tmpBoxedPropertyReference3], tmpNewAddress, tmpParentAddress, tmpRootObject);
1446
- } else {
1447
- // Continue to manage the parent address for recursion
1448
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
1449
- // We parsed a valid number out of the boxed property name, so recurse into the array
1450
- return this.getValueAtAddress(pObject[_tmpBoxedPropertyName6][_tmpBoxedPropertyNumber3], tmpNewAddress, tmpParentAddress, tmpRootObject);
1451
- }
1452
- }
1453
- // The requirements to detect a boxed set element are:
1454
- // 1) The start bracket is after character 0
1455
- else if (_tmpBracketStartIndex3 > 0
1456
- // 2) The end bracket is after the start bracket
1457
- && _tmpBracketStopIndex3 > _tmpBracketStartIndex3
1458
- // 3) There is nothing in the brackets
1459
- && _tmpBracketStopIndex3 - _tmpBracketStartIndex3 == 1) {
1460
- var _tmpBoxedPropertyName7 = pAddress.substring(0, _tmpBracketStartIndex3).trim();
1461
- if (!Array.isArray(pObject[_tmpBoxedPropertyName7])) {
1462
- // We asked for a set from an array but it isnt' an array.
1463
- return false;
1464
- }
1465
-
1466
- // We need to enumerate the array and grab the addresses from there.
1467
- var tmpArrayProperty = pObject[_tmpBoxedPropertyName7];
1468
- // Managing the parent address is a bit more complex here -- the box will be added for each element.
1469
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(_tmpBoxedPropertyName7);
1470
- // The container object is where we have the "Address":SOMEVALUE pairs
1471
- var tmpContainerObject = {};
1472
- for (var _i6 = 0; _i6 < tmpArrayProperty.length; _i6++) {
1473
- var tmpPropertyParentAddress = "".concat(tmpParentAddress, "[").concat(_i6, "]");
1474
- var tmpValue = this.getValueAtAddress(pObject[_tmpBoxedPropertyName7][_i6], tmpNewAddress, tmpPropertyParentAddress, tmpRootObject);
1475
- tmpContainerObject["".concat(tmpPropertyParentAddress, ".").concat(tmpNewAddress)] = tmpValue;
1476
- }
1477
- return tmpContainerObject;
1478
- }
1479
-
1480
- // OBJECT SET
1481
- // Note this will not work with a bracket in the same address box set
1482
- var _tmpObjectTypeMarkerIndex2 = pAddress.indexOf('{}');
1483
- if (_tmpObjectTypeMarkerIndex2 > 0) {
1484
- var _tmpObjectPropertyName2 = pAddress.substring(0, _tmpObjectTypeMarkerIndex2).trim();
1485
- if (_typeof(pObject[_tmpObjectPropertyName2]) != 'object') {
1486
- // We asked for a set from an array but it isnt' an array.
1487
- return false;
1488
- }
1489
-
1490
- // We need to enumerate the Object and grab the addresses from there.
1491
- var tmpObjectProperty = pObject[_tmpObjectPropertyName2];
1492
- var tmpObjectPropertyKeys = Object.keys(tmpObjectProperty);
1493
- // Managing the parent address is a bit more complex here -- the box will be added for each element.
1494
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(_tmpObjectPropertyName2);
1495
- // The container object is where we have the "Address":SOMEVALUE pairs
1496
- var _tmpContainerObject2 = {};
1497
- for (var _i7 = 0; _i7 < tmpObjectPropertyKeys.length; _i7++) {
1498
- var _tmpPropertyParentAddress2 = "".concat(tmpParentAddress, ".").concat(tmpObjectPropertyKeys[_i7]);
1499
- var _tmpValue2 = this.getValueAtAddress(pObject[_tmpObjectPropertyName2][tmpObjectPropertyKeys[_i7]], tmpNewAddress, _tmpPropertyParentAddress2, tmpRootObject);
1500
-
1501
- // The filtering is complex but allows config-based metaprogramming directly from schema
1502
- var _tmpKeepRecord2 = this.checkRecordFilters(pAddress, _tmpValue2);
1503
- if (_tmpKeepRecord2) {
1504
- _tmpContainerObject2["".concat(_tmpPropertyParentAddress2, ".").concat(tmpNewAddress)] = _tmpValue2;
1505
- }
1506
- }
1507
- return _tmpContainerObject2;
1508
- }
1509
-
1510
- // If there is an object property already named for the sub object, but it isn't an object
1511
- // then the system can't set the value in there. Error and abort!
1512
- if (tmpSubObjectName in pObject && _typeof(pObject[tmpSubObjectName]) !== 'object') {
1513
- return undefined;
1514
- } else if (tmpSubObjectName in pObject) {
1515
- // If there is already a subobject pass that to the recursive thingy
1516
- // Continue to manage the parent address for recursion
1517
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
1518
- return this.getValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress, tmpRootObject);
1519
- } else {
1520
- // Create a subobject and then pass that
1521
- // Continue to manage the parent address for recursion
1522
- tmpParentAddress = "".concat(tmpParentAddress).concat(tmpParentAddress.length > 0 ? '.' : '').concat(tmpSubObjectName);
1523
- pObject[tmpSubObjectName] = {};
1524
- return this.getValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress, tmpRootObject);
1525
- }
1526
- }
1527
- }
1528
- }]);
1529
- }();
1530
- ;
1531
- module.exports = ManyfestObjectAddressResolverGetValue;
1532
- }, {
1533
- "../source/Manyfest-ParseConditionals.js": 12,
1534
- "./Manyfest-CleanWrapCharacters.js": 3,
1535
- "./Manyfest-LogToConsole.js": 5,
1536
- "./Manyfest-ObjectAddress-Parser.js": 9
1537
- }],
1538
- 9: [function (require, module, exports) {
1539
- // TODO: This is an inelegant solution to delay the rewrite of Manyfest.
1540
-
1541
- // Fable 3.0 has a service for data formatting that deals well with nested enclosures.
1542
-
1543
- // The Manyfest library predates fable 3.0 and the services structure of it, so the functions
1544
- // are more or less pure javascript and as functional as they can be made to be.
1545
-
1546
- // Until we shift Manyfest to be a fable service, these three functions were pulled out of
1547
- // fable to aid in parsing functions with nested enclosures.
1548
-
1549
- var DEFAULT_START_SYMBOL_MAP = {
1550
- '{': 0,
1551
- '[': 1,
1552
- '(': 2
1553
- };
1554
- var DEFAULT_END_SYMBOL_MAP = {
1555
- '}': 0,
1556
- ']': 1,
1557
- ')': 2
1558
- };
1559
- module.exports = {
1560
- /**
1561
- * Count the number of segments in a string, respecting enclosures
1562
- *
1563
- * @param {string} pString
1564
- * @param {string} [pSeparator]
1565
- * @param {Record<string, number>} [pEnclosureStartSymbolMap]
1566
- * @param {Record<string, number>} [pEnclosureEndSymbolMap]
1567
- *
1568
- * @return {number} - The number of segments in the string
1569
- */
1570
- stringCountSegments: function stringCountSegments(pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap) {
1571
- var tmpString = typeof pString == 'string' ? pString : '';
1572
- var tmpSeparator = typeof pSeparator == 'string' ? pSeparator : '.';
1573
- var tmpEnclosureStartSymbolMap = _typeof(pEnclosureStartSymbolMap) == 'object' ? pEnclosureStartSymbolMap : DEFAULT_START_SYMBOL_MAP;
1574
- var tmpEnclosureEndSymbolMap = _typeof(pEnclosureEndSymbolMap) == 'object' ? pEnclosureEndSymbolMap : DEFAULT_END_SYMBOL_MAP;
1575
- if (pString.length < 1) {
1576
- return 0;
1577
- }
1578
- var tmpSegmentCount = 1;
1579
- var tmpEnclosureStack = [];
1580
- for (var i = 0; i < tmpString.length; i++) {
1581
- // IF This is the start of a segment
1582
- if (tmpString[i] == tmpSeparator
1583
- // AND we are not in a nested portion of the string
1584
- && tmpEnclosureStack.length == 0) {
1585
- // Increment the segment count
1586
- tmpSegmentCount++;
1587
- }
1588
- // IF This is the start of an enclosure
1589
- else if (tmpString[i] in tmpEnclosureStartSymbolMap) {
1590
- // Add it to the stack!
1591
- tmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);
1592
- }
1593
- // IF This is the end of an enclosure
1594
- else if (tmpString[i] in tmpEnclosureEndSymbolMap
1595
- // AND it matches the current nest level symbol
1596
- && tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1]) {
1597
- // Pop it off the stack!
1598
- tmpEnclosureStack.pop();
1599
- }
1600
- }
1601
- return tmpSegmentCount;
1602
- },
1603
- /**
1604
- * Get the first segment in a string, respecting enclosures
1605
- *
1606
- * @param {string} pString
1607
- * @param {string} [pSeparator]
1608
- * @param {Record<string, number>} [pEnclosureStartSymbolMap]
1609
- * @param {Record<string, number>} [pEnclosureEndSymbolMap]
1610
- *
1611
- * @return {string} - the first segment in the string as a string
1612
- */
1613
- stringGetFirstSegment: function stringGetFirstSegment(pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap) {
1614
- var tmpString = typeof pString == 'string' ? pString : '';
1615
- var tmpSeparator = typeof pSeparator == 'string' ? pSeparator : '.';
1616
- var tmpEnclosureStartSymbolMap = _typeof(pEnclosureStartSymbolMap) == 'object' ? pEnclosureStartSymbolMap : DEFAULT_START_SYMBOL_MAP;
1617
- var tmpEnclosureEndSymbolMap = _typeof(pEnclosureEndSymbolMap) == 'object' ? pEnclosureEndSymbolMap : DEFAULT_END_SYMBOL_MAP;
1618
- if (pString.length < 1) {
1619
- return '';
1620
- }
1621
- var tmpEnclosureStack = [];
1622
- for (var i = 0; i < tmpString.length; i++) {
1623
- // IF This is the start of a segment
1624
- if (tmpString[i] == tmpSeparator
1625
- // AND we are not in a nested portion of the string
1626
- && tmpEnclosureStack.length == 0) {
1627
- // Return the segment
1628
- return tmpString.substring(0, i);
1629
- }
1630
- // IF This is the start of an enclosure
1631
- else if (tmpString[i] in tmpEnclosureStartSymbolMap) {
1632
- // Add it to the stack!
1633
- tmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);
1634
- }
1635
- // IF This is the end of an enclosure
1636
- else if (tmpString[i] in tmpEnclosureEndSymbolMap
1637
- // AND it matches the current nest level symbol
1638
- && tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1]) {
1639
- // Pop it off the stack!
1640
- tmpEnclosureStack.pop();
1641
- }
1642
- }
1643
- return tmpString;
1644
- },
1645
- /**
1646
- * Get all segments in a string, respecting enclosures
1647
- *
1648
- * @param {string} pString
1649
- * @param {string} [pSeparator]
1650
- * @param {Record<string, number>} [pEnclosureStartSymbolMap]
1651
- * @param {Record<string, number>} [pEnclosureEndSymbolMap]
1652
- *
1653
- * @return {Array<string>} - the segments in the string as an array of strings
1654
- */
1655
- stringGetSegments: function stringGetSegments(pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap) {
1656
- var tmpString = typeof pString == 'string' ? pString : '';
1657
- var tmpSeparator = typeof pSeparator == 'string' ? pSeparator : '.';
1658
- var tmpEnclosureStartSymbolMap = _typeof(pEnclosureStartSymbolMap) == 'object' ? pEnclosureStartSymbolMap : DEFAULT_START_SYMBOL_MAP;
1659
- var tmpEnclosureEndSymbolMap = _typeof(pEnclosureEndSymbolMap) == 'object' ? pEnclosureEndSymbolMap : DEFAULT_END_SYMBOL_MAP;
1660
- var tmpCurrentSegmentStart = 0;
1661
- var tmpSegmentList = [];
1662
- if (pString.length < 1) {
1663
- return tmpSegmentList;
1664
- }
1665
- var tmpEnclosureStack = [];
1666
- for (var i = 0; i < tmpString.length; i++) {
1667
- // IF This is the start of a segment
1668
- if (tmpString[i] == tmpSeparator
1669
- // AND we are not in a nested portion of the string
1670
- && tmpEnclosureStack.length == 0) {
1671
- // Return the segment
1672
- tmpSegmentList.push(tmpString.substring(tmpCurrentSegmentStart, i));
1673
- tmpCurrentSegmentStart = i + 1;
1674
- }
1675
- // IF This is the start of an enclosure
1676
- else if (tmpString[i] in tmpEnclosureStartSymbolMap) {
1677
- // Add it to the stack!
1678
- tmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);
1679
- }
1680
- // IF This is the end of an enclosure
1681
- else if (tmpString[i] in tmpEnclosureEndSymbolMap
1682
- // AND it matches the current nest level symbol
1683
- && tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1]) {
1684
- // Pop it off the stack!
1685
- tmpEnclosureStack.pop();
1686
- }
1687
- }
1688
- if (tmpCurrentSegmentStart < tmpString.length) {
1689
- tmpSegmentList.push(tmpString.substring(tmpCurrentSegmentStart));
1690
- }
1691
- return tmpSegmentList;
1692
- },
1693
- /**
1694
- * Count the number of enclosures in a string based on the start and end characters.
1695
- *
1696
- * If no start or end characters are specified, it will default to parentheses. If the string is not a string, it will return 0.
1697
- *
1698
- * @param {string} pString
1699
- * @param {string} [pEnclosureStart]
1700
- * @param {string} [pEnclosureEnd]
1701
- * @returns the count of full in the string
1702
- */
1703
- stringCountEnclosures: function stringCountEnclosures(pString, pEnclosureStart, pEnclosureEnd) {
1704
- var tmpString = typeof pString == 'string' ? pString : '';
1705
- var tmpEnclosureStart = typeof pEnclosureStart == 'string' ? pEnclosureStart : '(';
1706
- var tmpEnclosureEnd = typeof pEnclosureEnd == 'string' ? pEnclosureEnd : ')';
1707
- var tmpEnclosureCount = 0;
1708
- var tmpEnclosureDepth = 0;
1709
- for (var i = 0; i < tmpString.length; i++) {
1710
- // This is the start of an enclosure
1711
- if (tmpString[i] == tmpEnclosureStart) {
1712
- if (tmpEnclosureDepth == 0) {
1713
- tmpEnclosureCount++;
1714
- }
1715
- tmpEnclosureDepth++;
1716
- } else if (tmpString[i] == tmpEnclosureEnd) {
1717
- tmpEnclosureDepth--;
1718
- }
1719
- }
1720
- return tmpEnclosureCount;
1721
- },
1722
- /**
1723
- * Get the value of the enclosure at the specified index.
1724
- *
1725
- * If the index is not a number, it will default to 0. If the string is not a string, it will return an empty string. If the enclosure is not found, it will return an empty string. If the enclosure
1726
- *
1727
- * @param {string} pString
1728
- * @param {number} pEnclosureIndexToGet
1729
- * @param {string} [pEnclosureStart]
1730
- * @param {string} [pEnclosureEnd]
1731
- *
1732
- * @return {string} - The value of the enclosure at the specified index
1733
- */
1734
- stringGetEnclosureValueByIndex: function stringGetEnclosureValueByIndex(pString, pEnclosureIndexToGet, pEnclosureStart, pEnclosureEnd) {
1735
- var tmpString = typeof pString == 'string' ? pString : '';
1736
- var tmpEnclosureIndexToGet = typeof pEnclosureIndexToGet == 'number' ? pEnclosureIndexToGet : 0;
1737
- var tmpEnclosureStart = typeof pEnclosureStart == 'string' ? pEnclosureStart : '(';
1738
- var tmpEnclosureEnd = typeof pEnclosureEnd == 'string' ? pEnclosureEnd : ')';
1739
- var tmpEnclosureCount = 0;
1740
- var tmpEnclosureDepth = 0;
1741
- var tmpMatchedEnclosureIndex = false;
1742
- var tmpEnclosedValueStartIndex = 0;
1743
- var tmpEnclosedValueEndIndex = 0;
1744
- for (var i = 0; i < tmpString.length; i++) {
1745
- // This is the start of an enclosure
1746
- if (tmpString[i] == tmpEnclosureStart) {
1747
- tmpEnclosureDepth++;
1748
-
1749
- // Only count enclosures at depth 1, but still this parses both pairs of all of them.
1750
- if (tmpEnclosureDepth == 1) {
1751
- tmpEnclosureCount++;
1752
- if (tmpEnclosureIndexToGet == tmpEnclosureCount - 1) {
1753
- // This is the start of *the* enclosure
1754
- tmpMatchedEnclosureIndex = true;
1755
- tmpEnclosedValueStartIndex = i;
1756
- }
1757
- }
1758
- }
1759
- // This is the end of an enclosure
1760
- else if (tmpString[i] == tmpEnclosureEnd) {
1761
- tmpEnclosureDepth--;
1762
-
1763
- // Again, only count enclosures at depth 1, but still this parses both pairs of all of them.
1764
- if (tmpEnclosureDepth == 0 && tmpMatchedEnclosureIndex && tmpEnclosedValueEndIndex <= tmpEnclosedValueStartIndex) {
1765
- tmpEnclosedValueEndIndex = i;
1766
- tmpMatchedEnclosureIndex = false;
1767
- }
1768
- }
1769
- }
1770
- if (tmpEnclosureCount <= tmpEnclosureIndexToGet) {
1771
- // Return an empty string if the enclosure is not found
1772
- return '';
1773
- }
1774
- if (tmpEnclosedValueEndIndex > 0 && tmpEnclosedValueEndIndex > tmpEnclosedValueStartIndex) {
1775
- return tmpString.substring(tmpEnclosedValueStartIndex + 1, tmpEnclosedValueEndIndex);
1776
- } else {
1777
- return tmpString.substring(tmpEnclosedValueStartIndex + 1);
1778
- }
1779
- }
1780
- };
1781
- }, {}],
1782
- 10: [function (require, module, exports) {
1783
- /**
1784
- * @author <steven@velozo.com>
1785
- */
1786
- var libSimpleLog = require('./Manyfest-LogToConsole.js');
1787
- var fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');
1788
-
1789
- /**
1790
- * Object Address Resolver - SetValue
1791
- *
1792
- * IMPORTANT NOTE: This code is intentionally more verbose than necessary, to
1793
- * be extremely clear what is going on in the recursion for
1794
- * each of the three address resolution functions.
1795
- *
1796
- * Although there is some opportunity to repeat ourselves a
1797
- * bit less in this codebase (e.g. with detection of arrays
1798
- * versus objects versus direct properties), it can make
1799
- * debugging.. challenging. The minified version of the code
1800
- * optimizes out almost anything repeated in here. So please
1801
- * be kind and rewind... meaning please keep the codebase less
1802
- * terse and more verbose so humans can comprehend it.
1803
- *
1804
- *
1805
- * @class ManyfestObjectAddressSetValue
1806
- */
1807
- var ManyfestObjectAddressSetValue = /*#__PURE__*/function () {
1808
- /**
1809
- * @param {function} [pInfoLog] - (optional) A logging function for info messages
1810
- * @param {function} [pErrorLog] - (optional) A logging function for error messages
1811
- */
1812
- function ManyfestObjectAddressSetValue(pInfoLog, pErrorLog) {
1813
- _classCallCheck(this, ManyfestObjectAddressSetValue);
1814
- // Wire in logging
1815
- this.logInfo = typeof pInfoLog == 'function' ? pInfoLog : libSimpleLog;
1816
- this.logError = typeof pErrorLog == 'function' ? pErrorLog : libSimpleLog;
1817
- this.cleanWrapCharacters = fCleanWrapCharacters;
1818
- }
1819
-
1820
- /**
1821
- * Set the value of an element at an address
1822
- *
1823
- * @param {object} pObject - The object to set the value in
1824
- * @param {string} pAddress - The address to set the value at
1825
- * @param {any} pValue - The value to set at the address
1826
- *
1827
- * @return {boolean} True if the value was set, false otherwise
1828
- */
1829
- return _createClass(ManyfestObjectAddressSetValue, [{
1830
- key: "setValueAtAddress",
1831
- value: function setValueAtAddress(pObject, pAddress, pValue) {
1832
- // Make sure pObject is an object
1833
- if (_typeof(pObject) != 'object') return false;
1834
- // Make sure pAddress is a string
1835
- if (typeof pAddress != 'string') return false;
1836
- var tmpSeparatorIndex = pAddress.indexOf('.');
1837
- if (tmpSeparatorIndex == -1) {
1838
- // Check if it's a boxed property
1839
- var tmpBracketStartIndex = pAddress.indexOf('[');
1840
- var tmpBracketStopIndex = pAddress.indexOf(']');
1841
- // Boxed elements look like this:
1842
- // MyValues[10]
1843
- // MyValues['Name']
1844
- // MyValues["Age"]
1845
- // MyValues[`Cost`]
1846
- //
1847
- // When we are passed SomeObject["Name"] this code below recurses as if it were SomeObject.Name
1848
- // The requirements to detect a boxed element are:
1849
- // 1) The start bracket is after character 0
1850
- if (tmpBracketStartIndex > 0
1851
- // 2) The end bracket has something between them
1852
- && tmpBracketStopIndex > tmpBracketStartIndex
1853
- // 3) There is data
1854
- && tmpBracketStopIndex - tmpBracketStartIndex > 1) {
1855
- // The "Name" of the Object contained too the left of the bracket
1856
- var tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();
1857
-
1858
- // The "Reference" to the property within it, either an array element or object property
1859
- var tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex + 1, tmpBracketStopIndex).trim();
1860
- // Attempt to parse the reference as a number, which will be used as an array element
1861
- var tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);
1862
- var tmpIndexIsNumeric = !isNaN(tmpBoxedPropertyNumber);
1863
- if (pObject[tmpBoxedPropertyName] == null) {
1864
- if (tmpIndexIsNumeric) {
1865
- pObject[tmpBoxedPropertyName] = [];
1866
- } else {
1867
- pObject[tmpBoxedPropertyName] = {};
1868
- }
1869
- }
1870
-
1871
- // If the subproperty doesn't test as a proper Object, none of the rest of this is possible.
1872
- // This is a rare case where Arrays testing as Objects is useful
1873
- if (_typeof(pObject[tmpBoxedPropertyName]) !== 'object') {
1874
- return false;
1875
- }
1876
-
1877
- // Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
1878
- // This seems confusing to me at first read, so explaination:
1879
- // Is the Boxed Object an Array? TRUE
1880
- // And is the Reference inside the boxed Object not a number? TRUE
1881
- // --> So when these are in agreement, it's an impossible access state
1882
- if (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber)) {
1883
- return false;
1884
- }
1885
-
1886
- // 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,
1887
- // otherwise we will try to treat it as a dynamic object property.
1888
- if (isNaN(tmpBoxedPropertyNumber)) {
1889
- // This isn't a number ... let's treat it as a dynamic object property.
1890
- // We would expect the property to be wrapped in some kind of quotes so strip them
1891
- tmpBoxedPropertyReference = this.cleanWrapCharacters('"', tmpBoxedPropertyReference);
1892
- tmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);
1893
- tmpBoxedPropertyReference = this.cleanWrapCharacters("'", tmpBoxedPropertyReference);
1894
- if (!(tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName])) {
1895
- // If the subobject doesn't exist, create it
1896
- pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = {};
1897
- }
1898
-
1899
- // Return the value in the property
1900
- //TODO: For cases where we have chained [][] properties, this needs to recurse somehow
1901
- pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = pValue;
1902
- return true;
1903
- } else {
1904
- while (pObject[tmpBoxedPropertyName].length < tmpBoxedPropertyNumber + 1) {
1905
- // If the subobject doesn't exist, create it
1906
- pObject[tmpBoxedPropertyName].push({});
1907
- }
1908
- pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber] = pValue;
1909
- return true;
1910
- }
1911
- } else {
1912
- // Now is the time in recursion to set the value in the object
1913
- pObject[pAddress] = pValue;
1914
- return true;
1915
- }
1916
- } else {
1917
- var tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);
1918
- var tmpNewAddress = pAddress.substring(tmpSeparatorIndex + 1);
1919
-
1920
- // Test if the tmpNewAddress is an array or object
1921
- // Check if it's a boxed property
1922
- var _tmpBracketStartIndex4 = tmpSubObjectName.indexOf('[');
1923
- var _tmpBracketStopIndex4 = tmpSubObjectName.indexOf(']');
1924
- // Boxed elements look like this:
1925
- // MyValues[42]
1926
- // MyValues['Color']
1927
- // MyValues["Weight"]
1928
- // MyValues[`Diameter`]
1929
- //
1930
- // When we are passed SomeObject["Name"] this code below recurses as if it were SomeObject.Name
1931
- // The requirements to detect a boxed element are:
1932
- // 1) The start bracket is after character 0
1933
- if (_tmpBracketStartIndex4 > 0
1934
- // 2) The end bracket has something between them
1935
- && _tmpBracketStopIndex4 > _tmpBracketStartIndex4
1936
- // 3) There is data
1937
- && _tmpBracketStopIndex4 - _tmpBracketStartIndex4 > 1) {
1938
- var _tmpBoxedPropertyName8 = tmpSubObjectName.substring(0, _tmpBracketStartIndex4).trim();
1939
- var _tmpBoxedPropertyReference4 = tmpSubObjectName.substring(_tmpBracketStartIndex4 + 1, _tmpBracketStopIndex4).trim();
1940
- var _tmpBoxedPropertyNumber4 = parseInt(_tmpBoxedPropertyReference4, 10);
1941
- var _tmpIndexIsNumeric = !isNaN(_tmpBoxedPropertyNumber4);
1942
-
1943
- //if (typeof(pObject[tmpBoxedPropertyName]) !== 'object')
1944
- if (pObject[_tmpBoxedPropertyName8] == null) {
1945
- if (_tmpIndexIsNumeric) {
1946
- pObject[_tmpBoxedPropertyName8] = [];
1947
- } else {
1948
- pObject[_tmpBoxedPropertyName8] = {};
1949
- }
1950
- }
1951
-
1952
- // Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.
1953
- // This seems confusing to me at first read, so explaination:
1954
- // Is the Boxed Object an Array? TRUE
1955
- // And is the Reference inside the boxed Object not a number? TRUE
1956
- // --> So when these are in agreement, it's an impossible access state
1957
- // This could be a failure in the recursion chain because they passed something like this in:
1958
- // StudentData.Sections.Algebra.Students[1].Tardy
1959
- // BUT
1960
- // StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access
1961
- // This could be a failure in the recursion chain because they passed something like this in:
1962
- // StudentData.Sections.Algebra.Students["JaneDoe"].Grade
1963
- // BUT
1964
- // StudentData.Sections.Algebra.Students is an array, so the ["JaneDoe"].Grade is not possible to access
1965
- // TODO: Should this be an error or something? Should we keep a log of failures like this?
1966
- if (Array.isArray(pObject[_tmpBoxedPropertyName8]) != _tmpIndexIsNumeric) {
1967
- return false;
1968
- }
1969
-
1970
- //This is a bracketed value
1971
- // 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,
1972
- // otherwise we will try to reat it as a dynamic object property.
1973
- if (isNaN(_tmpBoxedPropertyNumber4)) {
1974
- // This isn't a number ... let's treat it as a dynanmic object property.
1975
- _tmpBoxedPropertyReference4 = this.cleanWrapCharacters('"', _tmpBoxedPropertyReference4);
1976
- _tmpBoxedPropertyReference4 = this.cleanWrapCharacters('`', _tmpBoxedPropertyReference4);
1977
- _tmpBoxedPropertyReference4 = this.cleanWrapCharacters("'", _tmpBoxedPropertyReference4);
1978
- if (!(_tmpBoxedPropertyReference4 in pObject[_tmpBoxedPropertyName8])) {
1979
- // If the subobject doesn't exist, create it
1980
- pObject[_tmpBoxedPropertyName8][_tmpBoxedPropertyReference4] = {};
1981
- }
1982
-
1983
- // Recurse directly into the subobject
1984
- return this.setValueAtAddress(pObject[_tmpBoxedPropertyName8][_tmpBoxedPropertyReference4], tmpNewAddress, pValue);
1985
- } else {
1986
- while (pObject[_tmpBoxedPropertyName8].length < _tmpBoxedPropertyNumber4 + 1) {
1987
- // If the subobject doesn't exist, create it
1988
- pObject[_tmpBoxedPropertyName8].push({});
1989
- }
1990
-
1991
- // We parsed a valid number out of the boxed property name, so recurse into the array
1992
- return this.setValueAtAddress(pObject[_tmpBoxedPropertyName8][_tmpBoxedPropertyNumber4], tmpNewAddress, pValue);
1993
- }
1994
- }
1995
-
1996
- // If there is an object property already named for the sub object, but it isn't an object
1997
- // then the system can't set the value in there. Error and abort!
1998
- if (tmpSubObjectName in pObject && _typeof(pObject[tmpSubObjectName]) !== 'object') {
1999
- if (!('__ERROR' in pObject)) pObject['__ERROR'] = {};
2000
- // Put it in an error object so data isn't lost
2001
- pObject['__ERROR'][pAddress] = pValue;
2002
- return false;
2003
- } else if (tmpSubObjectName in pObject) {
2004
- // If there is already a subobject pass that to the recursive thingy
2005
- return this.setValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, pValue);
2006
- } else {
2007
- // Create a subobject and then pass that
2008
- pObject[tmpSubObjectName] = {};
2009
- return this.setValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, pValue);
2010
- }
2011
- }
2012
- }
2013
- }]);
2014
- }();
2015
- ;
2016
- module.exports = ManyfestObjectAddressSetValue;
2017
- }, {
2018
- "./Manyfest-CleanWrapCharacters.js": 3,
2019
- "./Manyfest-LogToConsole.js": 5
2020
- }],
2021
- 11: [function (require, module, exports) {
2022
- /**
2023
- * @author <steven@velozo.com>
2024
- */
2025
- var libSimpleLog = require('./Manyfest-LogToConsole.js');
2026
-
2027
- /**
2028
- * Object Address Generation
2029
- *
2030
- * Automagically generate addresses and properties based on a passed-in object,
2031
- * to be used for easy creation of schemas. Meant to simplify the lives of
2032
- * developers wanting to create schemas without typing a bunch of stuff.
2033
- *
2034
- * IMPORTANT NOTE: This code is intentionally more verbose than necessary, to
2035
- * be extremely clear what is going on in the recursion for
2036
- * each of the three address resolution functions.
2037
- *
2038
- * Although there is some opportunity to repeat ourselves a
2039
- * bit less in this codebase (e.g. with detection of arrays
2040
- * versus objects versus direct properties), it can make
2041
- * debugging.. challenging. The minified version of the code
2042
- * optimizes out almost anything repeated in here. So please
2043
- * be kind and rewind... meaning please keep the codebase less
2044
- * terse and more verbose so humans can comprehend it.
2045
- *
2046
- *
2047
- * @class ManyfestObjectAddressGeneration
2048
- */
2049
- var ManyfestObjectAddressGeneration = /*#__PURE__*/function () {
2050
- /**
2051
- * @param {function} [pInfoLog] - (optional) A logging function for info messages
2052
- * @param {function} [pErrorLog] - (optional) A logging function for error messages
2053
- */
2054
- function ManyfestObjectAddressGeneration(pInfoLog, pErrorLog) {
2055
- _classCallCheck(this, ManyfestObjectAddressGeneration);
2056
- // Wire in logging
2057
- this.logInfo = typeof pInfoLog == 'function' ? pInfoLog : libSimpleLog;
2058
- this.logError = typeof pErrorLog == 'function' ? pErrorLog : libSimpleLog;
2059
- }
2060
-
2061
- /**
2062
- * generateAddressses
2063
- *
2064
- * This flattens an object into a set of key:value pairs for *EVERY SINGLE
2065
- * POSSIBLE ADDRESS* in the object. It can get ... really insane really
2066
- * quickly. This is not meant to be used directly to generate schemas, but
2067
- * instead as a starting point for scripts or UIs.
2068
- *
2069
- * This will return a mega set of key:value pairs with all possible schema
2070
- * permutations and default values (when not an object) and everything else.
2071
- *
2072
- * @param {any} pObject - The object to generate addresses for
2073
- * @param {string} [pBaseAddress] - (optional) The base address to start from
2074
- * @param {object} [pSchema] - (optional) The schema object to append to
2075
- *
2076
- * @return {object} The generated schema object
2077
- */
2078
- return _createClass(ManyfestObjectAddressGeneration, [{
2079
- key: "generateAddressses",
2080
- value: function generateAddressses(pObject, pBaseAddress, pSchema) {
2081
- var tmpBaseAddress = typeof pBaseAddress == 'string' ? pBaseAddress : '';
2082
- var tmpSchema = _typeof(pSchema) == 'object' ? pSchema : {};
2083
- var tmpObjectType = _typeof(pObject);
2084
- var tmpSchemaObjectEntry = {
2085
- Address: tmpBaseAddress,
2086
- Hash: tmpBaseAddress,
2087
- Name: tmpBaseAddress,
2088
- // This is so scripts and UI controls can force a developer to opt-in.
2089
- InSchema: false
2090
- };
2091
- if (tmpObjectType == 'object' && pObject == null) {
2092
- tmpObjectType = 'undefined';
2093
- }
2094
- switch (tmpObjectType) {
2095
- case 'string':
2096
- tmpSchemaObjectEntry.DataType = 'String';
2097
- tmpSchemaObjectEntry.Default = pObject;
2098
- tmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;
2099
- break;
2100
- case 'number':
2101
- case 'bigint':
2102
- tmpSchemaObjectEntry.DataType = 'Number';
2103
- tmpSchemaObjectEntry.Default = pObject;
2104
- tmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;
2105
- break;
2106
- case 'undefined':
2107
- tmpSchemaObjectEntry.DataType = 'Any';
2108
- tmpSchemaObjectEntry.Default = pObject;
2109
- tmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;
2110
- break;
2111
- case 'object':
2112
- if (Array.isArray(pObject)) {
2113
- tmpSchemaObjectEntry.DataType = 'Array';
2114
- if (tmpBaseAddress != '') {
2115
- tmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;
2116
- }
2117
- for (var i = 0; i < pObject.length; i++) {
2118
- this.generateAddressses(pObject[i], "".concat(tmpBaseAddress, "[").concat(i, "]"), tmpSchema);
2119
- }
2120
- } else {
2121
- tmpSchemaObjectEntry.DataType = 'Object';
2122
- if (tmpBaseAddress != '') {
2123
- tmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;
2124
- tmpBaseAddress += '.';
2125
- }
2126
- var tmpObjectProperties = Object.keys(pObject);
2127
- for (var _i8 = 0; _i8 < tmpObjectProperties.length; _i8++) {
2128
- this.generateAddressses(pObject[tmpObjectProperties[_i8]], "".concat(tmpBaseAddress).concat(tmpObjectProperties[_i8]), tmpSchema);
2129
- }
2130
- }
2131
- break;
2132
- case 'symbol':
2133
- case 'function':
2134
- // Symbols and functions neither recurse nor get added to the schema
2135
- break;
2136
- }
2137
- return tmpSchema;
2138
- }
2139
- }]);
2140
- }();
2141
- ;
2142
- module.exports = ManyfestObjectAddressGeneration;
2143
- }, {
2144
- "./Manyfest-LogToConsole.js": 5
2145
- }],
2146
- 12: [function (require, module, exports) {
2147
- // Given a string, parse out any conditional expressions and set whether or not to keep the record.
2148
- //
2149
- // For instance:
2150
- // 'files[]<<~?format,==,Thumbnail?~>>'
2151
- // 'files[]<<~?format,==,Metadata?~>>'
2152
- // 'files[]<<~?size,>,4000?~>>'
2153
- //
2154
- // The wrapping parts are the <<~? and ?~>> megabrackets.
2155
- //
2156
- // The function does not need to alter the string -- just check the conditionals within.
2157
-
2158
- // TODO: Consider making this an es6 class
2159
-
2160
- // Let's use indexOf since it is apparently the fastest.
2161
- var _ConditionalStanzaStart = '<<~?';
2162
- var _ConditionalStanzaStartLength = _ConditionalStanzaStart.length;
2163
- var _ConditionalStanzaEnd = '?~>>';
2164
- var _ConditionalStanzaEndLength = _ConditionalStanzaEnd.length;
2165
-
2166
- // Ugh dependency injection. Can't wait to make these all fable services.
2167
- //let libObjectAddressCheckAddressExists = new (require('./Manyfest-ObjectAddress-CheckAddressExists.js'))();
2168
-
2169
- // Test the condition of a value in a record
2170
- var testCondition = function testCondition(pManyfest, pRecord, pSearchAddress, pSearchComparator, pValue) {
2171
- switch (pSearchComparator) {
2172
- case 'TRUE':
2173
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) === true;
2174
- break;
2175
- case 'FALSE':
2176
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) === false;
2177
- break;
2178
- case 'LNGT':
2179
- case 'LENGTH_GREATER_THAN':
2180
- switch (_typeof(pManyfest.getValueAtAddress(pRecord, pSearchAddress))) {
2181
- case 'string':
2182
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress).length > pValue;
2183
- break;
2184
- case 'object':
2185
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress).length > pValue;
2186
- break;
2187
- default:
2188
- return false;
2189
- break;
2190
- }
2191
- break;
2192
- case 'LNLT':
2193
- case 'LENGTH_LESS_THAN':
2194
- switch (_typeof(pManyfest.getValueAtAddress(pRecord, pSearchAddress))) {
2195
- case 'string':
2196
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress).length < pValue;
2197
- break;
2198
- case 'object':
2199
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress).length < pValue;
2200
- break;
2201
- default:
2202
- return false;
2203
- break;
2204
- }
2205
- break;
2206
- // TODO: Welcome to dependency hell. This fixes itself when we move to fable services.
2207
- // case 'EX':
2208
- // case 'EXISTS':
2209
- // return libObjectAddressCheckAddressExists.checkAddressExists(pRecord, pSearchAddress);
2210
- // break;
2211
- // case 'DNEX':
2212
- // case 'DOES_NOT_EXIST':
2213
- // return !libObjectAddressCheckAddressExists.checkAddressExists(pRecord, pSearchAddress);
2214
- // break;
2215
- case '!=':
2216
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) != pValue;
2217
- break;
2218
- case '<':
2219
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) < pValue;
2220
- break;
2221
- case '>':
2222
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) > pValue;
2223
- break;
2224
- case '<=':
2225
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) <= pValue;
2226
- break;
2227
- case '>=':
2228
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) >= pValue;
2229
- break;
2230
- case '===':
2231
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) === pValue;
2232
- break;
2233
- case '==':
2234
- default:
2235
- return pManyfest.getValueAtAddress(pRecord, pSearchAddress) == pValue;
2236
- break;
2237
- }
2238
- };
2239
- var parseConditionals = function parseConditionals(pManyfest, pAddress, pRecord) {
2240
- var tmpKeepRecord = true;
2241
-
2242
- /*
2243
- Algorithm is simple:
2244
- 1. Enuerate start points
2245
- 2. Find stop points within each start point
2246
- 3. Check the conditional
2247
- */
2248
- var tmpStartIndex = pAddress.indexOf(_ConditionalStanzaStart);
2249
- while (tmpStartIndex != -1) {
2250
- var tmpStopIndex = pAddress.indexOf(_ConditionalStanzaEnd, tmpStartIndex + _ConditionalStanzaStartLength);
2251
- if (tmpStopIndex != -1) {
2252
- var tmpMagicComparisonPatternSet = pAddress.substring(tmpStartIndex + _ConditionalStanzaStartLength, tmpStopIndex).split(',');
2253
-
2254
- // The address to search for
2255
- var tmpSearchAddress = tmpMagicComparisonPatternSet[0];
2256
-
2257
- // The copmparison expression (EXISTS as default)
2258
- var tmpSearchComparator = 'EXISTS';
2259
- if (tmpMagicComparisonPatternSet.length > 1) {
2260
- tmpSearchComparator = tmpMagicComparisonPatternSet[1];
2261
- }
2262
-
2263
- // The value to search for
2264
- var tmpSearchValue = false;
2265
- if (tmpMagicComparisonPatternSet.length > 2) {
2266
- tmpSearchValue = tmpMagicComparisonPatternSet[2];
2267
- }
2268
-
2269
- // Process the piece
2270
- tmpKeepRecord = tmpKeepRecord && testCondition(pManyfest, pRecord, tmpSearchAddress, tmpSearchComparator, tmpSearchValue);
2271
- tmpStartIndex = pAddress.indexOf(_ConditionalStanzaStart, tmpStopIndex + _ConditionalStanzaEndLength);
2272
- } else {
2273
- tmpStartIndex = -1;
2274
- }
2275
- }
2276
- return tmpKeepRecord;
2277
- };
2278
- module.exports = parseConditionals;
2279
- }, {}],
2280
- 13: [function (require, module, exports) {
2281
- /**
2282
- * @author <steven@velozo.com>
2283
- */
2284
- var libSimpleLog = require('./Manyfest-LogToConsole.js');
2285
-
2286
- /**
2287
- * Schema Manipulation Functions
2288
- *
2289
- * @class ManyfestSchemaManipulation
2290
- */
2291
- var ManyfestSchemaManipulation = /*#__PURE__*/function () {
2292
- /**
2293
- * @param {function} [pInfoLog] - (optional) A logging function for info messages
2294
- * @param {function} [pErrorLog] - (optional) A logging function for error messages
2295
- */
2296
- function ManyfestSchemaManipulation(pInfoLog, pErrorLog) {
2297
- _classCallCheck(this, ManyfestSchemaManipulation);
2298
- // Wire in logging
2299
- this.logInfo = typeof pInfoLog === 'function' ? pInfoLog : libSimpleLog;
2300
- this.logError = typeof pErrorLog === 'function' ? pErrorLog : libSimpleLog;
2301
- }
2302
-
2303
- /**
2304
- * This translates the default address mappings to something different.
2305
- *
2306
- * For instance you can pass in manyfest schema descriptor object:
2307
- * {
2308
- * "Address.Of.a": { "Hash": "a", "Type": "Number" },
2309
- * "Address.Of.b": { "Hash": "b", "Type": "Number" }
2310
- * }
2311
- *
2312
- *
2313
- * And then an address mapping (basically a Hash->Address map)
2314
- * {
2315
- * "a": "New.Address.Of.a",
2316
- * "b": "New.Address.Of.b"
2317
- * }
2318
- *
2319
- * NOTE: This mutates the schema object permanently, altering the base hash.
2320
- * If there is a collision with an existing address, it can lead to overwrites.
2321
- * TODO: Discuss what should happen on collisions.
2322
- *
2323
- * @param {object} pManyfestSchemaDescriptors - The manyfest schema descriptors to resolve address mappings for
2324
- * @param {object} pAddressMapping - The address mapping object to use for remapping
2325
- *
2326
- * @return {boolean} True if successful, false if there was an error
2327
- */
2328
- return _createClass(ManyfestSchemaManipulation, [{
2329
- key: "resolveAddressMappings",
2330
- value: function resolveAddressMappings(pManyfestSchemaDescriptors, pAddressMapping) {
2331
- if (_typeof(pManyfestSchemaDescriptors) != 'object') {
2332
- this.logError("Attempted to resolve address mapping but the descriptor was not an object.");
2333
- return false;
2334
- }
2335
- if (_typeof(pAddressMapping) != 'object') {
2336
- // No mappings were passed in
2337
- return true;
2338
- }
2339
-
2340
- // Get the arrays of both the schema definition and the hash mapping
2341
- var tmpManyfestAddresses = Object.keys(pManyfestSchemaDescriptors);
2342
- var tmpHashMapping = {};
2343
- tmpManyfestAddresses.forEach(function (pAddress) {
2344
- if ('Hash' in pManyfestSchemaDescriptors[pAddress]) {
2345
- tmpHashMapping[pManyfestSchemaDescriptors[pAddress].Hash] = pAddress;
2346
- }
2347
- });
2348
- var tmpAddressMappingSet = Object.keys(pAddressMapping);
2349
- tmpAddressMappingSet.forEach(function (pInputAddress) {
2350
- var tmpNewDescriptorAddress = pAddressMapping[pInputAddress];
2351
- var tmpOldDescriptorAddress = null;
2352
- var tmpDescriptor;
2353
-
2354
- // See if there is a matching descriptor either by Address directly or Hash
2355
- if (pInputAddress in pManyfestSchemaDescriptors) {
2356
- tmpOldDescriptorAddress = pInputAddress;
2357
- } else if (pInputAddress in tmpHashMapping) {
2358
- tmpOldDescriptorAddress = tmpHashMapping[pInputAddress];
2359
- }
2360
-
2361
- // If there was a matching descriptor in the manifest, store it in the temporary descriptor
2362
- if (tmpOldDescriptorAddress) {
2363
- tmpDescriptor = pManyfestSchemaDescriptors[tmpOldDescriptorAddress];
2364
- delete pManyfestSchemaDescriptors[tmpOldDescriptorAddress];
2365
- } else {
2366
- // Create a new descriptor! Map it to the input address.
2367
- tmpDescriptor = {
2368
- Hash: pInputAddress
2369
- };
2370
- }
2371
-
2372
- // Now re-add the descriptor to the manyfest schema
2373
- pManyfestSchemaDescriptors[tmpNewDescriptorAddress] = tmpDescriptor;
2374
- });
2375
- return true;
2376
- }
2377
-
2378
- /**
2379
- * @param {object} pManyfestSchemaDescriptors - The manyfest schema descriptors to resolve address mappings for
2380
- * @param {object} pAddressMapping - The address mapping object to use for remapping
2381
- *
2382
- * @return {object} A new object containing the remapped schema descriptors
2383
- */
2384
- }, {
2385
- key: "safeResolveAddressMappings",
2386
- value: function safeResolveAddressMappings(pManyfestSchemaDescriptors, pAddressMapping) {
2387
- // This returns the descriptors as a new object, safely remapping without mutating the original schema Descriptors
2388
- var tmpManyfestSchemaDescriptors = JSON.parse(JSON.stringify(pManyfestSchemaDescriptors));
2389
- this.resolveAddressMappings(tmpManyfestSchemaDescriptors, pAddressMapping);
2390
- return tmpManyfestSchemaDescriptors;
2391
- }
2392
-
2393
- /**
2394
- * @param {object} pManyfestSchemaDescriptorsDestination - The destination manyfest schema descriptors
2395
- * @param {object} pManyfestSchemaDescriptorsSource - The source manyfest schema descriptors
2396
- *
2397
- * @return {object} A new object containing the merged schema descriptors
2398
- */
2399
- }, {
2400
- key: "mergeAddressMappings",
2401
- value: function mergeAddressMappings(pManyfestSchemaDescriptorsDestination, pManyfestSchemaDescriptorsSource) {
2402
- if (_typeof(pManyfestSchemaDescriptorsSource) != 'object' || _typeof(pManyfestSchemaDescriptorsDestination) != 'object') {
2403
- this.logError("Attempted to merge two schema descriptors but both were not objects.");
2404
- return false;
2405
- }
2406
- var tmpSource = JSON.parse(JSON.stringify(pManyfestSchemaDescriptorsSource));
2407
- var tmpNewManyfestSchemaDescriptors = JSON.parse(JSON.stringify(pManyfestSchemaDescriptorsDestination));
2408
-
2409
- // The first passed-in set of descriptors takes precedence.
2410
- var tmpDescriptorAddresses = Object.keys(tmpSource);
2411
- tmpDescriptorAddresses.forEach(function (pDescriptorAddress) {
2412
- if (!(pDescriptorAddress in tmpNewManyfestSchemaDescriptors)) {
2413
- tmpNewManyfestSchemaDescriptors[pDescriptorAddress] = tmpSource[pDescriptorAddress];
2414
- }
2415
- });
2416
- return tmpNewManyfestSchemaDescriptors;
2417
- }
2418
- }]);
2419
- }();
2420
- module.exports = ManyfestSchemaManipulation;
2421
- }, {
2422
- "./Manyfest-LogToConsole.js": 5
2423
- }],
2424
- 14: [function (require, module, exports) {
2425
- /**
2426
- * @author <steven@velozo.com>
2427
- */
2428
- var libFableServiceProviderBase = require('fable-serviceproviderbase');
2429
- var libSimpleLog = require('./Manyfest-LogToConsole.js');
2430
- var libHashTranslation = require('./Manyfest-HashTranslation.js');
2431
- var libObjectAddressCheckAddressExists = require('./Manyfest-ObjectAddress-CheckAddressExists.js');
2432
- var libObjectAddressGetValue = require('./Manyfest-ObjectAddress-GetValue.js');
2433
- var libObjectAddressSetValue = require('./Manyfest-ObjectAddress-SetValue.js');
2434
- var libObjectAddressDeleteValue = require('./Manyfest-ObjectAddress-DeleteValue.js');
2435
- var libObjectAddressGeneration = require('./Manyfest-ObjectAddressGeneration.js');
2436
- var libSchemaManipulation = require('./Manyfest-SchemaManipulation.js');
2437
- var _DefaultConfiguration = {
2438
- Scope: 'DEFAULT',
2439
- Descriptors: {}
2440
- };
2441
-
2442
- /**
2443
- * @typedef {{
2444
- * Hash?: string,
2445
- * Name?: string,
2446
- * DataType?: string,
2447
- * Required?: boolean,
2448
- * Address?: string,
2449
- * Description?: string,
2450
- * [key: string]: any,
2451
- * }} ManifestDescriptor
2452
- */
2453
-
2454
- /**
2455
- * Manyfest object address-based descriptions and manipulations.
2456
- *
2457
- * @class Manyfest
2458
- */
2459
- var Manyfest = /*#__PURE__*/function (_libFableServiceProvi) {
2460
- function Manyfest(pFable, pManifest, pServiceHash) {
2461
- var _this3;
2462
- _classCallCheck(this, Manyfest);
2463
- if (pFable === undefined) {
2464
- _this3 = _callSuper(this, Manyfest, [{}]);
2465
- } else {
2466
- _this3 = _callSuper(this, Manyfest, [pFable, pManifest, pServiceHash]);
2467
- }
2468
-
2469
- /** @type {import('fable')} */
2470
- _this3.fable;
2471
- /** @type {Record<string, any>} */
2472
- _this3.options;
2473
- /** @type {string} */
2474
- _this3.Hash;
2475
- /** @type {string} */
2476
- _this3.UUID;
2477
- _this3.serviceType = 'Manifest';
2478
-
2479
- // Wire in logging
2480
- _this3.logInfo = libSimpleLog;
2481
- _this3.logError = libSimpleLog;
2482
-
2483
- // Create an object address resolver and map in the functions
2484
- _this3.objectAddressCheckAddressExists = new libObjectAddressCheckAddressExists(_this3.logInfo, _this3.logError);
2485
- _this3.objectAddressGetValue = new libObjectAddressGetValue(_this3.logInfo, _this3.logError);
2486
- _this3.objectAddressSetValue = new libObjectAddressSetValue(_this3.logInfo, _this3.logError);
2487
- _this3.objectAddressDeleteValue = new libObjectAddressDeleteValue(_this3.logInfo, _this3.logError);
2488
- if (!('defaultValues' in _this3.options)) {
2489
- _this3.options.defaultValues = {
2490
- "String": "",
2491
- "Number": 0,
2492
- "Float": 0.0,
2493
- "Integer": 0,
2494
- "PreciseNumber": "0.0",
2495
- "Boolean": false,
2496
- "Binary": 0,
2497
- "DateTime": 0,
2498
- "Array": [],
2499
- "Object": {},
2500
- "Null": null
2501
- };
2502
- }
2503
- if (!('strict' in _this3.options)) {
2504
- _this3.options.strict = false;
2505
- }
2506
-
2507
- /** @type {string} */
2508
- _this3.scope = undefined;
2509
- /** @type {Array<string>} */
2510
- _this3.elementAddresses = undefined;
2511
- /** @type {Record<string, string>} */
2512
- _this3.elementHashes = undefined;
2513
- /** @type {Record<string, ManifestDescriptor>} */
2514
- _this3.elementDescriptors = undefined;
2515
- _this3.reset();
2516
- if (_typeof(_this3.options) === 'object') {
2517
- _this3.loadManifest(_this3.options);
2518
- }
2519
- _this3.schemaManipulations = new libSchemaManipulation(_this3.logInfo, _this3.logError);
2520
- _this3.objectAddressGeneration = new libObjectAddressGeneration(_this3.logInfo, _this3.logError);
2521
- _this3.hashTranslations = new libHashTranslation(_this3.logInfo, _this3.logError);
2522
- _this3.numberRegex = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
2523
- return _assertThisInitialized(_this3);
2524
- }
2525
-
2526
- /*************************************************************************
2527
- * Schema Manifest Loading, Reading, Manipulation and Serialization Functions
2528
- */
2529
-
2530
- // Reset critical manifest properties
2531
- _inherits(Manyfest, _libFableServiceProvi);
2532
- return _createClass(Manyfest, [{
2533
- key: "reset",
2534
- value: function reset() {
2535
- this.scope = 'DEFAULT';
2536
- this.elementAddresses = [];
2537
- this.elementHashes = {};
2538
- this.elementDescriptors = {};
2539
- }
2540
- }, {
2541
- key: "clone",
2542
- value: function clone() {
2543
- // Make a copy of the options in-place
2544
- var tmpNewOptions = JSON.parse(JSON.stringify(this.options));
2545
- var tmpNewManyfest = new Manyfest(this.fable, tmpNewOptions, this.Hash);
2546
- tmpNewManyfest.logInfo = this.logInfo;
2547
- tmpNewManyfest.logError = this.logError;
2548
- //FIXME: mostly written by co-pilot
2549
- var _this$getManifest = this.getManifest(),
2550
- Scope = _this$getManifest.Scope,
2551
- Descriptors = _this$getManifest.Descriptors,
2552
- HashTranslations = _this$getManifest.HashTranslations;
2553
- tmpNewManyfest.scope = Scope;
2554
- tmpNewManyfest.elementDescriptors = Descriptors;
2555
- tmpNewManyfest.elementAddresses = Object.keys(Descriptors);
2556
- // Rebuild the element hashes
2557
- for (var i = 0; i < tmpNewManyfest.elementAddresses.length; i++) {
2558
- var tmpAddress = tmpNewManyfest.elementAddresses[i];
2559
- var tmpDescriptor = tmpNewManyfest.elementDescriptors[tmpAddress];
2560
- tmpNewManyfest.elementHashes[tmpAddress] = tmpAddress;
2561
- if ('Hash' in tmpDescriptor) {
2562
- tmpNewManyfest.elementHashes[tmpDescriptor.Hash] = tmpAddress;
2563
- }
2564
- }
2565
-
2566
- // Import the hash translations
2567
- tmpNewManyfest.hashTranslations.addTranslation(this.hashTranslations.translationTable);
2568
- return tmpNewManyfest;
2569
- }
2570
-
2571
- // Deserialize a Manifest from a string
2572
- /**
2573
- * @param {string} pManifestString - The manifest string to deserialize
2574
- *
2575
- * @return {Manyfest} The deserialized manifest
2576
- */
2577
- }, {
2578
- key: "deserialize",
2579
- value: function deserialize(pManifestString) {
2580
- // TODO: Add guards for bad manifest string
2581
- this.loadManifest(JSON.parse(pManifestString));
2582
- return this;
2583
- }
2584
-
2585
- // Load a manifest from an object
2586
- }, {
2587
- key: "loadManifest",
2588
- value: function loadManifest(pManifest) {
2589
- if (_typeof(pManifest) !== 'object') {
2590
- this.logError("(".concat(this.scope, ") Error loading manifest; expecting an object but parameter was type ").concat(_typeof(pManifest), "."));
2591
- }
2592
- var tmpManifest = _typeof(pManifest) == 'object' ? pManifest : {};
2593
- var tmpDescriptorKeys = Object.keys(_DefaultConfiguration);
2594
- for (var i = 0; i < tmpDescriptorKeys.length; i++) {
2595
- if (!(tmpDescriptorKeys[i] in tmpManifest)) {
2596
- tmpManifest[tmpDescriptorKeys[i]] = JSON.parse(JSON.stringify(_DefaultConfiguration[tmpDescriptorKeys[i]]));
2597
- }
2598
- }
2599
- if ('Scope' in tmpManifest) {
2600
- if (typeof tmpManifest.Scope === 'string') {
2601
- this.scope = tmpManifest.Scope;
2602
- } else {
2603
- this.logError("(".concat(this.scope, ") Error loading scope from manifest; expecting a string but property was type ").concat(_typeof(tmpManifest.Scope), "."), tmpManifest);
2604
- }
2605
- } else {
2606
- this.logError("(".concat(this.scope, ") Error loading scope from manifest object. Property \"Scope\" does not exist in the root of the object."), tmpManifest);
2607
- }
2608
- if ('Descriptors' in tmpManifest) {
2609
- if (_typeof(tmpManifest.Descriptors) === 'object') {
2610
- var tmpDescriptionAddresses = Object.keys(tmpManifest.Descriptors);
2611
- for (var _i9 = 0; _i9 < tmpDescriptionAddresses.length; _i9++) {
2612
- this.addDescriptor(tmpDescriptionAddresses[_i9], tmpManifest.Descriptors[tmpDescriptionAddresses[_i9]]);
2613
- }
2614
- } else {
2615
- this.logError("(".concat(this.scope, ") Error loading description object from manifest object. Expecting an object in 'Manifest.Descriptors' but the property was type ").concat(_typeof(tmpManifest.Descriptors), "."), tmpManifest);
2616
- }
2617
- } else {
2618
- this.logError("(".concat(this.scope, ") Error loading object description from manifest object. Property \"Descriptors\" does not exist in the root of the Manifest object."), tmpManifest);
2619
- }
2620
- if ('HashTranslations' in tmpManifest) {
2621
- if (_typeof(tmpManifest.HashTranslations) === 'object') {
2622
- for (var _i0 = 0; _i0 < tmpManifest.HashTranslations.length; _i0++) {
2623
- // Each translation is
2624
- //FIXME: ?????????
2625
- }
2626
- }
2627
- }
2628
- }
2629
-
2630
- /**
2631
- * Serialize the Manifest to a string
2632
- *
2633
- * @return {string} - The serialized manifest
2634
- */
2635
- }, {
2636
- key: "serialize",
2637
- value: function serialize() {
2638
- return JSON.stringify(this.getManifest());
2639
- }
2640
-
2641
- /**
2642
- * @return {{ Scope: string, Descriptors: Record<string, ManifestDescriptor>, HashTranslations: Record<string, string> }} - A copy of the manifest state.
2643
- */
2644
- }, {
2645
- key: "getManifest",
2646
- value: function getManifest() {
2647
- return {
2648
- Scope: this.scope,
2649
- Descriptors: JSON.parse(JSON.stringify(this.elementDescriptors)),
2650
- HashTranslations: JSON.parse(JSON.stringify(this.hashTranslations.translationTable))
2651
- };
2652
- }
2653
-
2654
- /**
2655
- * Add a descriptor to the manifest
2656
- *
2657
- * @param {string} pAddress - The address of the element to add the descriptor for.
2658
- * @param {ManifestDescriptor} pDescriptor - The descriptor object to add.
2659
- */
2660
- }, {
2661
- key: "addDescriptor",
2662
- value: function addDescriptor(pAddress, pDescriptor) {
2663
- if (_typeof(pDescriptor) === 'object') {
2664
- // Add the Address into the Descriptor if it doesn't exist:
2665
- if (!('Address' in pDescriptor)) {
2666
- pDescriptor.Address = pAddress;
2667
- }
2668
- if (!(pAddress in this.elementDescriptors)) {
2669
- this.elementAddresses.push(pAddress);
2670
- }
2671
-
2672
- // Add the element descriptor to the schema
2673
- this.elementDescriptors[pAddress] = pDescriptor;
2674
-
2675
- // Always add the address as a hash
2676
- this.elementHashes[pAddress] = pAddress;
2677
- if ('Hash' in pDescriptor) {
2678
- // TODO: Check if this is a good idea or not..
2679
- // Collisions are bound to happen with both representations of the address/hash in here and developers being able to create their own hashes.
2680
- this.elementHashes[pDescriptor.Hash] = pAddress;
2681
- } else {
2682
- pDescriptor.Hash = pAddress;
2683
- }
2684
- return true;
2685
- } else {
2686
- this.logError("(".concat(this.scope, ") Error loading object descriptor for address '").concat(pAddress, "' from manifest object. Expecting an object but property was type ").concat(_typeof(pDescriptor), "."));
2687
- return false;
2688
- }
2689
- }
2690
-
2691
- /**
2692
- * @param {string} pHash - The hash of the address to resolve.
2693
- *
2694
- * @return {ManifestDescriptor} The descriptor for the address
2695
- */
2696
- }, {
2697
- key: "getDescriptorByHash",
2698
- value: function getDescriptorByHash(pHash) {
2699
- return this.getDescriptor(this.resolveHashAddress(pHash));
2700
- }
2701
-
2702
- /**
2703
- * @param {string} pAddress - The address of the element to get the descriptor for.
2704
- *
2705
- * @return {ManifestDescriptor} The descriptor for the address
2706
- */
2707
- }, {
2708
- key: "getDescriptor",
2709
- value: function getDescriptor(pAddress) {
2710
- return this.elementDescriptors[pAddress];
2711
- }
2712
-
2713
- /**
2714
- * execute an action function for each descriptor
2715
- * @param {(d: ManifestDescriptor) => void} fAction - The action function to execute for each descriptor.
2716
- */
2717
- }, {
2718
- key: "eachDescriptor",
2719
- value: function eachDescriptor(fAction) {
2720
- var tmpDescriptorAddresses = Object.keys(this.elementDescriptors);
2721
- for (var i = 0; i < tmpDescriptorAddresses.length; i++) {
2722
- fAction(this.elementDescriptors[tmpDescriptorAddresses[i]]);
2723
- }
2724
- }
2725
-
2726
- /*************************************************************************
2727
- * Beginning of Object Manipulation (read & write) Functions
2728
- */
2729
- // Check if an element exists by its hash
2730
- }, {
2731
- key: "checkAddressExistsByHash",
2732
- value: function checkAddressExistsByHash(pObject, pHash) {
2733
- return this.checkAddressExists(pObject, this.resolveHashAddress(pHash));
2734
- }
2735
-
2736
- // Check if an element exists at an address
2737
- }, {
2738
- key: "checkAddressExists",
2739
- value: function checkAddressExists(pObject, pAddress) {
2740
- return this.objectAddressCheckAddressExists.checkAddressExists(pObject, pAddress);
2741
- }
2742
-
2743
- // Turn a hash into an address, factoring in the translation table.
2744
- }, {
2745
- key: "resolveHashAddress",
2746
- value: function resolveHashAddress(pHash) {
2747
- var tmpAddress = undefined;
2748
- var tmpInElementHashTable = pHash in this.elementHashes;
2749
- var tmpInTranslationTable = pHash in this.hashTranslations.translationTable;
2750
-
2751
- // The most straightforward: the hash exists, no translations.
2752
- if (tmpInElementHashTable && !tmpInTranslationTable) {
2753
- tmpAddress = this.elementHashes[pHash];
2754
- }
2755
- // There is a translation from one hash to another, and, the elementHashes contains the pointer end
2756
- else if (tmpInTranslationTable && this.hashTranslations.translate(pHash) in this.elementHashes) {
2757
- tmpAddress = this.elementHashes[this.hashTranslations.translate(pHash)];
2758
- }
2759
- // Use the level of indirection only in the Translation Table
2760
- else if (tmpInTranslationTable) {
2761
- tmpAddress = this.hashTranslations.translate(pHash);
2762
- }
2763
- // Just treat the hash as an address.
2764
- // TODO: Discuss this ... it is magic but controversial
2765
- else {
2766
- tmpAddress = pHash;
2767
- }
2768
- return tmpAddress;
2769
- }
2770
-
2771
- // Get the value of an element by its hash
2772
- }, {
2773
- key: "getValueByHash",
2774
- value: function getValueByHash(pObject, pHash) {
2775
- var tmpValue = this.getValueAtAddress(pObject, this.resolveHashAddress(pHash));
2776
- if (typeof tmpValue == 'undefined') {
2777
- // Try to get a default if it exists
2778
- tmpValue = this.getDefaultValue(this.getDescriptorByHash(pHash));
2779
- }
2780
- return tmpValue;
2781
- }
2782
- }, {
2783
- key: "lintAddress",
2784
- value: function lintAddress(pAddress) {
2785
- var tmpLintedAddress = pAddress.trim();
2786
- // Check for a single . (but not a ..) at the end of the address and remove it.
2787
- if (tmpLintedAddress.endsWith('..')) {
2788
- tmpLintedAddress = tmpLintedAddress.slice(0, -1);
2789
- } else if (tmpLintedAddress.endsWith('.')) {
2790
- tmpLintedAddress = tmpLintedAddress.slice(0, -1);
2791
- }
2792
- return tmpLintedAddress;
2793
- }
2794
-
2795
- // Get the value of an element at an address
2796
- }, {
2797
- key: "getValueAtAddress",
2798
- value: function getValueAtAddress(pObject, pAddress) {
2799
- var tmpLintedAddress = this.lintAddress(pAddress);
2800
- if (tmpLintedAddress == '') {
2801
- this.logError("(".concat(this.scope, ") Error getting value at address; address is an empty string."), pObject);
2802
- return undefined;
2803
- }
2804
- var tmpValue = this.objectAddressGetValue.getValueAtAddress(pObject, tmpLintedAddress);
2805
- if (typeof tmpValue == 'undefined') {
2806
- // Try to get a default if it exists
2807
- tmpValue = this.getDefaultValue(this.getDescriptor(tmpLintedAddress));
2808
- }
2809
- return tmpValue;
2810
- }
2811
-
2812
- // Set the value of an element by its hash
2813
- }, {
2814
- key: "setValueByHash",
2815
- value: function setValueByHash(pObject, pHash, pValue) {
2816
- return this.setValueAtAddress(pObject, this.resolveHashAddress(pHash), pValue);
2817
- }
2818
-
2819
- // Set the value of an element at an address
2820
- }, {
2821
- key: "setValueAtAddress",
2822
- value: function setValueAtAddress(pObject, pAddress, pValue) {
2823
- var tmpLintedAddress = this.lintAddress(pAddress);
2824
- return this.objectAddressSetValue.setValueAtAddress(pObject, tmpLintedAddress, pValue);
2825
- }
2826
-
2827
- // Delete the value of an element by its hash
2828
- }, {
2829
- key: "deleteValueByHash",
2830
- value: function deleteValueByHash(pObject, pHash, pValue) {
2831
- return this.deleteValueAtAddress(pObject, this.resolveHashAddress(pHash), pValue);
2832
- }
2833
-
2834
- // Delete the value of an element at an address
2835
- }, {
2836
- key: "deleteValueAtAddress",
2837
- value: function deleteValueAtAddress(pObject, pAddress, pValue) {
2838
- var tmpLintedAddress = this.lintAddress(pAddress);
2839
- return this.objectAddressDeleteValue.deleteValueAtAddress(pObject, tmpLintedAddress, pValue);
2840
- }
2841
-
2842
- // Validate the consistency of an object against the schema
2843
- }, {
2844
- key: "validate",
2845
- value: function validate(pObject) {
2846
- var tmpValidationData = {
2847
- Error: null,
2848
- Errors: [],
2849
- MissingElements: []
2850
- };
2851
- if (_typeof(pObject) !== 'object') {
2852
- tmpValidationData.Error = true;
2853
- tmpValidationData.Errors.push("Expected passed in object to be type object but was passed in ".concat(_typeof(pObject)));
2854
- }
2855
- var addValidationError = function addValidationError(pAddress, pErrorMessage) {
2856
- tmpValidationData.Error = true;
2857
- tmpValidationData.Errors.push("Element at address \"".concat(pAddress, "\" ").concat(pErrorMessage, "."));
2858
- };
2859
-
2860
- // Now enumerate through the values and check for anomalies based on the schema
2861
- for (var i = 0; i < this.elementAddresses.length; i++) {
2862
- var tmpDescriptor = this.getDescriptor(this.elementAddresses[i]);
2863
- var tmpValueExists = this.checkAddressExists(pObject, tmpDescriptor.Address);
2864
- var tmpValue = this.getValueAtAddress(pObject, tmpDescriptor.Address);
2865
- if (typeof tmpValue == 'undefined' || !tmpValueExists) {
2866
- // This will technically mean that `Object.Some.Value = undefined` will end up showing as "missing"
2867
- // TODO: Do we want to do a different message based on if the property exists but is undefined?
2868
- tmpValidationData.MissingElements.push(tmpDescriptor.Address);
2869
- if (tmpDescriptor.Required || this.options.strict) {
2870
- addValidationError(tmpDescriptor.Address, 'is flagged REQUIRED but is not set in the object');
2871
- }
2872
- }
2873
-
2874
- // Now see if there is a data type specified for this element
2875
- if (tmpDescriptor.DataType) {
2876
- var tmpElementType = _typeof(tmpValue);
2877
- switch (tmpDescriptor.DataType.toString().trim().toLowerCase()) {
2878
- case 'string':
2879
- if (tmpElementType != 'string') {
2880
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " but is of the type ").concat(tmpElementType));
2881
- }
2882
- break;
2883
- case "precisenumber":
2884
- if (tmpElementType != 'string') {
2885
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " but is of the type ").concat(tmpElementType));
2886
- } else if (!this.numberRegex.test(tmpValue)) {
2887
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " but is not a valid number"));
2888
- }
2889
- break;
2890
- case 'number':
2891
- if (tmpElementType != 'number') {
2892
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " but is of the type ").concat(tmpElementType));
2893
- }
2894
- break;
2895
- case 'integer':
2896
- if (tmpElementType != 'number') {
2897
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " but is of the type ").concat(tmpElementType));
2898
- } else {
2899
- var tmpValueString = tmpValue.toString();
2900
- if (tmpValueString.indexOf('.') > -1) {
2901
- // TODO: Is this an error?
2902
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " but has a decimal point in the number."));
2903
- }
2904
- }
2905
- break;
2906
- case 'float':
2907
- if (tmpElementType != 'number') {
2908
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " but is of the type ").concat(tmpElementType));
2909
- }
2910
- break;
2911
- case 'datetime':
2912
- var tmpValueDate = new Date(tmpValue);
2913
- if (tmpValueDate.toString() == 'Invalid Date') {
2914
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " but is not parsable as a Date by Javascript"));
2915
- }
2916
- default:
2917
- // Check if this is a string, in the default case
2918
- // Note this is only when a DataType is specified and it is an unrecognized data type.
2919
- if (tmpElementType != 'string') {
2920
- addValidationError(tmpDescriptor.Address, "has a DataType ".concat(tmpDescriptor.DataType, " (which auto-converted to String because it was unrecognized) but is of the type ").concat(tmpElementType));
2921
- }
2922
- break;
2923
- }
2924
- }
2925
- }
2926
- return tmpValidationData;
2927
- }
2928
-
2929
- /**
2930
- * Returns a default value, or, the default value for the data type (which is overridable with configuration)
2931
- *
2932
- * @param {ManifestDescriptor} pDescriptor - The descriptor definition.
2933
- */
2934
- }, {
2935
- key: "getDefaultValue",
2936
- value: function getDefaultValue(pDescriptor) {
2937
- if (_typeof(pDescriptor) != 'object') {
2938
- return undefined;
2939
- }
2940
- if ('Default' in pDescriptor) {
2941
- return pDescriptor.Default;
2942
- } else {
2943
- // Default to a null if it doesn't have a type specified.
2944
- // This will ensure a placeholder is created but isn't misinterpreted.
2945
- var tmpDataType = 'DataType' in pDescriptor ? pDescriptor.DataType : 'String';
2946
- if (tmpDataType in this.options.defaultValues) {
2947
- return this.options.defaultValues[tmpDataType];
2948
- } else {
2949
- // give up and return null
2950
- return null;
2951
- }
2952
- }
2953
- }
2954
-
2955
- // Enumerate through the schema and populate default values if they don't exist.
2956
- }, {
2957
- key: "populateDefaults",
2958
- value: function populateDefaults(pObject, pOverwriteProperties) {
2959
- return this.populateObject(pObject, pOverwriteProperties,
2960
- // This just sets up a simple filter to see if there is a default set.
2961
- function (pDescriptor) {
2962
- return 'Default' in pDescriptor;
2963
- });
2964
- }
2965
-
2966
- // Forcefully populate all values even if they don't have defaults.
2967
- // Based on type, this can do unexpected things.
2968
- }, {
2969
- key: "populateObject",
2970
- value: function populateObject(pObject, pOverwriteProperties, fFilter) {
2971
- var _this4 = this;
2972
- // Automatically create an object if one isn't passed in.
2973
- var tmpObject = _typeof(pObject) === 'object' ? pObject : {};
2974
- // Default to *NOT OVERWRITING* properties
2975
- var tmpOverwriteProperties = typeof pOverwriteProperties == 'undefined' ? false : pOverwriteProperties;
2976
- // This is a filter function, which is passed the schema and allows complex filtering of population
2977
- // The default filter function just returns true, populating everything.
2978
- var tmpFilterFunction = typeof fFilter == 'function' ? fFilter : function (pDescriptor) {
2979
- return true;
2980
- };
2981
- this.elementAddresses.forEach(function (pAddress) {
2982
- var tmpDescriptor = _this4.getDescriptor(pAddress);
2983
- // Check the filter function to see if this is an address we want to set the value for.
2984
- if (tmpFilterFunction(tmpDescriptor)) {
2985
- // If we are overwriting properties OR the property does not exist
2986
- if (tmpOverwriteProperties || !_this4.checkAddressExists(tmpObject, pAddress)) {
2987
- _this4.setValueAtAddress(tmpObject, pAddress, _this4.getDefaultValue(tmpDescriptor));
2988
- }
2989
- }
2990
- });
2991
- return tmpObject;
2992
- }
2993
- }]);
2994
- }(libFableServiceProviderBase);
2995
- ;
2996
- module.exports = Manyfest;
2997
- }, {
2998
- "./Manyfest-HashTranslation.js": 4,
2999
- "./Manyfest-LogToConsole.js": 5,
3000
- "./Manyfest-ObjectAddress-CheckAddressExists.js": 6,
3001
- "./Manyfest-ObjectAddress-DeleteValue.js": 7,
3002
- "./Manyfest-ObjectAddress-GetValue.js": 8,
3003
- "./Manyfest-ObjectAddress-SetValue.js": 10,
3004
- "./Manyfest-ObjectAddressGeneration.js": 11,
3005
- "./Manyfest-SchemaManipulation.js": 13,
3006
- "fable-serviceproviderbase": 2
3007
- }]
3008
- }, {}, [14])(14);
3009
- });
3010
- //# sourceMappingURL=manyfest.compatible.js.map