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.
- package/CONTRIBUTING.md +50 -0
- package/README.md +97 -254
- package/docs/.nojekyll +0 -0
- package/docs/README.md +108 -0
- package/docs/_sidebar.md +17 -0
- package/docs/address-notation.md +244 -0
- package/docs/cover.md +11 -0
- package/docs/css/docuserve.css +73 -0
- package/docs/hash-translation.md +202 -0
- package/docs/index.html +39 -0
- package/docs/quickstart.md +203 -0
- package/docs/reading.md +339 -0
- package/docs/retold-catalog.json +105 -0
- package/docs/retold-keyword-index.json +19 -0
- package/docs/schema-manipulation.md +186 -0
- package/docs/schema.md +319 -0
- package/docs/validating.md +344 -0
- package/docs/writing.md +300 -0
- package/package.json +3 -3
- package/source/Manyfest-ObjectAddress-CheckAddressExists.js +3 -4
- package/source/Manyfest-ObjectAddress-DeleteValue.js +7 -5
- package/source/Manyfest-ObjectAddress-GetValue.js +2 -6
- package/source/Manyfest-ObjectAddress-Parser.js +3 -3
- package/source/Manyfest-ObjectAddress-SetValue.js +7 -4
- package/source/Manyfest-ParseConditionals.js +0 -13
- package/source/Manyfest.js +28 -15
- package/dist/manyfest.compatible.js +0 -3010
- package/dist/manyfest.compatible.js.map +0 -1
- package/dist/manyfest.compatible.min.js +0 -2
- package/dist/manyfest.compatible.min.js.map +0 -1
- package/dist/manyfest.js +0 -2894
- package/dist/manyfest.js.map +0 -1
- package/dist/manyfest.min.js +0 -2
- package/dist/manyfest.min.js.map +0 -1
|
@@ -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
|