Skip to content

Commit b4d1458

Browse files
committed
eslint, code style changes
1 parent 23810c8 commit b4d1458

9 files changed

Lines changed: 185 additions & 49 deletions

.eslintrc.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"rules": {
3+
"indent": [ 2, 2, {"SwitchCase": 1} ],
4+
"quotes": [ 2, "single", "avoid-escape" ],
5+
"linebreak-style": [ 2, "unix" ],
6+
"semi": [ 2, "always" ],
7+
"valid-jsdoc": [ 2, { "requireReturn": false } ],
8+
"no-invalid-this": 2,
9+
"no-unused-vars": [ 2, { "args": "none" } ],
10+
"no-console": [ 2, { "allow": ["warn", "error"] } ],
11+
"block-scoped-var": 2,
12+
"complexity": [2, 13],
13+
"curly": [2, "multi-or-nest", "consistent"],
14+
"dot-location": [2, "property"],
15+
"dot-notation": 2,
16+
"no-else-return": 2,
17+
"no-eq-null": 2,
18+
"no-fallthrough": 2,
19+
"no-return-assign": 2,
20+
"strict": [2, "global"],
21+
"no-shadow": 1,
22+
"no-use-before-define": [2, "nofunc"],
23+
"callback-return": 2
24+
},
25+
"env": {
26+
"node": true
27+
},
28+
"extends": "eslint:recommended"
29+
}

lib/evaluation_keywords.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ module.exports = {
1111
};
1212

1313

14+
/**
15+
* Validation function for custom validation keyword resolvePendingRefs.
16+
* It marks the current path as evaluated and resolves pending references.
17+
* @this Evaluation
18+
* @param {Object} data Current script, not used
19+
* @param {String} dataPath Current data path (JSON pointer)
20+
* @return {Boolean} validation result
21+
*/
1422
function resolvePendingRefs(data, dataPath) {
1523
dataPath = dataPath.replace(/^\/script/, '');
1624
this.evaluatedRefs[dataPath] = true;

lib/generate_schema.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module.exports = function generateSchema(schemaName, instructions) {
1010
var template = getSchemaTemplate(schemaName);
1111
var schemaStr = template({ instructions: instructions });
1212
return JSON.parse(schemaStr);
13-
}
13+
};
1414

1515

1616
function getSchemaTemplate(schemaName) {

lib/get_jst.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var definitions = getFile('definitions.def');
88
module.exports = function getJst(fileName) {
99
var jst = getFile(fileName + '.jst');
1010
return doT.compile(jst, { definitions: definitions });
11-
}
11+
};
1212

1313

1414
function getFile(fileNameExt) {

lib/instruction_keywords.js

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use strict';
2+
/*global Promise*/
23

34
var pointer = require('json-pointer');
45
var util = require('./util');
@@ -13,6 +14,12 @@ module.exports = {
1314
};
1415

1516

17+
/**
18+
* execute external executor/method
19+
* @this Evaluation
20+
* @param {Object} params instruction keywords ($exec, $method, $args)
21+
* @return {Promise|Any} result
22+
*/
1623
function eval$exec(params) {
1724
var $exec = params.$exec;
1825
var $method = params.$method;
@@ -22,20 +29,26 @@ function eval$exec(params) {
2229
if (typeof executor[$method] != 'function')
2330
throw new Error('unknown method ' + $method + ' of executor ' + $exec);
2431
return executor[$method](params.$args);
25-
} else {
26-
if (typeof executor != 'function')
27-
throw new Error('executor ' + $exec + ' is not a function');
28-
return executor(params.$args);
2932
}
33+
if (typeof executor != 'function')
34+
throw new Error('executor ' + $exec + ' is not a function');
35+
return executor(params.$args);
3036
}
3137

3238

39+
/**
40+
* resolve reference to the current script
41+
* @this Evaluation
42+
* @param {Object} params instruction keywords ($ref)
43+
* @param {String} dataPath current path (JSON pointer)
44+
* @return {Promise|Any} reolved reference
45+
*/
3346
function eval$ref(params, dataPath) {
3447
dataPath = dataPath.replace(this.refPrefixRegexp, '');
3548
var $ref = params.$ref;
3649
if ($ref.indexOf('0/') == 0) throw new Error('Cannot reference the same $ref instruction or child');
3750

38-
var pathParsed = pointer.parse(dataPath)
51+
var pathParsed = pointer.parse(dataPath);
3952
var absPointerParsed = util.toAbsolutePointer($ref, pathParsed);
4053
// N# pointer returns property/index
4154
if (typeof absPointerParsed == 'string') return absPointerParsed;
@@ -51,18 +64,17 @@ function eval$ref(params, dataPath) {
5164
var rootPointer = pointer.compile(rootPointerParsed);
5265
var pointerFromRoot = pointer.compile(absPointerParsed.slice(i+1));
5366

54-
if (this.evaluatedRefs[rootPointer]) {
67+
if (this.evaluatedRefs[rootPointer])
5568
return getRefValue(this.script, rootPointer, pointerFromRoot);
56-
} else {
57-
var self = this;
58-
var pendingRef = self.pendingRefs[rootPointer]
59-
= self.pendingRefs[rootPointer] || new PendingRef(rootPointer);
60-
return new Promise(function (resolve, reject) {
61-
pendingRef.addCallback(function () {
62-
resolve(getRefValue(self.script, rootPointer, pointerFromRoot));
63-
});
69+
70+
var self = this;
71+
var pendingRef = self.pendingRefs[rootPointer]
72+
= self.pendingRefs[rootPointer] || new PendingRef(rootPointer);
73+
return new Promise(function (resolve, reject) {
74+
pendingRef.addCallback(function () {
75+
resolve(getRefValue(self.script, rootPointer, pointerFromRoot));
6476
});
65-
}
77+
});
6678
}
6779

6880

@@ -72,19 +84,31 @@ function getRefValue(obj, rootPointer, pointerFromRoot) {
7284
return root.then(function(rootValue) {
7385
return pointer.get(rootValue, pointerFromRoot);
7486
});
75-
} else {
76-
return pointer.get(root, pointerFromRoot);
7787
}
88+
89+
return pointer.get(root, pointerFromRoot);
7890
}
7991

8092

93+
/**
94+
* resolve reference to the data object
95+
* @this Evaluation
96+
* @param {Object} params instruction keywords ($data)
97+
* @return {Any} data value
98+
*/
8199
function eval$data(params) {
82100
var $data = params.$data;
83101
if ($data[0] == '#') $data = decodeURIComponent($data.slice(1));
84102
return pointer.get(this.data, $data);
85103
}
86104

87105

106+
/**
107+
* conditional evaluation
108+
* @this Evaluation
109+
* @param {Object} params instruction keywords ($if, $then, $else)
110+
* @return {Script|Any} script to be evaluated
111+
*/
88112
function eval$if(params) {
89113
var script = params.$if
90114
? params.$then
@@ -95,6 +119,12 @@ function eval$if(params) {
95119
}
96120

97121

122+
/**
123+
* delayed evaluation
124+
* @this Evaluation
125+
* @param {Object} params instruction keywords ($delay, $wait)
126+
* @return {Script|Promise} script to be evaluated or asynchronous value
127+
*/
98128
function eval$delay(params) {
99129
var value = new Promise(function (resolve, reject) {
100130
setTimeout(function() {
@@ -108,5 +138,5 @@ function eval$delay(params) {
108138

109139

110140
function isScript(value) {
111-
return value && typeof value == 'object'
141+
return value && typeof value == 'object';
112142
}

lib/jsonscript.js

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use strict';
2+
/*global Promise*/
23

34
var util = require('./util');
45
var Ajv = require('ajv');
@@ -32,13 +33,26 @@ JSONScript.prototype.addInstruction = addInstruction;
3233
JSONScript.prototype.addExecutor = addExecutor;
3334

3435

36+
/**
37+
* validates script
38+
* @this JSONScript
39+
* @param {Any} script script can be any allowed value
40+
* @return {Boolean} validation result
41+
*/
3542
function validateScript(script) {
3643
var valid = this._validate(script);
3744
validateScript.errors = this._validate.errors;
3845
return valid;
3946
}
4047

4148

49+
/**
50+
* evaluates script
51+
* @this JSONScript
52+
* @param {Any} script any valid script
53+
* @param {Any} data data instance that can be referenced from the script
54+
* @return {Any} evaluation result
55+
*/
4256
function evaluateScript(script, data) {
4357
var wrapped = { script: script };
4458
var valid;
@@ -54,27 +68,43 @@ function evaluateScript(script, data) {
5468
}
5569

5670

57-
function addInstruction(definition, keywordFunc, regenerateSchemas) {
71+
/**
72+
* add JSONScript instruction to the interpreter
73+
* @this JSONScript
74+
* @param {Object} definition instruction definition, should be valid according to the schema http://json-script.com/schema/instruction.json#
75+
* @param {Function} keywordFunc function to implement the instruction, accepts instruction object and dataPath as parameter, should return sync/async value or Script instance
76+
* @param {Boolean} _regenerateSchemas pass false to prevent regenerating the schemas, can be used when multiple instructions are added
77+
*/
78+
function addInstruction(definition, keywordFunc, _regenerateSchemas) {
5879
var valid = this._validateInstruction(definition);
5980
if (!valid) throw new Ajv.ValidationError(this._validateInstruction.errors);
6081
// TODO check instruction is unique
6182
this._instructions.push(definition);
6283
var keyword = definition.evaluate.validatorKeyword;
6384
this._evalKeywords[keyword] = keywordFunc;
6485
addAjvKeyword.call(this, keyword, 'object', true);
65-
if (regenerateSchemas !== false) generateSchemas();
86+
if (_regenerateSchemas !== false) generateSchemas();
6687
}
6788

6889

90+
/**
91+
* add external executor to JSONScript interpreter
92+
* @this JSONScript
93+
* @param {String} name executor name to use in $exec keyword
94+
* @param {Object|Function} executor executor object or function
95+
*/
6996
function addExecutor(name, executor) {
7097
// TODO check duplicates, show warnings
7198
// ? TODO whitelist methods?
7299
this._executors[name] = executor;
73100
}
74101

75102

103+
/**
104+
* private function to add Ajv keywords that are used in the schema that evaluates scripts
105+
* @this JSONScript
106+
*/
76107
function addAjvKeywords() {
77-
var self = this;
78108
addAjvKeyword.call(this, 'validateAsync');
79109
addAjvKeyword.call(this, 'itemsSerial', 'array');
80110
this._evalKeywords.objectToAsync = util.objectToPromise;
@@ -86,6 +116,13 @@ function addAjvKeywords() {
86116
}
87117

88118

119+
/**
120+
* private function to add Ajv keyword that is used for instruction/script evaluation
121+
* @this JSONScript
122+
* @param {String} keyword custom validation keyword
123+
* @param {String|Array<String>} types type(s) that the keyword applies for
124+
* @param {Boolean} inlineInstruction true to use evaluationKeywords.inlineInstruction as keyword function, otherwise evaluationKeywords[keyword] is used
125+
*/
89126
function addAjvKeyword(keyword, types, inlineInstruction) {
90127
var inlineFunc = evaluationKeywords[inlineInstruction ? 'inlineInstruction' : keyword];
91128
this.ajv.addKeyword(keyword, {
@@ -97,6 +134,10 @@ function addAjvKeyword(keyword, types, inlineInstruction) {
97134
}
98135

99136

137+
/**
138+
* private function to add all standard JSONScript instructions to the interpreter
139+
* @this JSONScript
140+
*/
100141
function addCoreInstructions() {
101142
this._validateInstruction = this.ajv.compile(require('jsonscript/schema/instruction.json'));
102143
instructions.forEach(function (inst) {
@@ -106,6 +147,10 @@ function addCoreInstructions() {
106147
}
107148

108149

150+
/**
151+
* private function to regenerate validation and evaluation schemas, called when an instruction is added
152+
* @this JSONScript
153+
*/
109154
function generateSchemas() {
110155
this.ajv.addMetaSchema(_generate.call(this, 'evaluate_metaschema'));
111156
this._validate = this.ajv.compile(_generate.call(this, 'schema'));
@@ -114,13 +159,23 @@ function generateSchemas() {
114159
}
115160

116161

162+
/**
163+
* private function to generate one of schemas used by the interpreter
164+
* @this JSONScript
165+
* @param {String} schemaName schema name
166+
* @return {Object} generated schema object
167+
*/
117168
function _generate(schemaName) {
118169
var schema = generateSchema(schemaName, this._instructions);
119170
this.ajv.removeSchema(schema.id);
120171
return schema;
121172
}
122173

123174

175+
/**
176+
* Constructor for Script object. Instructions can return the instance (as "new this.js.Script(script)") if the returned value is a script that should be evaluated
177+
* @param {Any} script any valid script
178+
*/
124179
function Script(script) {
125180
this.script = script;
126181
}

lib/pending.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
module.exports = PendingRef;
44

55

6-
function PendingRef(rootPointer) {
7-
this.rootPointer = rootPointer;
6+
/**
7+
* Class to store unresolved reference and callbacks
8+
* @param {String} jsonPointer JSON-pointer of the reference
9+
*/
10+
function PendingRef(jsonPointer) {
11+
this.jsonPointer = jsonPointer;
812
this.callbacks = [];
913
}
1014

@@ -13,12 +17,21 @@ PendingRef.prototype.addCallback = addCallback;
1317
PendingRef.prototype.resolve = resolve;
1418

1519

20+
/**
21+
* add callback to pending reference
22+
* @this PendingRef
23+
* @param {Function} callback it will be called when ther eference is resolved
24+
*/
1625
function addCallback(callback) {
1726
this.callbacks.push(callback);
1827
}
1928

2029

21-
function resolve(value) {
30+
/**
31+
* call all callbacks when reference is resolved
32+
* @this PendingRef
33+
*/
34+
function resolve() {
2235
for (var i=0; i<this.callbacks.length; i++)
2336
this.callbacks[i]();
2437
}

0 commit comments

Comments
 (0)