manyfest 1.0.2 → 1.0.4
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/.config/configstore/update-notifier-npm.json +1 -1
- package/README.md +35 -11
- package/package.json +3 -2
- package/source/Manyfest-HashTranslation.js +118 -0
- package/source/Manyfest-LogToConsole.js +1 -1
- package/source/Manyfest-ObjectAddressResolver.js +585 -0
- package/source/Manyfest-SchemaManipulation.js +112 -0
- package/source/Manyfest.js +195 -258
- package/test/Manyfest_Object_CheckExistence_tests.js +70 -0
- package/test/Manyfest_Object_HashTranslation_tests.js +166 -0
- package/test/Manyfest_Object_Populate_tests.js +140 -0
- package/test/{Manyfest_ObjectAccess_tests.js → Manyfest_Object_Read_tests.js} +74 -52
- package/test/Manyfest_Object_SchemaManipulation_tests.js +93 -0
- package/test/Manyfest_Object_Validate_tests.js +82 -0
- package/test/Manyfest_Object_Write_tests.js +161 -0
- package/test/Manyfest_tests.js +50 -1
- package/test/Manyfest_AdvancedObjectAccess_tests.js +0 -80
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ let animalManyfest = new libManyfest(
|
|
|
46
46
|
"Scope": "Animal",
|
|
47
47
|
"Descriptors":
|
|
48
48
|
{
|
|
49
|
-
"IDAnimal": { "Name":"Database ID", "Description":"The unique integer-based database identifier for an Animal record.", "DataType":"Integer" },
|
|
49
|
+
"IDAnimal": { "Name":"Database ID", "Description":"The unique integer-based database identifier for an Animal record.", "DataType":"Integer", "Default":0 },
|
|
50
50
|
"Name": { "Description":"The animal's colloquial species name (e.g. Rabbit, Dog, Bear, Mongoose)." },
|
|
51
51
|
"Type": { "Description":"Whether or not the animal is wild, domesticated, agricultural, in a research lab or a part of a zoo.." }
|
|
52
52
|
}
|
|
@@ -70,16 +70,19 @@ Error does not mean the software throws an exception. It comes back as well-for
|
|
|
70
70
|
Below is a lexicon of terms used throughout this documentation. If you see anything missing, want more elaboration or just dislike a particular term, please file an issue in github!
|
|
71
71
|
|
|
72
72
|
| Term | Description |
|
|
73
|
-
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
73
|
+
| ---- | ----------- |
|
|
74
|
+
Scope | The scope of this representation; generally the clustered or parent record name (e.g. Animal, User, Transaction, etc.) -- does not have functional purpose; only for information and logging.
|
|
75
|
+
Schema | The stateful representation of an object's structural definition.
|
|
76
|
+
Element | A defined element of data in an object.
|
|
77
|
+
Address | The address where that data lies in the object.
|
|
78
|
+
Hash | A unique within this scope string-based key for this element. Used for easy access of data.
|
|
79
|
+
Descriptor | A description of an element including data such as Name, NameShort, Hash, Description, and other important properties.
|
|
80
|
+
Name | The name of the element. Meant to be the most succinct human readable name possible.
|
|
81
|
+
NameShort | A shorter name for the element. Meant to be useful enough to identify the property in log lines, tabular views, graphs and anywhere where we don't always want to see the full name.
|
|
82
|
+
Description | A description for the element. Very useful when consuming other APIs with their own terse naming standards (or no naming standards)!
|
|
83
|
+
Required | Set to true if this element is required.
|
|
84
|
+
|
|
85
|
+
Okay so these are a lot of crazy words. The important two are *Address* and *Hash*. Every element in a schema must have an address. Having a hash just multiplies the usefulness of these addresses.
|
|
83
86
|
|
|
84
87
|
## A More Advanced Schema Example
|
|
85
88
|
|
|
@@ -108,6 +111,7 @@ let animalManyfest = new libManyfest(
|
|
|
108
111
|
"Name":"Comfortable Environmental Temperature",
|
|
109
112
|
"NameShort":"Comf Env Temp",
|
|
110
113
|
"Hash":"ComfET",
|
|
114
|
+
"DataType":"Float",
|
|
111
115
|
"Description":"The most comfortable temperature for this animal to survive in."
|
|
112
116
|
}
|
|
113
117
|
}
|
|
@@ -118,6 +122,22 @@ Notice in this example, the addresses are more complex. They have a dot syntax.
|
|
|
118
122
|
|
|
119
123
|
To aid in this discovery, reference and such, we've given it a NameShort (for use in things like tabular views and graphs/charts), a longer Name and a Hash (to enable easy reading and writing using the object element read/write functions described later in this documentation).
|
|
120
124
|
|
|
125
|
+
### Data Types
|
|
126
|
+
|
|
127
|
+
| Type | Description |
|
|
128
|
+
| ---- | ----------- |
|
|
129
|
+
String | A pretty basic string
|
|
130
|
+
Integer | An integer number
|
|
131
|
+
Float | A floating point number; does not require a decimal point
|
|
132
|
+
Number | A number of any type
|
|
133
|
+
Boolean | A boolean value represented by the JSON true or false
|
|
134
|
+
Binary | A boolean value represented as 1 or 0
|
|
135
|
+
YesNo | A boolean value represented as Y or N
|
|
136
|
+
DateTime | A javascript date
|
|
137
|
+
Array | A plain old javascript array
|
|
138
|
+
Object | A plain old javascript object
|
|
139
|
+
Null | A null value
|
|
140
|
+
|
|
121
141
|
## Reading and Writing Element Properties
|
|
122
142
|
|
|
123
143
|
Lastly, when working with objects, Manyfest provides a set of functions to read and write from/to these element addresses. This can be useful for consistently accessing objects across boundaries as well as filling out element defaults without requiring a crazy amount of boilerplate code.
|
|
@@ -187,6 +207,10 @@ console.log(animalManyfest.getValueByHash(favAnimal,'ComfET'));
|
|
|
187
207
|
|
|
188
208
|
For any elements that haven't defined a Hash, the Address is used. This allows code to gracefully fall back.
|
|
189
209
|
|
|
210
|
+
## Hash Translation Tables
|
|
211
|
+
|
|
212
|
+
Sometimes we want to reuse the structure of a schema, but look up values by hash using translations.
|
|
213
|
+
|
|
190
214
|
## Programmatically Defining a Schema
|
|
191
215
|
|
|
192
216
|
Sometimes we don't have schemas, and want to define object element structure on the fly. This can be done programmatically. As a refresher, here is how we loaded our simplest schema manifest above:
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "manyfest",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "JSON Object Manifest for Data Description and Parsing",
|
|
5
5
|
"main": "source/Manyfest.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"docker-dev-build-image": "docker build ./ -f Dockerfile_LUXURYCode -t retold/manyfest:local",
|
|
8
8
|
"docker-dev-run": "docker run -it -d --name manyfest -p 12340:8080 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/manyfest\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" retold/manyfest:local",
|
|
9
9
|
"test": "./node_modules/mocha/bin/_mocha -u tdd -R spec",
|
|
10
|
-
"tests": "./node_modules/mocha/bin/_mocha -u tdd -R spec --grep"
|
|
10
|
+
"tests": "./node_modules/mocha/bin/_mocha -u tdd -R spec --grep",
|
|
11
|
+
"coverage": "nyc npm run test && nyc report --reporter=lcov"
|
|
11
12
|
},
|
|
12
13
|
"repository": {
|
|
13
14
|
"type": "git",
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license MIT
|
|
3
|
+
* @author <steven@velozo.com>
|
|
4
|
+
*/
|
|
5
|
+
let libSimpleLog = require('./Manyfest-LogToConsole.js');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Hash Translation
|
|
9
|
+
*
|
|
10
|
+
* This is a very simple translation table for hashes, which allows the same schema to resolve
|
|
11
|
+
* differently based on a loaded translation table.
|
|
12
|
+
*
|
|
13
|
+
* This is to prevent the requirement for mutating schemas over and over again when we want to
|
|
14
|
+
* reuse the structure but look up data elements by different addresses.
|
|
15
|
+
*
|
|
16
|
+
* One side-effect of this is that a translation table can "override" the built-in hashes, since
|
|
17
|
+
* this is always used to resolve hashes before any of the functionCallByHash(pHash, ...) perform
|
|
18
|
+
* their lookups by hash.
|
|
19
|
+
*
|
|
20
|
+
* @class ManyfestHashTranslation
|
|
21
|
+
*/
|
|
22
|
+
class ManyfestHashTranslation
|
|
23
|
+
{
|
|
24
|
+
constructor(pInfoLog, pErrorLog)
|
|
25
|
+
{
|
|
26
|
+
// Wire in logging
|
|
27
|
+
this.logInfo = (typeof(pInfoLog) === 'function') ? pInfoLog : libSimpleLog;
|
|
28
|
+
this.logError = (typeof(pErrorLog) === 'function') ? pErrorLog : libSimpleLog;
|
|
29
|
+
|
|
30
|
+
this.translationTable = {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
translationCount()
|
|
34
|
+
{
|
|
35
|
+
return Object.keys(this.translationTable).length;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
addTranslation(pTranslation)
|
|
39
|
+
{
|
|
40
|
+
// This adds a translation in the form of:
|
|
41
|
+
// { "SourceHash": "DestinationHash", "SecondSourceHash":"SecondDestinationHash" }
|
|
42
|
+
if (typeof(pTranslation) != 'object')
|
|
43
|
+
{
|
|
44
|
+
this.logError(`Hash translation addTranslation expected a translation be type object but was passed in ${typeof(pTranslation)}`);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let tmpTranslationSources = Object.keys(pTranslation)
|
|
49
|
+
|
|
50
|
+
tmpTranslationSources.forEach(
|
|
51
|
+
(pTranslationSource) =>
|
|
52
|
+
{
|
|
53
|
+
if (typeof(pTranslation[pTranslationSource]) != 'string')
|
|
54
|
+
{
|
|
55
|
+
this.logError(`Hash translation addTranslation expected a translation destination hash for [${pTranslationSource}] to be a string but the referrant was a ${typeof(pTranslation[pTranslationSource])}`);
|
|
56
|
+
}
|
|
57
|
+
else
|
|
58
|
+
{
|
|
59
|
+
this.translationTable[pTranslationSource] = pTranslation[pTranslationSource];
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
removeTranslationHash(pTranslationHash)
|
|
65
|
+
{
|
|
66
|
+
if (this.translationTable.hasOwnProperty(pTranslationHash))
|
|
67
|
+
{
|
|
68
|
+
delete this.translationTable[pTranslationHash];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// This removes translations.
|
|
73
|
+
// If passed a string, just removes the single one.
|
|
74
|
+
// If passed an object, it does all the source keys.
|
|
75
|
+
removeTranslation(pTranslation)
|
|
76
|
+
{
|
|
77
|
+
if (typeof(pTranslation) == 'string')
|
|
78
|
+
{
|
|
79
|
+
this.removeTranslationHash(pTranslation);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
else if (typeof(pTranslation) == 'object')
|
|
83
|
+
{
|
|
84
|
+
let tmpTranslationSources = Object.keys(pTranslation)
|
|
85
|
+
|
|
86
|
+
tmpTranslationSources.forEach(
|
|
87
|
+
(pTranslationSource) =>
|
|
88
|
+
{
|
|
89
|
+
this.removeTranslation(pTranslationSource);
|
|
90
|
+
});
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
else
|
|
94
|
+
{
|
|
95
|
+
this.logError(`Hash translation removeTranslation expected either a string or an object but the passed-in translation was type ${typeof(pTranslation)}`);
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
clearTranslations()
|
|
101
|
+
{
|
|
102
|
+
this.translationTable = {};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
translate(pTranslation)
|
|
106
|
+
{
|
|
107
|
+
if (this.translationTable.hasOwnProperty(pTranslation))
|
|
108
|
+
{
|
|
109
|
+
return this.translationTable[pTranslation];
|
|
110
|
+
}
|
|
111
|
+
else
|
|
112
|
+
{
|
|
113
|
+
return pTranslation;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = ManyfestHashTranslation;
|
|
@@ -13,7 +13,7 @@ const logToConsole = (pLogLine, pLogObject) =>
|
|
|
13
13
|
|
|
14
14
|
console.log(`[Manyfest] ${tmpLogLine}`);
|
|
15
15
|
|
|
16
|
-
if (pLogObject) console.log(JSON.stringify(
|
|
16
|
+
if (pLogObject) console.log(JSON.stringify(pLogObject));
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
module.exports = logToConsole;
|