mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Introduced a pattern based url auto complete backend
This commit is contained in:
parent
8a0136d8d2
commit
fd128a52e8
37 changed files with 2977 additions and 1943 deletions
File diff suppressed because it is too large
Load diff
199
sense/app/autocomplete/json_body_autocomplete.js
Normal file
199
sense/app/autocomplete/json_body_autocomplete.js
Normal file
|
@ -0,0 +1,199 @@
|
|||
define([
|
||||
'exports',
|
||||
'./json_rule_walker',
|
||||
'kb',
|
||||
'mappings',
|
||||
'_'
|
||||
],
|
||||
function (exports, json_rule_walker, kb, mappings, _) {
|
||||
"use strict";
|
||||
|
||||
function merge(a, b) {
|
||||
a.push.apply(a, b);
|
||||
}
|
||||
|
||||
function addMetaToTermsList(list, meta, template) {
|
||||
return _.map(list, function (t) {
|
||||
if (typeof t !== "object") {
|
||||
t = { name: t};
|
||||
}
|
||||
return _.defaults(t, { meta: meta, template: template });
|
||||
});
|
||||
}
|
||||
|
||||
function getRulesForPath(rules, tokenPath, scopeRules) {
|
||||
// scopeRules are the rules used to resolve relative scope links
|
||||
var walker = new json_rule_walker.RuleWalker(rules, scopeRules);
|
||||
walker.walkTokenPath(tokenPath);
|
||||
return walker.getNormalizedRules();
|
||||
|
||||
}
|
||||
|
||||
function expandTerm(term, context) {
|
||||
if (term == "$INDEX$") {
|
||||
return addMetaToTermsList(mappings.getIndices(), "index");
|
||||
}
|
||||
else if (term == "$TYPE$") {
|
||||
return addMetaToTermsList(mappings.getTypes(context.indices), "type");
|
||||
}
|
||||
else if (term == "$FIELD$") {
|
||||
return _.map(mappings.getFields(context.indices, context.types), function (f) {
|
||||
return { name: f.name, meta: f.type };
|
||||
});
|
||||
}
|
||||
return [ term ]
|
||||
}
|
||||
|
||||
function addAutocompleteForPath(autocompleteSet, rules, tokenPath, context) {
|
||||
// extracts the relevant parts of rules for tokenPath
|
||||
var initialRules = rules;
|
||||
rules = getRulesForPath(rules, tokenPath);
|
||||
|
||||
// apply rule set
|
||||
var term;
|
||||
if (rules) {
|
||||
if (typeof rules == "string") {
|
||||
merge(autocompleteSet, expandTerm(rules, context));
|
||||
}
|
||||
else if (rules instanceof Array) {
|
||||
if (rules.length > 0 && typeof rules[0] != "object") {// not an array of objects
|
||||
_.map(rules, function (t) {
|
||||
merge(autocompleteSet, expandTerm(t, context));
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (rules.__one_of) {
|
||||
if (rules.__one_of.length > 0 && typeof rules.__one_of[0] != "object") {
|
||||
merge(autocompleteSet, rules.__one_of);
|
||||
}
|
||||
}
|
||||
else if (rules.__any_of) {
|
||||
if (rules.__any_of.length > 0 && typeof rules.__any_of[0] != "object") {
|
||||
merge(autocompleteSet, rules.__any_of);
|
||||
}
|
||||
}
|
||||
else if (typeof rules == "object") {
|
||||
for (term in rules) {
|
||||
|
||||
if (typeof term == "string" && term.match(/^__|^\*$/)) {
|
||||
continue;
|
||||
} // meta term
|
||||
|
||||
var rules_for_term = rules[term], template_for_term;
|
||||
|
||||
// following linked scope until we find the right template
|
||||
while (typeof rules_for_term.__template == "undefined" &&
|
||||
typeof rules_for_term.__scope_link != "undefined"
|
||||
) {
|
||||
rules_for_term = json_rule_walker.getLinkedRules(rules_for_term.__scope_link, initialRules);
|
||||
}
|
||||
|
||||
if (typeof rules_for_term.__template != "undefined") {
|
||||
template_for_term = rules_for_term.__template;
|
||||
}
|
||||
else if (rules_for_term instanceof Array) {
|
||||
template_for_term = [];
|
||||
if (rules_for_term.length) {
|
||||
if (rules_for_term[0] instanceof Array) {
|
||||
template_for_term = [
|
||||
[]
|
||||
];
|
||||
}
|
||||
else if (typeof rules_for_term[0] == "object") {
|
||||
template_for_term = [
|
||||
{}
|
||||
];
|
||||
}
|
||||
else {
|
||||
template_for_term = [rules_for_term[0]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_.isObject(rules_for_term)) {
|
||||
if (rules_for_term.__one_of) {
|
||||
template_for_term = rules_for_term.__one_of[0];
|
||||
}
|
||||
else if (_.isEmpty(rules_for_term))
|
||||
// term sub rules object. Check if has actual or just meta stuff (like __one_of
|
||||
{
|
||||
template_for_term = {};
|
||||
}
|
||||
else {
|
||||
for (var sub_rule in rules_for_term) {
|
||||
if (!(typeof sub_rule == "string" && sub_rule.substring(0, 2) == "__")) {
|
||||
// found a real sub element, it's an object.
|
||||
template_for_term = {};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// just add what ever the value is -> default
|
||||
template_for_term = rules_for_term;
|
||||
}
|
||||
|
||||
switch (term) {
|
||||
case "$INDEX$":
|
||||
if (context.indices) {
|
||||
merge(autocompleteSet,
|
||||
addMetaToTermsList(context.indices, "index", template_for_term));
|
||||
}
|
||||
break;
|
||||
case "$TYPE$":
|
||||
merge(autocompleteSet,
|
||||
addMetaToTermsList(mappings.getTypes(context.indices), "type", template_for_term));
|
||||
break;
|
||||
case "$FIELD$":
|
||||
/* jshint -W083 */
|
||||
merge(autocompleteSet,
|
||||
_.map(mappings.getFields(context.indices, context.types), function (f) {
|
||||
return { name: f.name, meta: f.type, template: template_for_term };
|
||||
}));
|
||||
break;
|
||||
default:
|
||||
autocompleteSet.push({ name: term, template: template_for_term });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
autocompleteSet.push(rules);
|
||||
}
|
||||
}
|
||||
|
||||
return rules ? true : false;
|
||||
}
|
||||
|
||||
|
||||
exports.populateContext = function (tokenPath, context) {
|
||||
var autocompleteSet = [];
|
||||
|
||||
tokenPath = _.clone(tokenPath);
|
||||
|
||||
// apply global rules first, as they are of lower priority.
|
||||
// start with one before end as to not to resolve just "{" -> empty path
|
||||
for (var i = tokenPath.length - 2; i >= 0; i--) {
|
||||
var subPath = tokenPath.slice(i);
|
||||
if (addAutocompleteForPath(autocompleteSet, kb.getGlobalAutocompleteRules(), subPath, context)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var pathAsString = tokenPath.join(",");
|
||||
addAutocompleteForPath(autocompleteSet, (context.endpoint || {}).data_autocomplete_rules,
|
||||
tokenPath, context);
|
||||
|
||||
if (autocompleteSet) {
|
||||
_.uniq(autocompleteSet, false, function (t) {
|
||||
return t.name ? t.name : t
|
||||
});
|
||||
}
|
||||
|
||||
console.log("Resolved token path " + pathAsString + " to ", autocompleteSet,
|
||||
" (endpoint: ", context.endpoint, ")"
|
||||
);
|
||||
context.autoCompleteSet = autocompleteSet;
|
||||
return context;
|
||||
|
||||
}
|
||||
});
|
187
sense/app/autocomplete/json_rule_walker.js
Normal file
187
sense/app/autocomplete/json_rule_walker.js
Normal file
|
@ -0,0 +1,187 @@
|
|||
define(['_', 'kb', 'exports'], function (_, kb, exports) {
|
||||
'use strict';
|
||||
|
||||
var WALKER_MODE_EXPECTS_KEY = 1, WALKER_MODE_EXPECTS_CONTAINER = 2, WALKER_MODE_DONE = 3;
|
||||
|
||||
function RuleWalker(initialRules, scopeRules) {
|
||||
// scopeRules are the rules used to resolve relative scope links
|
||||
if (typeof scopeRules == "undefined") {
|
||||
scopeRules = initialRules;
|
||||
}
|
||||
|
||||
this._rules = initialRules;
|
||||
this._mode = WALKER_MODE_EXPECTS_CONTAINER;
|
||||
this.scopeRules = scopeRules;
|
||||
}
|
||||
|
||||
function getRulesType(rules) {
|
||||
if (rules == null || typeof rules == undefined) {
|
||||
return "null";
|
||||
}
|
||||
if (rules.__any_of || rules instanceof Array) {
|
||||
return "list";
|
||||
}
|
||||
if (rules.__one_of) {
|
||||
return getRulesType(rules.__one_of[0]);
|
||||
}
|
||||
if (typeof rules == "object") {
|
||||
return "object";
|
||||
}
|
||||
return "value";
|
||||
}
|
||||
|
||||
function getLinkedRules(link, currentRules) {
|
||||
var link_path = link.split(".");
|
||||
var scheme_id = link_path.shift();
|
||||
var linked_rules = currentRules;
|
||||
if (scheme_id == "GLOBAL") {
|
||||
linked_rules = kb.getGlobalAutocompleteRules();
|
||||
}
|
||||
else if (scheme_id) {
|
||||
linked_rules = kb.getEndpointDescriptionByEndpoint(scheme_id);
|
||||
if (!linked_rules) {
|
||||
throw "Failed to resolve linked scheme: " + scheme_id;
|
||||
}
|
||||
linked_rules = linked_rules.data_autocomplete_rules;
|
||||
if (!linked_rules) {
|
||||
throw "No autocomplete rules defined in linked scheme: " + scheme_id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var walker = new RuleWalker(linked_rules);
|
||||
var normalized_path = [];
|
||||
_.each(link_path, function (t) {
|
||||
normalized_path.push("{", t);
|
||||
}); // inject { before every step
|
||||
walker.walkTokenPath(normalized_path);
|
||||
var rules = walker.getRules();
|
||||
if (!rules) {
|
||||
throw "Failed to resolve rules by link: " + link;
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
|
||||
_.defaults(RuleWalker.prototype, {
|
||||
|
||||
walkByToken: function (token) {
|
||||
var new_rules;
|
||||
if (this._mode == WALKER_MODE_EXPECTS_KEY) {
|
||||
if (token == "{" || token == "[") {
|
||||
this._rules = null;
|
||||
this._mode = WALKER_MODE_DONE;
|
||||
return null;
|
||||
}
|
||||
new_rules = this._rules[token] || this._rules["*"]
|
||||
|| this._rules["$FIELD$"] || this._rules["$TYPE$"]; // we accept anything for a field.
|
||||
if (new_rules && new_rules.__scope_link) {
|
||||
new_rules = getLinkedRules(new_rules.__scope_link, this.scopeRules);
|
||||
}
|
||||
|
||||
switch (getRulesType(new_rules)) {
|
||||
case "object":
|
||||
case "list":
|
||||
this._mode = WALKER_MODE_EXPECTS_CONTAINER;
|
||||
break;
|
||||
default:
|
||||
this._mode = WALKER_MODE_DONE;
|
||||
}
|
||||
|
||||
this._rules = new_rules;
|
||||
return new_rules;
|
||||
}
|
||||
else if (this._mode == WALKER_MODE_EXPECTS_CONTAINER) {
|
||||
var rulesType = getRulesType(this._rules);
|
||||
|
||||
if (token == "{") {
|
||||
if (rulesType != "object") {
|
||||
this._mode = WALKER_MODE_DONE;
|
||||
return this._rules = null;
|
||||
}
|
||||
this._mode = WALKER_MODE_EXPECTS_KEY;
|
||||
return this._rules;
|
||||
}
|
||||
else if (token == "[") {
|
||||
if (this._rules.__any_of) {
|
||||
new_rules = this._rules.__any_of;
|
||||
}
|
||||
else if (this._rules instanceof Array) {
|
||||
new_rules = this._rules;
|
||||
}
|
||||
else {
|
||||
this._mode = WALKER_MODE_DONE;
|
||||
return this._rules = null;
|
||||
}
|
||||
|
||||
// for now we resolve using the first element in the array
|
||||
if (new_rules.length == 0) {
|
||||
this._mode = WALKER_MODE_DONE;
|
||||
return this._rules = null;
|
||||
}
|
||||
else {
|
||||
if (new_rules[0] && new_rules[0].__scope_link) {
|
||||
new_rules = [ getLinkedRules(new_rules[0].__scope_link, this.scopeRules) ];
|
||||
}
|
||||
switch (getRulesType(new_rules[0])) {
|
||||
case "object":
|
||||
this._mode = WALKER_MODE_EXPECTS_CONTAINER;
|
||||
new_rules = new_rules[0];
|
||||
break;
|
||||
case "list":
|
||||
this._mode = WALKER_MODE_EXPECTS_CONTAINER;
|
||||
new_rules = new_rules[0];
|
||||
break;
|
||||
default:
|
||||
this._mode = WALKER_MODE_EXPECTS_KEY;
|
||||
}
|
||||
}
|
||||
this._rules = new_rules;
|
||||
return this._rules;
|
||||
}
|
||||
else {
|
||||
this._rules = null;
|
||||
this._mode = WALKER_MODE_DONE;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._rules = null;
|
||||
this._mode = WALKER_MODE_DONE;
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
walkTokenPath: function (tokenPath) {
|
||||
if (tokenPath.length == 0) {
|
||||
return;
|
||||
}
|
||||
tokenPath = _.clone(tokenPath);
|
||||
var t;
|
||||
do {
|
||||
t = tokenPath.shift();
|
||||
}
|
||||
while (this._rules && this.walkByToken(t) != null && tokenPath.length);
|
||||
},
|
||||
|
||||
getRules: function () {
|
||||
return this._rules;
|
||||
},
|
||||
getNormalizedRules: function () {
|
||||
var rulesType = getRulesType(this._rules);
|
||||
if (this._mode == WALKER_MODE_EXPECTS_CONTAINER) {
|
||||
switch (rulesType) {
|
||||
case "object":
|
||||
return [ "{" ];
|
||||
case "list":
|
||||
return [ "[" ];
|
||||
}
|
||||
}
|
||||
return this._rules;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
exports.RuleWalker = RuleWalker;
|
||||
exports.getLinkedRules = getLinkedRules;
|
||||
});
|
158
sense/app/autocomplete/url_path_autocomplete.js
Normal file
158
sense/app/autocomplete/url_path_autocomplete.js
Normal file
|
@ -0,0 +1,158 @@
|
|||
define([
|
||||
'exports',
|
||||
'_'
|
||||
],
|
||||
function (exports, _) {
|
||||
"use strict";
|
||||
|
||||
exports.AutocompleteComponent = function (name) {
|
||||
this.name = name;
|
||||
};
|
||||
|
||||
exports.Matcher = function (name, next) {
|
||||
this.name = name;
|
||||
this.next = next;
|
||||
};
|
||||
|
||||
exports.AutocompleteComponent.prototype.getTerms = function (context, editor) {
|
||||
return [];
|
||||
};
|
||||
|
||||
/*
|
||||
if the current matcher matches this term, this method should return an object with the following keys
|
||||
{
|
||||
context_values: {
|
||||
values extract from term that should be added to the context
|
||||
}
|
||||
next: AutocompleteComponent(s) to use next
|
||||
priority: optional priority to solve collisions between multiple paths. Min value is used across entire chain
|
||||
}
|
||||
*/
|
||||
exports.AutocompleteComponent.prototype.match = function (token, context, editor) {
|
||||
var r = {};
|
||||
r[this.name] = token;
|
||||
return {
|
||||
next: this.next
|
||||
};
|
||||
};
|
||||
|
||||
function passThroughContext(context, extensionList) {
|
||||
function PTC() {
|
||||
|
||||
}
|
||||
|
||||
PTC.prototype = context;
|
||||
var r = new PTC();
|
||||
if (extensionList) {
|
||||
extensionList.unshift(r);
|
||||
_.assign.apply(_, extensionList);
|
||||
extensionList.shift();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function WalkingState(parent_name, components, contextExtensionList, depth, priority) {
|
||||
this.parent_name = parent_name;
|
||||
this.components = components;
|
||||
this.contextExtensionList = contextExtensionList;
|
||||
this.depth = depth || 0;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
|
||||
function walkTokenPath(tokenPath, walkingStates, context, editor) {
|
||||
if (!tokenPath || tokenPath.length === 0) {
|
||||
return walkingStates
|
||||
}
|
||||
var token = tokenPath[0],
|
||||
nextWalkingStates = [];
|
||||
|
||||
_.each(walkingStates, function (ws) {
|
||||
var contextForState = passThroughContext(context, ws.contextExtensionList);
|
||||
_.each(ws.components, function (component) {
|
||||
var result = component.match(token, contextForState, editor);
|
||||
if (result && !_.isEmpty(result)) {
|
||||
var next, extensionList;
|
||||
if (result.next && !_.isArray(result.next)) {
|
||||
next = [result.next];
|
||||
}
|
||||
else {
|
||||
next = result.next;
|
||||
}
|
||||
if (result.context_values) {
|
||||
extensionList = [];
|
||||
[].push.apply(extensionList, ws.contextExtensionList);
|
||||
extensionList.push(result.context_values);
|
||||
}
|
||||
else {
|
||||
extensionList = ws.contextExtensionList;
|
||||
}
|
||||
|
||||
var priority = ws.priority;
|
||||
if (_.isNumber(result.priority)) {
|
||||
if (_.isNumber(priority)) {
|
||||
priority = Math.min(priority, result.priority);
|
||||
}
|
||||
else {
|
||||
priority = result.priority;
|
||||
}
|
||||
}
|
||||
|
||||
nextWalkingStates.push(new WalkingState(component.name, next, extensionList, ws.depth + 1, priority));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (nextWalkingStates.length == 0) {
|
||||
// no where to go, still return context variables returned so far..
|
||||
return _.map(walkingStates, function (ws) {
|
||||
return new WalkingState(ws.name, [], ws.contextExtensionList);
|
||||
})
|
||||
}
|
||||
|
||||
return walkTokenPath(tokenPath.splice(1), nextWalkingStates, context, editor);
|
||||
}
|
||||
|
||||
exports.populateContext = function (tokenPath, context, editor, includeAutoComplete, components) {
|
||||
|
||||
var walkStates = walkTokenPath(tokenPath, [new WalkingState("ROOT", components, [])], context, editor);
|
||||
if (includeAutoComplete) {
|
||||
var autoCompleteSet = [];
|
||||
_.each(walkStates, function (ws) {
|
||||
var contextForState = passThroughContext(context, ws.contextExtensionList);
|
||||
_.each(ws.components, function (c) {
|
||||
_.each(c.getTerms(contextForState, editor), function (t) {
|
||||
if (!_.isObject(t)) {
|
||||
t = { name: t };
|
||||
}
|
||||
autoCompleteSet.push(t);
|
||||
});
|
||||
})
|
||||
});
|
||||
_.uniq(autoCompleteSet, false);
|
||||
context.autoCompleteSet = autoCompleteSet;
|
||||
}
|
||||
|
||||
// apply what values were set so far to context, selecting the deepest on which sets the context
|
||||
if (walkStates.length !== 0) {
|
||||
var wsToUse;
|
||||
walkStates = _.sortBy(walkStates, function (ws) {
|
||||
return _.isNumber(ws.priority) ? ws.priority : Number.MAX_VALUE;
|
||||
});
|
||||
wsToUse = _.find(walkStates, function (ws) {
|
||||
return _.isEmpty(ws.components)
|
||||
});
|
||||
if (!wsToUse && walkStates.length > 1 && !includeAutoComplete) {
|
||||
console.info("more then one context active for current path, but autocomplete isn't requested", walkStates);
|
||||
}
|
||||
if (!wsToUse) {
|
||||
wsToUse = walkStates[0];
|
||||
}
|
||||
_.each(wsToUse.contextExtensionList, function (e) {
|
||||
_.assign(context, e);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
});
|
150
sense/app/kb.js
150
sense/app/kb.js
|
@ -4,13 +4,117 @@ define([
|
|||
'mappings',
|
||||
'es',
|
||||
'kb/api',
|
||||
'kb/url_pattern_matcher',
|
||||
'require'
|
||||
],
|
||||
function (_, exports, mappings, es, api, require) {
|
||||
function (_, exports, mappings, es, api, url_pattern_matcher, require) {
|
||||
'use strict';
|
||||
|
||||
var ACTIVE_API = new api.Api("empty");
|
||||
|
||||
function nonValidIndexType(token) {
|
||||
return !(token === "_all" || token[0] !== "_");
|
||||
}
|
||||
|
||||
function IndexUrlComponent(name, parent, multi_valued) {
|
||||
url_pattern_matcher.ListComponent.call(this, name, mappings.getIndices, parent, multi_valued);
|
||||
}
|
||||
|
||||
IndexUrlComponent.prototype = _.create(
|
||||
url_pattern_matcher.ListComponent.prototype,
|
||||
{ 'constructor': IndexUrlComponent });
|
||||
|
||||
(function (cls) {
|
||||
cls.validateToken = function (token) {
|
||||
if (!this.multi_valued && token.length > 1) {
|
||||
return false;
|
||||
}
|
||||
return !_.find(token, nonValidIndexType);
|
||||
};
|
||||
|
||||
cls.getDefaultTermMeta = function () {
|
||||
return "index"
|
||||
};
|
||||
|
||||
cls.getContextKey = function () {
|
||||
return "indices";
|
||||
};
|
||||
})(IndexUrlComponent.prototype);
|
||||
|
||||
|
||||
function TypeGenerator(context) {
|
||||
return mappings.getTypes(context.indices);
|
||||
}
|
||||
|
||||
function TypeUrlComponent(name, parent, multi_valued) {
|
||||
url_pattern_matcher.ListComponent.call(this, name, TypeGenerator, parent, multi_valued);
|
||||
}
|
||||
|
||||
TypeUrlComponent.prototype = _.create(
|
||||
url_pattern_matcher.ListComponent.prototype,
|
||||
{ 'constructor': TypeUrlComponent });
|
||||
|
||||
(function (cls) {
|
||||
cls.validateToken = function (token) {
|
||||
if (!this.multi_valued && token.length > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !_.find(token, nonValidIndexType);
|
||||
};
|
||||
|
||||
cls.getDefaultTermMeta = function () {
|
||||
return "type"
|
||||
};
|
||||
|
||||
cls.getContextKey = function () {
|
||||
return "types";
|
||||
};
|
||||
})(TypeUrlComponent.prototype);
|
||||
|
||||
|
||||
function IdUrlComponent(name, parent) {
|
||||
url_pattern_matcher.SharedComponent.call(this, name, parent);
|
||||
}
|
||||
|
||||
IdUrlComponent.prototype = _.create(
|
||||
url_pattern_matcher.SharedComponent.prototype,
|
||||
{ 'constructor': IdUrlComponent });
|
||||
|
||||
(function (cls) {
|
||||
cls.match = function (token, context, editor) {
|
||||
if (_.isArray(token) || !token) {
|
||||
return null;
|
||||
}
|
||||
if (token.match(/[\/,]/)) {
|
||||
return null;
|
||||
}
|
||||
var r = Object.getPrototypeOf(cls).match.call(this, token, context, editor);
|
||||
r.context_values = r.context_values || {};
|
||||
r.context_values['id'] = token;
|
||||
return r;
|
||||
};
|
||||
})(IdUrlComponent.prototype);
|
||||
|
||||
var globalUrlComponentFactories = {
|
||||
|
||||
'index': function (part, parent, endpoint) {
|
||||
return new IndexUrlComponent(part, parent, false);
|
||||
},
|
||||
'indices': function (part, parent, endpoint) {
|
||||
return new IndexUrlComponent(part, parent, true);
|
||||
},
|
||||
'type': function (part, parent, endpoint) {
|
||||
return new TypeUrlComponent(part, parent, false);
|
||||
},
|
||||
'types': function (part, parent, endpoint) {
|
||||
return new TypeUrlComponent(part, parent, true);
|
||||
},
|
||||
'id': function (part, parent, endpoint) {
|
||||
return new IdUrlComponent(part, parent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function expandAliases(indices) {
|
||||
if (indices && indices.length > 0) {
|
||||
|
@ -23,16 +127,8 @@ define([
|
|||
return ACTIVE_API.getEndpointDescriptionByEndpoint(endpoint)
|
||||
}
|
||||
|
||||
function getEndpointsForIndicesTypesAndId(indices, types, id) {
|
||||
return ACTIVE_API.getEndpointsForIndicesTypesAndId(expandAliases(indices), types, id);
|
||||
}
|
||||
|
||||
function getEndpointDescriptionByPath(path, indices, types, id) {
|
||||
return ACTIVE_API.getEndpointDescriptionByPath(path, expandAliases(indices), types, id);
|
||||
}
|
||||
|
||||
function getEndpointAutocomplete(indices, types, id) {
|
||||
return ACTIVE_API.getEndpointAutocomplete(expandAliases(indices), types, id);
|
||||
function getTopLevelUrlCompleteComponents() {
|
||||
return ACTIVE_API.getTopLevelUrlCompleteComponents();
|
||||
}
|
||||
|
||||
function getGlobalAutocompleteRules() {
|
||||
|
@ -40,32 +136,48 @@ define([
|
|||
}
|
||||
|
||||
function setActiveApi(api) {
|
||||
if (_.isString(api)) {
|
||||
require([api], setActiveApi);
|
||||
return;
|
||||
}
|
||||
if (_.isFunction(api)) {
|
||||
/* jshint -W055 */
|
||||
setActiveApi(new api(globalUrlComponentFactories));
|
||||
return;
|
||||
}
|
||||
ACTIVE_API = api;
|
||||
console.log("setting api to " + api.name);
|
||||
}
|
||||
|
||||
es.addServerChangeListener(function () {
|
||||
var version = es.getVersion();
|
||||
var version = es.getVersion(), api;
|
||||
if (!version || version.length == 0) {
|
||||
require(["kb/api_0_90"], setActiveApi);
|
||||
api = "kb/api_0_90";
|
||||
}
|
||||
else if (version[0] === "1") {
|
||||
require(["kb/api_1_0"], setActiveApi);
|
||||
api = "kb/api_1_0";
|
||||
}
|
||||
else if (version[0] === "2") {
|
||||
require(["kb/api_1_0"], setActiveApi);
|
||||
api = "kb/api_1_0";
|
||||
}
|
||||
else {
|
||||
require(["kb/api_0_90"], setActiveApi);
|
||||
api = "kb/api_0_90";
|
||||
}
|
||||
|
||||
if (api) {
|
||||
setActiveApi(api);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
exports.setActiveApi = setActiveApi;
|
||||
exports.getGlobalAutocompleteRules = getGlobalAutocompleteRules;
|
||||
exports.getEndpointAutocomplete = getEndpointAutocomplete;
|
||||
exports.getEndpointDescriptionByPath = getEndpointDescriptionByPath;
|
||||
exports.getEndpointDescriptionByEndpoint = getEndpointDescriptionByEndpoint;
|
||||
exports.getEndpointsForIndicesTypesAndId = getEndpointsForIndicesTypesAndId;
|
||||
exports.getTopLevelUrlCompleteComponents = getTopLevelUrlCompleteComponents;
|
||||
|
||||
exports._test = {
|
||||
globalUrlComponentFactories: globalUrlComponentFactories
|
||||
};
|
||||
|
||||
return exports;
|
||||
});
|
|
@ -1,42 +1,42 @@
|
|||
define([ '_', 'exports'],
|
||||
function (_, exports) {
|
||||
define([ '_', 'exports', './url_pattern_matcher'],
|
||||
function (_, exports, url_pattern_matcher) {
|
||||
'use strict';
|
||||
|
||||
function Api(name) {
|
||||
this.global_rules = {};
|
||||
/**
|
||||
*
|
||||
* @param name
|
||||
* @param globalSharedComponentFactories a dictionary of factory functions
|
||||
* that will be used as fallback for parametrized path part (i.e., {indices} )
|
||||
* see url_pattern_matcher.UrlPatternMatcher
|
||||
* @constructor
|
||||
*/
|
||||
function Api(name, globalSharedComponentFactories) {
|
||||
this.globalRules = {};
|
||||
this.endpoints = {};
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
function escapeRegex(text) {
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
this.urlPatternMatcher = new url_pattern_matcher.UrlPatternMatcher(globalSharedComponentFactories);
|
||||
}
|
||||
|
||||
Api.prototype.addGlobalAutocompleteRules = function (parentNode, rules) {
|
||||
this.global_rules[parentNode] = rules;
|
||||
this.globalRules[parentNode] = rules;
|
||||
};
|
||||
|
||||
Api.prototype.getGlobalAutocompleteRules = function () {
|
||||
return this.global_rules;
|
||||
return this.globalRules;
|
||||
};
|
||||
|
||||
Api.prototype.addEndpointDescription = function (endpoint, description) {
|
||||
if (!description.endpoint_autocomplete) {
|
||||
description.endpoint_autocomplete = [endpoint];
|
||||
}
|
||||
|
||||
if (!description.match) {
|
||||
var l = _.map(description.endpoint_autocomplete, escapeRegex);
|
||||
description.match = "(?:" + l.join(")|(?:") + ")";
|
||||
}
|
||||
|
||||
if (typeof description.match == "string") {
|
||||
description.match = new RegExp(description.match);
|
||||
}
|
||||
|
||||
var copiedDescription = {};
|
||||
_.extend(copiedDescription, description);
|
||||
copiedDescription._id = endpoint;
|
||||
_.extend(copiedDescription, description || {});
|
||||
_.defaults(copiedDescription, {
|
||||
id: endpoint,
|
||||
patterns: [endpoint],
|
||||
methods: [ 'GET' ]
|
||||
});
|
||||
_.each(copiedDescription.patterns, function (p) {
|
||||
this.urlPatternMatcher.addEndpoint(p, copiedDescription);
|
||||
}, this);
|
||||
|
||||
this.endpoints[endpoint] = copiedDescription;
|
||||
};
|
||||
|
@ -45,100 +45,14 @@ define([ '_', 'exports'],
|
|||
return this.endpoints[endpoint];
|
||||
};
|
||||
|
||||
Api.prototype.getEndpointsForIndicesTypesAndId = function (indices, types, id) {
|
||||
var ret = [];
|
||||
var index_mode = "none";
|
||||
if (indices && indices.length > 0) {
|
||||
index_mode = typeof indices == "string" ? "single" : "multi";
|
||||
}
|
||||
|
||||
var type_mode = "none";
|
||||
if (types && types.length > 0) {
|
||||
type_mode = types.length > 1 ? "multi" : "single";
|
||||
}
|
||||
var id_mode = "none";
|
||||
if (id && id.length > 0) {
|
||||
id_mode = "single";
|
||||
}
|
||||
|
||||
for (var endpoint in this.endpoints) {
|
||||
var scheme = this.endpoints[endpoint];
|
||||
switch (scheme.indices_mode) {
|
||||
case "none":
|
||||
if (index_mode !== "none") {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case "single":
|
||||
if (index_mode !== "single") {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case "required_multi":
|
||||
if (index_mode === "none") {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case "multi": // always good
|
||||
break;
|
||||
}
|
||||
switch (scheme.types_mode) {
|
||||
case "none":
|
||||
if (type_mode !== "none") {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case "single":
|
||||
if (type_mode !== "single") {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case "multi": // always good
|
||||
break;
|
||||
}
|
||||
|
||||
switch (scheme.doc_id_mode) {
|
||||
case "none":
|
||||
if (id_mode !== "none") {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case "required_single":
|
||||
if (id_mode === "none") {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ret.push(endpoint);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
Api.prototype.getEndpointDescriptionByPath = function (path, indices, types, id) {
|
||||
var endpoints = this.getEndpointsForIndicesTypesAndId(indices, types, id);
|
||||
for (var i = 0; i < endpoints.length; i++) {
|
||||
var scheme = this.endpoints[endpoints[i]];
|
||||
if (scheme.match.test(path || "")) {
|
||||
return scheme;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Api.prototype.getEndpointAutocomplete = function (indices, types, id) {
|
||||
var ret = [];
|
||||
var endpoints = this.getEndpointsForIndicesTypesAndId(indices, types, id);
|
||||
for (var i = 0; i < endpoints.length; i++) {
|
||||
var scheme = this.endpoints[endpoints[i]];
|
||||
ret.push.apply(ret, scheme.endpoint_autocomplete);
|
||||
}
|
||||
return ret;
|
||||
Api.prototype.getTopLevelUrlCompleteComponents = function () {
|
||||
return this.urlPatternMatcher.getTopLevelComponents();
|
||||
};
|
||||
|
||||
Api.prototype.clear = function () {
|
||||
this.endpoints = {};
|
||||
this.global_rules = {};
|
||||
this.globalRules = {};
|
||||
};
|
||||
|
||||
exports.Api = Api;
|
||||
|
|
|
@ -3,6 +3,7 @@ define([
|
|||
'./api',
|
||||
'./api_0_90/aliases',
|
||||
'./api_0_90/cluster',
|
||||
'./api_0_90/document',
|
||||
'./api_0_90/facets',
|
||||
'./api_0_90/filter',
|
||||
'./api_0_90/globals',
|
||||
|
@ -17,11 +18,16 @@ define([
|
|||
], function (_, api) {
|
||||
'use strict';
|
||||
|
||||
var api_0_90 = new api.Api("api_0_90");
|
||||
var parts = _(arguments).rest(3);
|
||||
|
||||
_(arguments).rest(3).each(function (apiSection) {
|
||||
apiSection(api_0_90);
|
||||
});
|
||||
function Api_0_90(globalSharedComponentFactories) {
|
||||
api.Api.call(this, "api_0_90", globalSharedComponentFactories);
|
||||
parts.each(function (apiSection) {
|
||||
apiSection(this);
|
||||
}, this);
|
||||
}
|
||||
|
||||
return api_0_90;
|
||||
Api_0_90.prototype = _.create(api.Api.prototype, { 'constructor': Api_0_90 });
|
||||
|
||||
return Api_0_90;
|
||||
});
|
|
@ -3,15 +3,12 @@ define(function () {
|
|||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_aliases', {
|
||||
match: /_aliases/,
|
||||
def_method: 'GET',
|
||||
methods: ['GET', 'POST'],
|
||||
endpoint_autocomplete: [
|
||||
'_aliases'
|
||||
patterns: [
|
||||
"{indices}/_aliases",
|
||||
"_aliases",
|
||||
],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
'actions': {
|
||||
__template: [
|
||||
|
|
|
@ -2,34 +2,17 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_cluster/nodes/stats', {
|
||||
methods: ['GET'],
|
||||
indices_mode: 'none',
|
||||
types_mode: 'none'
|
||||
});
|
||||
api.addEndpointDescription('_cluster/nodes/stats');
|
||||
|
||||
api.addEndpointDescription('_cluster/state', {
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: ['_cluster/state'],
|
||||
indices_mode: 'none',
|
||||
types_mode: 'none'
|
||||
});
|
||||
api.addEndpointDescription('_cluster/state');
|
||||
|
||||
api.addEndpointDescription('_cluster/health', {
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: ['_cluster/health'],
|
||||
indices_mode: 'none',
|
||||
types_mode: 'none'
|
||||
});
|
||||
api.addEndpointDescription('_cluster/health');
|
||||
|
||||
api.addEndpointDescription('_cluster/settings', {
|
||||
methods: ['GET', 'PUT'],
|
||||
endpoint_autocomplete: ['_cluster/settings'],
|
||||
indices_mode: 'none',
|
||||
types_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
data_autocomplete_rules: {
|
||||
persistent: {
|
||||
'routing.allocation.same_shard.host' : { __one_of: [ false, true ]}
|
||||
'routing.allocation.same_shard.host': { __one_of: [ false, true ]}
|
||||
},
|
||||
transient: {
|
||||
__scope_link: '.persistent'
|
||||
|
|
37
sense/app/kb/api_0_90/document.js
Normal file
37
sense/app/kb/api_0_90/document.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
define(function () {
|
||||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_get_doc', {
|
||||
methods: ['GET'],
|
||||
patterns: [
|
||||
"{index}/{type}/{id}"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_get_doc_source', {
|
||||
methods: ['GET'],
|
||||
patterns: [
|
||||
"{index}/{type}/{id}/_source"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_delete_doc', {
|
||||
methods: ['DELETE'],
|
||||
patterns: [
|
||||
"{index}/{type}/{id}/"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('index_doc', {
|
||||
methods: ['PUT', 'POST'],
|
||||
patterns: [
|
||||
"{index}/{type}/{id}"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('index_doc_no_id', {
|
||||
methods: ['POST'],
|
||||
patterns: [
|
||||
"{index}/{type}"
|
||||
]
|
||||
});
|
||||
|
||||
}
|
||||
});
|
|
@ -3,49 +3,44 @@ define(function () {
|
|||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_refresh', {
|
||||
def_method: 'POST',
|
||||
methods: ['POST'],
|
||||
endpoint_autocomplete: [
|
||||
'_refresh'
|
||||
],
|
||||
indices_mode: 'multi'
|
||||
methods: ['POST']
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_stats', {
|
||||
def_method: 'GET',
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: [
|
||||
'_stats'
|
||||
],
|
||||
indices_mode: 'multi'
|
||||
patterns: [
|
||||
"{indices}/_stats",
|
||||
"_stats"
|
||||
]
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_segments', {
|
||||
def_method: 'GET',
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: [
|
||||
'_segments'
|
||||
],
|
||||
indices_mode: 'multi'
|
||||
patterns: [
|
||||
"{indices}/_segments",
|
||||
"_segments"
|
||||
]
|
||||
});
|
||||
|
||||
api.addEndpointDescription('__create_index__', {
|
||||
methods: ['PUT', 'DELETE'],
|
||||
indices_mode: 'single',
|
||||
types_mode: 'none',
|
||||
match: '^/?$',
|
||||
endpoint_autocomplete: [
|
||||
''
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"{index}"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
mappings: {
|
||||
__scope_link: '_mapping'
|
||||
__scope_link: '_put_mapping'
|
||||
},
|
||||
settings: {
|
||||
__scope_link: '_settings.index'
|
||||
__scope_link: '_put_settings.index'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
api.addEndpointDescription('__delete_indices__', {
|
||||
methods: ['DELETE'],
|
||||
patterns: [
|
||||
"{indices}"
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
});
|
|
@ -2,11 +2,22 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_mapping', {
|
||||
def_method: 'GET',
|
||||
methods: ['GET', 'PUT'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'multi',
|
||||
api.addEndpointDescription('_get_mapping', {
|
||||
methods: ['GET'],
|
||||
priority: 10, // collides with get doc by id
|
||||
patterns: [
|
||||
"{indices}/_mapping",
|
||||
"{indices}/{types}/_mapping",
|
||||
"_mapping"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_put_mapping', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"{indices}/_mapping",
|
||||
"{indices}/{type}/_mapping",
|
||||
],
|
||||
priority: 10, // collides with put doc by id
|
||||
data_autocomplete_rules: {
|
||||
'$TYPE$': {
|
||||
__template: {
|
||||
|
@ -106,7 +117,7 @@ define(function () {
|
|||
|
||||
// objects
|
||||
properties: {
|
||||
__scope_link: '_mapping.$TYPE$.properties'
|
||||
__scope_link: '_put_mapping.$TYPE$.properties'
|
||||
},
|
||||
|
||||
// multi_field
|
||||
|
@ -115,7 +126,7 @@ define(function () {
|
|||
},
|
||||
fields: {
|
||||
'*': {
|
||||
__scope_link: '_mapping.$TYPE$.properties.$FIELD$'
|
||||
__scope_link: '_put_mapping.$TYPE$.properties.$FIELD$'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,30 +2,9 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_stats', {
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: ['_stats'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none'
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_cache/clear', {
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: ['_cache/clear'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none'
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_status', {
|
||||
methods: ['GET'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
endpoint_autocomplete: ['_status']
|
||||
});
|
||||
api.addEndpointDescription('_cache/clear');
|
||||
|
||||
api.addEndpointDescription('_status');
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -3,14 +3,13 @@ define(function () {
|
|||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_search', {
|
||||
def_method: 'POST',
|
||||
methods: ['GET', 'POST'],
|
||||
endpoint_autocomplete: [
|
||||
'_search'
|
||||
priority: 10, // collides with get doc by id
|
||||
patterns: [
|
||||
"{indices}/{types}/_search",
|
||||
"{indices}/_search",
|
||||
"_search"
|
||||
],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'multi',
|
||||
doc_id_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
query: {
|
||||
// populated by a global rule
|
||||
|
|
|
@ -2,13 +2,18 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_settings', {
|
||||
match: /_settings/,
|
||||
methods: ['GET', 'PUT'],
|
||||
endpoint_autocomplete: ['_settings'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
api.addEndpointDescription('_get_settings', {
|
||||
patterns: [
|
||||
"{indices}/_settings",
|
||||
"_settings"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_put_settings', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"{indices}/_settings",
|
||||
"_settings"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
index: {
|
||||
refresh_interval: '1s',
|
||||
|
|
|
@ -2,16 +2,24 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_template', {
|
||||
match: /\/?_template/,
|
||||
def_method: 'PUT',
|
||||
methods: ['GET', 'PUT', 'DELETE'],
|
||||
endpoint_autocomplete: [
|
||||
'_template/TEMPLATE_ID'
|
||||
api.addEndpointDescription('_delete_template', {
|
||||
methods: ['DELETE'],
|
||||
patterns: [
|
||||
"_template/{id}",
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_get_template', {
|
||||
methods: ['GET'],
|
||||
patterns: [
|
||||
"_template/{id}",
|
||||
"_template",
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_put_template', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"_template/{id}",
|
||||
],
|
||||
indices_mode: 'none',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
template: 'index*',
|
||||
warmers: { __scope_link: '_warmer' },
|
||||
|
|
|
@ -2,16 +2,23 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_warmer', {
|
||||
match: /_warmer/,
|
||||
def_method: 'PUT',
|
||||
methods: ['GET', 'PUT', 'DELETE'],
|
||||
endpoint_autocomplete: [
|
||||
'_warmer', '_warmer/WARMER_ID'
|
||||
api.addEndpointDescription('_get_warmer', {
|
||||
patterns: ["_warmer", "_warmer/{id}"]
|
||||
});
|
||||
api.addEndpointDescription('_delete_warmer', {
|
||||
methods: ['DELETE'],
|
||||
patterns: [
|
||||
"{indices}/_warmer",
|
||||
"{indices}/_warmer/{id}"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_put_warmer', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"{indices}/_warmer",
|
||||
"{indices}/_warmer/{id}",
|
||||
"{indices}/{types}/_warmer/{id}"
|
||||
],
|
||||
indices_mode: 'required_multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
query: {
|
||||
// populated by a global rule
|
||||
|
|
|
@ -4,6 +4,7 @@ define([
|
|||
'./api_1_0/aliases',
|
||||
'./api_1_0/cat',
|
||||
'./api_1_0/cluster',
|
||||
'./api_1_0/document',
|
||||
'./api_1_0/facets',
|
||||
'./api_1_0/aggregations',
|
||||
'./api_1_0/filter',
|
||||
|
@ -19,12 +20,17 @@ define([
|
|||
], function (_, api) {
|
||||
'use strict';
|
||||
|
||||
var api_1_0 = new api.Api("api_1_0");
|
||||
var parts = _(arguments).rest(3);
|
||||
|
||||
function Api_1_0(globalSharedComponentFactories) {
|
||||
api.Api.call(this, "api_1_0", globalSharedComponentFactories);
|
||||
parts.each(function (apiSection) {
|
||||
apiSection(this);
|
||||
}, this);
|
||||
}
|
||||
|
||||
_(arguments).rest(3).each(function (apiSection) {
|
||||
apiSection(api_1_0);
|
||||
});
|
||||
Api_1_0.prototype = _.create(api.Api.prototype, { 'constructor': Api_1_0 });
|
||||
|
||||
return Api_1_0;
|
||||
|
||||
return api_1_0;
|
||||
});
|
|
@ -3,15 +3,12 @@ define(function () {
|
|||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_aliases', {
|
||||
match: /_aliases/,
|
||||
def_method: 'GET',
|
||||
methods: ['GET', 'POST'],
|
||||
endpoint_autocomplete: [
|
||||
'_aliases'
|
||||
patterns: [
|
||||
"{indices}/_aliases",
|
||||
"_aliases",
|
||||
],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
'actions': {
|
||||
__template: [
|
||||
|
|
|
@ -3,24 +3,27 @@ define(function () {
|
|||
|
||||
function addSimple(endpoint, api) {
|
||||
api.addEndpointDescription(endpoint, {
|
||||
def_method: 'GET',
|
||||
methods: ['GET' ],
|
||||
indices_mode: 'none',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return function init(api) {
|
||||
addSimple('_cluster/nodes/stats', api);
|
||||
addSimple('_cluster/state', api);
|
||||
addSimple('_cluster/health', api);
|
||||
addSimple('_cluster/pending_tasks', api);
|
||||
api.addEndpointDescription('_cluster/nodes/stats');
|
||||
api.addEndpointDescription('_cluster/state');
|
||||
api.addEndpointDescription('_cluster/health');
|
||||
api.addEndpointDescription('_cluster/pending_tasks');
|
||||
api.addEndpointDescription('get_cluster/settings', {
|
||||
patterns: [
|
||||
'_cluster/settings'
|
||||
]
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_cluster/settings', {
|
||||
methods: ['GET', 'PUT'],
|
||||
endpoint_autocomplete: ['_cluster/settings'],
|
||||
indices_mode: 'none',
|
||||
types_mode: 'none',
|
||||
api.addEndpointDescription('put_cluster/settings', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
'_cluster/settings'
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
persistent: {
|
||||
'routing.allocation.same_shard.host': { __one_of: [ false, true ]}
|
||||
|
|
37
sense/app/kb/api_1_0/document.js
Normal file
37
sense/app/kb/api_1_0/document.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
define(function () {
|
||||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_get_doc', {
|
||||
methods: ['GET'],
|
||||
patterns: [
|
||||
"{index}/{type}/{id}"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_get_doc_source', {
|
||||
methods: ['GET'],
|
||||
patterns: [
|
||||
"{index}/{type}/{id}/_source"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_delete_doc', {
|
||||
methods: ['DELETE'],
|
||||
patterns: [
|
||||
"{index}/{type}/{id}/"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('index_doc', {
|
||||
methods: ['PUT', 'POST'],
|
||||
patterns: [
|
||||
"{index}/{type}/{id}"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('index_doc_no_id', {
|
||||
methods: ['POST'],
|
||||
patterns: [
|
||||
"{index}/{type}"
|
||||
]
|
||||
});
|
||||
|
||||
}
|
||||
});
|
|
@ -3,49 +3,44 @@ define(function () {
|
|||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_refresh', {
|
||||
def_method: 'POST',
|
||||
methods: ['POST'],
|
||||
endpoint_autocomplete: [
|
||||
'_refresh'
|
||||
],
|
||||
indices_mode: 'multi'
|
||||
methods: ['POST']
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_stats', {
|
||||
def_method: 'GET',
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: [
|
||||
'_stats'
|
||||
],
|
||||
indices_mode: 'multi'
|
||||
patterns: [
|
||||
"{indices}/_stats",
|
||||
"_stats"
|
||||
]
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_segments', {
|
||||
def_method: 'GET',
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: [
|
||||
'_segments'
|
||||
],
|
||||
indices_mode: 'multi'
|
||||
patterns: [
|
||||
"{indices}/_segments",
|
||||
"_segments"
|
||||
]
|
||||
});
|
||||
|
||||
api.addEndpointDescription('__create_index__', {
|
||||
methods: ['PUT', 'DELETE'],
|
||||
indices_mode: 'single',
|
||||
types_mode: 'none',
|
||||
match: '^/?$',
|
||||
endpoint_autocomplete: [
|
||||
''
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"{index}"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
mappings: {
|
||||
__scope_link: '_mapping'
|
||||
__scope_link: '_put_mapping'
|
||||
},
|
||||
settings: {
|
||||
__scope_link: '_settings.index'
|
||||
__scope_link: '_put_settings.index'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
api.addEndpointDescription('__delete_indices__', {
|
||||
methods: ['DELETE'],
|
||||
patterns: [
|
||||
"{indices}"
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
});
|
|
@ -2,11 +2,22 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_mapping', {
|
||||
def_method: 'GET',
|
||||
methods: ['GET', 'PUT'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'multi',
|
||||
api.addEndpointDescription('_get_mapping', {
|
||||
methods: ['GET'],
|
||||
priority: 10, // collides with get doc by id
|
||||
patterns: [
|
||||
"{indices}/_mapping",
|
||||
"{indices}/{types}/_mapping",
|
||||
"_mapping"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_put_mapping', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"{indices}/_mapping",
|
||||
"{indices}/{type}/_mapping",
|
||||
],
|
||||
priority: 10, // collides with put doc by id
|
||||
data_autocomplete_rules: {
|
||||
'$TYPE$': {
|
||||
__template: {
|
||||
|
@ -106,7 +117,7 @@ define(function () {
|
|||
|
||||
// objects
|
||||
properties: {
|
||||
__scope_link: '_mapping.$TYPE$.properties'
|
||||
__scope_link: '_put_mapping.$TYPE$.properties'
|
||||
},
|
||||
|
||||
// multi_field
|
||||
|
@ -115,7 +126,7 @@ define(function () {
|
|||
},
|
||||
fields: {
|
||||
'*': {
|
||||
__scope_link: '_mapping.$TYPE$.properties.$FIELD$'
|
||||
__scope_link: '_put_mapping.$TYPE$.properties.$FIELD$'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,30 +3,24 @@ define(function () {
|
|||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_stats', {
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: ['_stats'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none'
|
||||
patterns: [
|
||||
"_stats",
|
||||
"{indices}/_stats"
|
||||
]
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_cache/clear', {
|
||||
methods: ['GET'],
|
||||
endpoint_autocomplete: ['_cache/clear'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none'
|
||||
patterns: [
|
||||
"_cache/clear",
|
||||
"{indices}/_cache/clear"
|
||||
]
|
||||
});
|
||||
|
||||
api.addEndpointDescription('_status', {
|
||||
methods: ['GET'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
endpoint_autocomplete: ['_status']
|
||||
patterns: [
|
||||
"_status",
|
||||
"{indices}/_status"
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
});
|
|
@ -3,14 +3,13 @@ define(function () {
|
|||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_search', {
|
||||
def_method: 'POST',
|
||||
methods: ['GET', 'POST'],
|
||||
endpoint_autocomplete: [
|
||||
'_search'
|
||||
priority: 10, // collides with get doc by id
|
||||
patterns: [
|
||||
"{indices}/{types}/_search",
|
||||
"{indices}/_search",
|
||||
"_search"
|
||||
],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'multi',
|
||||
doc_id_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
query: {
|
||||
// populated by a global rule
|
||||
|
|
|
@ -2,13 +2,18 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_settings', {
|
||||
match: /_settings/,
|
||||
methods: ['GET', 'PUT'],
|
||||
endpoint_autocomplete: ['_settings'],
|
||||
indices_mode: 'multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
api.addEndpointDescription('_get_settings', {
|
||||
patterns: [
|
||||
"{indices}/_settings",
|
||||
"_settings"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_put_settings', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"{indices}/_settings",
|
||||
"_settings"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
index: {
|
||||
refresh_interval: '1s',
|
||||
|
|
|
@ -2,16 +2,24 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_template', {
|
||||
match: /\/?_template/,
|
||||
def_method: 'PUT',
|
||||
methods: ['GET', 'PUT', 'DELETE'],
|
||||
endpoint_autocomplete: [
|
||||
'_template/TEMPLATE_ID'
|
||||
api.addEndpointDescription('_delete_template', {
|
||||
methods: ['DELETE'],
|
||||
patterns: [
|
||||
"_template/{id}",
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_get_template', {
|
||||
methods: ['GET'],
|
||||
patterns: [
|
||||
"_template/{id}",
|
||||
"_template",
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_put_template', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"_template/{id}",
|
||||
],
|
||||
indices_mode: 'none',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
template: 'index*',
|
||||
warmers: { __scope_link: '_warmer' },
|
||||
|
|
|
@ -2,16 +2,23 @@ define(function () {
|
|||
'use strict';
|
||||
|
||||
return function init(api) {
|
||||
api.addEndpointDescription('_warmer', {
|
||||
match: /_warmer/,
|
||||
def_method: 'PUT',
|
||||
methods: ['GET', 'PUT', 'DELETE'],
|
||||
endpoint_autocomplete: [
|
||||
'_warmer', '_warmer/WARMER_ID'
|
||||
api.addEndpointDescription('_get_warmer', {
|
||||
patterns: ["_warmer", "_warmer/{id}"]
|
||||
});
|
||||
api.addEndpointDescription('_delete_warmer', {
|
||||
methods: ['DELETE'],
|
||||
patterns: [
|
||||
"{indices}/_warmer",
|
||||
"{indices}/_warmer/{id}"
|
||||
]
|
||||
});
|
||||
api.addEndpointDescription('_put_warmer', {
|
||||
methods: ['PUT'],
|
||||
patterns: [
|
||||
"{indices}/_warmer",
|
||||
"{indices}/_warmer/{id}",
|
||||
"{indices}/{types}/_warmer/{id}"
|
||||
],
|
||||
indices_mode: 'required_multi',
|
||||
types_mode: 'none',
|
||||
doc_id_mode: 'none',
|
||||
data_autocomplete_rules: {
|
||||
query: {
|
||||
// populated by a global rule
|
||||
|
|
276
sense/app/kb/url_pattern_matcher.js
Normal file
276
sense/app/kb/url_pattern_matcher.js
Normal file
|
@ -0,0 +1,276 @@
|
|||
define([
|
||||
"_", "exports", "autocomplete/url_path_autocomplete"
|
||||
], function (_, exports, url_path_autocomplete) {
|
||||
"use strict";
|
||||
|
||||
exports.URL_PATH_END_MARKER = "__url_path_end__";
|
||||
|
||||
function SharedComponent(name, parent) {
|
||||
url_path_autocomplete.AutocompleteComponent.call(this, name);
|
||||
this._nextDict = {};
|
||||
if (parent) {
|
||||
parent.addComponent(this);
|
||||
}
|
||||
// for debugging purposes
|
||||
this._parent = parent;
|
||||
}
|
||||
|
||||
SharedComponent.prototype = _.create(
|
||||
url_path_autocomplete.AutocompleteComponent.prototype,
|
||||
{ 'constructor': SharedComponent });
|
||||
|
||||
(function (cls) {
|
||||
cls.getComponent = function (name) {
|
||||
return this._nextDict[name];
|
||||
};
|
||||
|
||||
cls.addComponent = function (c) {
|
||||
this._nextDict[c.name] = c;
|
||||
this.next = _.values(this._nextDict);
|
||||
};
|
||||
|
||||
})(SharedComponent.prototype);
|
||||
|
||||
/** A component that suggests one of the give options, but accepts anything */
|
||||
function ListComponent(name, list, parent, multi_valued) {
|
||||
SharedComponent.call(this, name, parent);
|
||||
this.listGenerator = _.isArray(list) ? function () {
|
||||
return list
|
||||
} : list;
|
||||
this.multi_valued = _.isUndefined(multi_valued) ? true : multi_valued;
|
||||
}
|
||||
|
||||
ListComponent.prototype = _.create(SharedComponent.prototype, { "constructor": ListComponent });
|
||||
|
||||
(function (cls) {
|
||||
cls.getTerms = function (context, editor) {
|
||||
if (!this.multi_valued && context.otherTokenValues) {
|
||||
// already have a value -> no suggestions
|
||||
return []
|
||||
}
|
||||
var already_set = context.otherTokenValues || [];
|
||||
if (_.isString(already_set)) {
|
||||
already_set = [already_set];
|
||||
}
|
||||
var ret = _.difference(this.listGenerator(context, editor), already_set);
|
||||
|
||||
if (this.getDefaultTermMeta()) {
|
||||
var meta = this.getDefaultTermMeta();
|
||||
ret = _.map(ret, function (t) {
|
||||
if (_.isString(t)) {
|
||||
t = { "name": t};
|
||||
}
|
||||
return _.defaults(t, { meta: meta });
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
cls.validateToken = function (token, context, editor) {
|
||||
if (!this.multi_valued && token.length > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// verify we have all tokens
|
||||
var list = this.listGenerator();
|
||||
var not_found = _.any(token, function (p) {
|
||||
return list.indexOf(p) == -1;
|
||||
});
|
||||
|
||||
if (not_found) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
cls.getContextKey = function (context, editor) {
|
||||
return this.name;
|
||||
};
|
||||
|
||||
cls.getDefaultTermMeta = function (context, editor) {
|
||||
return null;
|
||||
};
|
||||
|
||||
cls.match = function (token, context, editor) {
|
||||
if (!_.isArray(token)) {
|
||||
token = [ token ]
|
||||
}
|
||||
if (!this.validateToken(token, context, editor)) {
|
||||
return null
|
||||
}
|
||||
|
||||
var r = Object.getPrototypeOf(cls).match.call(this, token, context, editor);
|
||||
r.context_values = r.context_values || {};
|
||||
r.context_values[this.getContextKey()] = token;
|
||||
return r;
|
||||
}
|
||||
})(ListComponent.prototype);
|
||||
|
||||
function SimpleParamComponent(name, parent) {
|
||||
SharedComponent.call(this, name, parent);
|
||||
}
|
||||
|
||||
SimpleParamComponent.prototype = _.create(SharedComponent.prototype, { "constructor": SimpleParamComponent });
|
||||
|
||||
(function (cls) {
|
||||
cls.match = function (token, context, editor) {
|
||||
var r = Object.getPrototypeOf(cls).match.call(this, token, context, editor);
|
||||
r.context_values = r.context_values || {};
|
||||
r.context_values[this.name] = token;
|
||||
return r;
|
||||
}
|
||||
|
||||
})(SimpleParamComponent.prototype);
|
||||
|
||||
function SimplePartComponent(name, parent, options) {
|
||||
SharedComponent.call(this, name, parent);
|
||||
if (_.isString(options)) {
|
||||
options = [options];
|
||||
}
|
||||
this.options = options || [name];
|
||||
}
|
||||
|
||||
SimplePartComponent.prototype = _.create(SharedComponent.prototype, { "constructor": SimplePartComponent });
|
||||
|
||||
(function (cls) {
|
||||
cls.getTerms = function () {
|
||||
return this.options;
|
||||
};
|
||||
|
||||
cls.addOption = function (options) {
|
||||
if (!_.isArray(options)) {
|
||||
options = [options];
|
||||
}
|
||||
|
||||
[].push.apply(this.options, options);
|
||||
this.options = _.uniq(this.options);
|
||||
};
|
||||
cls.match = function (token, context, editor) {
|
||||
if (token !== this.name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Object.getPrototypeOf(cls).match.call(this, token, context, editor);
|
||||
|
||||
}
|
||||
})(SimplePartComponent.prototype);
|
||||
|
||||
function AcceptEndpointComponent(endpoint, parent) {
|
||||
SharedComponent.call(this, endpoint.id, parent);
|
||||
this.endpoint = endpoint
|
||||
}
|
||||
|
||||
AcceptEndpointComponent.prototype = _.create(SharedComponent.prototype, { "constructor": AcceptEndpointComponent });
|
||||
|
||||
(function (cls) {
|
||||
|
||||
cls.match = function (token, context, editor) {
|
||||
if (token !== exports.URL_PATH_END_MARKER) {
|
||||
return null;
|
||||
}
|
||||
if (this.endpoint.methods && -1 === _.indexOf(this.endpoint.methods, context.method)) {
|
||||
return null;
|
||||
}
|
||||
var r = Object.getPrototypeOf(cls).match.call(this, token, context, editor);
|
||||
r.context_values = r.context_values || {};
|
||||
r.context_values['endpoint'] = this.endpoint;
|
||||
if (_.isNumber(this.endpoint.priority)) {
|
||||
r.priority = this.endpoint.priority;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
})(AcceptEndpointComponent.prototype);
|
||||
|
||||
|
||||
/**
|
||||
* @param globalSharedComponentFactories a dict of the following structure
|
||||
* that will be used as a fall back for pattern parameters (i.e.: {indices})
|
||||
* {
|
||||
* indices: function (part, parent, endpoint) {
|
||||
* return new SharedComponent(part, parent)
|
||||
* }
|
||||
* }
|
||||
* @constructor
|
||||
*/
|
||||
function UrlPatternMatcher(globalSharedComponentFactories) {
|
||||
// This is not really a component, just a handy container to make iteration logic simpler
|
||||
this.rootComponent = new SharedComponent("ROOT");
|
||||
this.globalSharedComponentFactories = globalSharedComponentFactories || {};
|
||||
}
|
||||
|
||||
(function (cls) {
|
||||
cls.addEndpoint = function (pattern, endpoint) {
|
||||
var c,
|
||||
active_component = this.rootComponent,
|
||||
endpointComponents = endpoint.url_components || {};
|
||||
var partList = pattern.split("/");
|
||||
_.each(partList, function (part, partIndex) {
|
||||
if (part.search(/^{.+}$/) >= 0) {
|
||||
part = part.substr(1, part.length - 2);
|
||||
if (active_component.getComponent(part)) {
|
||||
// we already have something for this, reuse
|
||||
active_component = active_component.getComponent(part);
|
||||
return;
|
||||
}
|
||||
// a new path, resolve.
|
||||
|
||||
if ((c = endpointComponents[part])) {
|
||||
// endpoint specific. Support list
|
||||
if (_.isArray(c)) {
|
||||
c = new ListComponent(part, c, active_component);
|
||||
}
|
||||
else {
|
||||
console.warn("incorrectly configured url component ", part, " in endpoint", endpoint);
|
||||
c = new SharedComponent(part);
|
||||
}
|
||||
}
|
||||
else if ((c = this.globalSharedComponentFactories[part])) {
|
||||
// c is a f
|
||||
c = c(part, active_component, endpoint);
|
||||
}
|
||||
else {
|
||||
// just accept whatever with not suggestions
|
||||
c = new SimpleParamComponent(part, active_component);
|
||||
}
|
||||
|
||||
active_component = c;
|
||||
}
|
||||
else {
|
||||
// not pattern
|
||||
var lookAhead = part, s;
|
||||
|
||||
for (partIndex++; partIndex < partList.length; partIndex++) {
|
||||
s = partList[partIndex];
|
||||
if (s.indexOf("{") >= 0) {
|
||||
break;
|
||||
}
|
||||
lookAhead += "/" + s;
|
||||
|
||||
}
|
||||
|
||||
if (active_component.getComponent(part)) {
|
||||
// we already have something for this, reuse
|
||||
active_component = active_component.getComponent(part);
|
||||
active_component.addOption(lookAhead);
|
||||
}
|
||||
else {
|
||||
c = new SimplePartComponent(part, active_component, lookAhead);
|
||||
active_component = c;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
// mark end of endpoint path
|
||||
new AcceptEndpointComponent(endpoint, active_component);
|
||||
};
|
||||
|
||||
cls.getTopLevelComponents = function () {
|
||||
return this.rootComponent.next;
|
||||
}
|
||||
|
||||
})(UrlPatternMatcher.prototype);
|
||||
|
||||
exports.UrlPatternMatcher = UrlPatternMatcher;
|
||||
exports.SharedComponent = SharedComponent;
|
||||
exports.ListComponent = ListComponent;
|
||||
});
|
|
@ -148,7 +148,7 @@ define([
|
|||
if (requestRange) {
|
||||
var pos = editor.getCursorPosition();
|
||||
editor.getSession().replace(requestRange, text);
|
||||
var max_row = Math.max(requestRange.start.row + text.split('\n').length -1 , 0);
|
||||
var max_row = Math.max(requestRange.start.row + text.split('\n').length - 1, 0);
|
||||
pos.row = Math.min(pos.row, max_row);
|
||||
editor.moveCursorToPosition(pos);
|
||||
// ACE UPGRADE - check if needed - at the moment the above may trigger a selection.
|
||||
|
@ -267,10 +267,10 @@ define([
|
|||
var maxLines = session.getLength();
|
||||
for (; curRow < maxLines - 1; curRow++) {
|
||||
var curRowMode = editor.parser.getRowParseMode(curRow, editor);
|
||||
if ((curRowMode & RowParser.MODE_REQUEST_END) > 0) {
|
||||
if ((curRowMode & editor.parser.MODE.REQUEST_END) > 0) {
|
||||
break;
|
||||
}
|
||||
if (curRow != pos.row && (curRowMode & RowParser.MODE_REQUEST_START) > 0) {
|
||||
if (curRow != pos.row && (curRowMode & editor.parser.MODE.REQUEST_START) > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -290,10 +290,10 @@ define([
|
|||
if ((curRowMode & RowParser.REQUEST_END) > 0) {
|
||||
break;
|
||||
}
|
||||
if ((curRowMode & RowParser.MODE_MULTI_DOC_CUR_DOC_END) > 0) {
|
||||
if ((curRowMode & editor.parser.MODE.MULTI_DOC_CUR_DOC_END) > 0) {
|
||||
break;
|
||||
}
|
||||
if (curRow != pos.row && (curRowMode & RowParser.MODE_REQUEST_START) > 0) {
|
||||
if (curRow != pos.row && (curRowMode & editor.parser.MODE.REQUEST_START) > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ define(['require', 'exports', 'module' , 'ace'], function (require, exports, mod
|
|||
}
|
||||
|
||||
function addEOL(tokens, reg, nextIfEOL, normalNext) {
|
||||
if (typeof reg == "object") reg = reg.source;
|
||||
if (typeof reg == "object") {
|
||||
reg = reg.source;
|
||||
}
|
||||
return [
|
||||
{ token: tokens.concat(["whitespace"]), regex: reg + "(\\s*)$", next: nextIfEOL },
|
||||
{ token: tokens, regex: reg, next: normalNext }
|
||||
|
@ -41,33 +43,12 @@ define(['require', 'exports', 'module' , 'ace'], function (require, exports, mod
|
|||
}
|
||||
]),
|
||||
"method_sep": mergeTokens(
|
||||
addEOL(["whitespace", "url.slash"], /(\s+)(\/)/, "start", "indices"),
|
||||
addEOL(["whitespace"], /(\s+)/, "start", "indices")
|
||||
addEOL(["whitespace", "url.slash"], /(\s+)(\/)/, "start", "url"),
|
||||
addEOL(["whitespace"], /(\s+)/, "start", "url")
|
||||
),
|
||||
"indices": mergeTokens(
|
||||
addEOL(["url.scheme", "url.host", "url.slash"], /([^:]+:\/\/)([^?\/\s]*)(\/?)/, "start"),
|
||||
addEOL(["url.index"], /(_all)/, "start"),
|
||||
addEOL(["url.endpoint"], /(_[^\/?]+)/, "start", "urlRest"),
|
||||
addEOL(["url.index"], /([^\/?,]+)/, "start"),
|
||||
"url": mergeTokens(
|
||||
addEOL(["url.part"], /([^?\/,]+)/, "start"),
|
||||
addEOL(["url.comma"], /(,)/, "start"),
|
||||
addEOL(["url.slash"], /(\/)/, "start", "types"),
|
||||
addEOL(["url.questionmark"], /(\?)/, "start", "urlParams")
|
||||
),
|
||||
"types": mergeTokens(
|
||||
addEOL(["url.endpoint"], /(_[^\/?]+)/, "start", "urlRest"),
|
||||
addEOL(["url.type"], /([^\/?,]+)/, "start"),
|
||||
addEOL(["url.comma"], /(,)/, "start"),
|
||||
addEOL(["url.slash"], /(\/)/, "start", "id"),
|
||||
addEOL(["url.questionmark"], /(\?)/, "start", "urlParams")
|
||||
),
|
||||
"id": mergeTokens(
|
||||
addEOL(["url.endpoint"], /(_[^\/?]+)/, "start", "urlRest"),
|
||||
addEOL(["url.id"], /([^\/?]+)/, "start"),
|
||||
addEOL(["url.slash"], /(\/)/, "start", "urlRest"),
|
||||
addEOL(["url.questionmark"], /(\?)/, "start", "urlParams")
|
||||
),
|
||||
"urlRest": mergeTokens(
|
||||
addEOL(["url.part"], /([^?\/]+)/, "start"),
|
||||
addEOL(["url.slash"], /(\/)/, "start"),
|
||||
addEOL(["url.questionmark"], /(\?)/, "start", "urlParams")
|
||||
),
|
||||
|
@ -165,8 +146,9 @@ define(['require', 'exports', 'module' , 'ace'], function (require, exports, mod
|
|||
]
|
||||
}
|
||||
|
||||
if (this.constructor === SenseJsonHighlightRules)
|
||||
if (this.constructor === SenseJsonHighlightRules) {
|
||||
this.normalizeRules();
|
||||
}
|
||||
};
|
||||
|
||||
oop.inherits(SenseJsonHighlightRules, TextHighlightRules);
|
||||
|
|
|
@ -1,21 +1,39 @@
|
|||
define([], function () {
|
||||
'use strict';
|
||||
|
||||
var MODE = {
|
||||
REQUEST_START: 2,
|
||||
IN_REQUEST: 4,
|
||||
MULTI_DOC_CUR_DOC_END: 8,
|
||||
REQUEST_END: 16,
|
||||
BETWEEN_REQUESTS: 32
|
||||
|
||||
};
|
||||
|
||||
function RowParser(editor) {
|
||||
var defaultEditor = editor;
|
||||
|
||||
this.getRowParseMode = function (row) {
|
||||
if (row == null || typeof row == "undefined") row = editor.getCursorPosition().row;
|
||||
if (row == null || typeof row == "undefined") {
|
||||
row = editor.getCursorPosition().row;
|
||||
}
|
||||
|
||||
var session = editor.getSession();
|
||||
if (row >= session.getLength()) return RowParser.MODE_BETWEEN_REQUESTS;
|
||||
if (row >= session.getLength() || row < 0) {
|
||||
return MODE.BETWEEN_REQUESTS;
|
||||
}
|
||||
var mode = session.getState(row);
|
||||
if (!mode)
|
||||
return RowParser.MODE_BETWEEN_REQUESTS; // shouldn't really happen
|
||||
if (!mode) {
|
||||
return MODE.BETWEEN_REQUESTS;
|
||||
} // shouldn't really happen
|
||||
|
||||
if (mode !== "start") return RowParser.MODE_IN_REQUEST;
|
||||
if (mode !== "start") {
|
||||
return MODE.IN_REQUEST;
|
||||
}
|
||||
var line = (session.getLine(row) || "").trim();
|
||||
if (!line || line[0] === '#') return RowParser.MODE_BETWEEN_REQUESTS; // empty line or a comment waiting for a new req to start
|
||||
if (!line || line[0] === '#') {
|
||||
return MODE.BETWEEN_REQUESTS;
|
||||
} // empty line or a comment waiting for a new req to start
|
||||
|
||||
if (line.indexOf("}", line.length - 1) >= 0) {
|
||||
// check for a multi doc request (must start a new json doc immediately after this one end.
|
||||
|
@ -23,59 +41,59 @@ define([], function () {
|
|||
if (row < session.getLength()) {
|
||||
line = (session.getLine(row) || "").trim();
|
||||
if (line.indexOf("{") === 0) { // next line is another doc in a multi doc
|
||||
return RowParser.MODE_MULTI_DOC_CUR_DOC_END | RowParser.MODE_IN_REQUEST;
|
||||
return MODE.MULTI_DOC_CUR_DOC_END | MODE.IN_REQUEST;
|
||||
}
|
||||
|
||||
}
|
||||
return RowParser.MODE_REQUEST_END | RowParser.MODE_MULTI_DOC_CUR_DOC_END; // end of request
|
||||
return MODE.REQUEST_END | MODE.MULTI_DOC_CUR_DOC_END; // end of request
|
||||
}
|
||||
|
||||
// check for single line requests
|
||||
row++;
|
||||
if (row >= session.getLength()) {
|
||||
return RowParser.MODE_REQUEST_START | RowParser.MODE_REQUEST_END;
|
||||
return MODE.REQUEST_START | MODE.REQUEST_END;
|
||||
}
|
||||
line = (session.getLine(row) || "").trim();
|
||||
if (line.indexOf("{") !== 0) { // next line is another request
|
||||
return RowParser.MODE_REQUEST_START | RowParser.MODE_REQUEST_END;
|
||||
return MODE.REQUEST_START | MODE.REQUEST_END;
|
||||
}
|
||||
|
||||
return RowParser.MODE_REQUEST_START;
|
||||
}
|
||||
return MODE.REQUEST_START;
|
||||
};
|
||||
|
||||
this.rowPredicate = function (row, editor, value) {
|
||||
var mode = this.getRowParseMode(row, editor);
|
||||
return (mode & value) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
this.isEndRequestRow = function (row, _e) {
|
||||
var editor = _e || defaultEditor;
|
||||
return this.rowPredicate(row, editor, RowParser.MODE_REQUEST_END);
|
||||
return this.rowPredicate(row, editor, MODE.REQUEST_END);
|
||||
};
|
||||
|
||||
this.isRequestEdge = function (row, _e) {
|
||||
var editor = _e || defaultEditor;
|
||||
return this.rowPredicate(row, editor, RowParser.MODE_REQUEST_END | RowParser.MODE_REQUEST_START);
|
||||
return this.rowPredicate(row, editor, MODE.REQUEST_END | MODE.REQUEST_START);
|
||||
};
|
||||
|
||||
this.isStartRequestRow = function (row, _e) {
|
||||
var editor = _e || defaultEditor;
|
||||
return this.rowPredicate(row, editor, RowParser.MODE_REQUEST_START);
|
||||
return this.rowPredicate(row, editor, MODE.REQUEST_START);
|
||||
};
|
||||
|
||||
this.isInBetweenRequestsRow = function (row, _e) {
|
||||
var editor = _e || defaultEditor;
|
||||
return this.rowPredicate(row, editor, RowParser.MODE_BETWEEN_REQUESTS);
|
||||
return this.rowPredicate(row, editor, MODE.BETWEEN_REQUESTS);
|
||||
};
|
||||
|
||||
this.isInRequestsRow = function (row, _e) {
|
||||
var editor = _e || defaultEditor;
|
||||
return this.rowPredicate(row, editor, RowParser.MODE_IN_REQUEST);
|
||||
return this.rowPredicate(row, editor, MODE.IN_REQUEST);
|
||||
};
|
||||
|
||||
this.isMultiDocDocEndRow = function (row, _e) {
|
||||
var editor = _e || defaultEditor;
|
||||
return this.rowPredicate(row, editor, RowParser.MODE_MULTI_DOC_CUR_DOC_END);
|
||||
return this.rowPredicate(row, editor, MODE.MULTI_DOC_CUR_DOC_END);
|
||||
};
|
||||
|
||||
this.isEmptyToken = function (tokenOrTokenIter) {
|
||||
|
@ -103,11 +121,7 @@ define([], function () {
|
|||
};
|
||||
}
|
||||
|
||||
RowParser.MODE_REQUEST_START = 2;
|
||||
RowParser.MODE_IN_REQUEST = 4;
|
||||
RowParser.MODE_MULTI_DOC_CUR_DOC_END = 8;
|
||||
RowParser.MODE_REQUEST_END = 16;
|
||||
RowParser.MODE_BETWEEN_REQUESTS = 32;
|
||||
RowParser.prototype.MODE = MODE;
|
||||
|
||||
return RowParser;
|
||||
})
|
||||
});
|
|
@ -15,6 +15,7 @@
|
|||
z-index: 200;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
#output_container {
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
@ -25,52 +26,59 @@
|
|||
z-index: 201;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
#editor, #output {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="editor_container"><div id="editor"></div></div>
|
||||
<div id="output_container"><div id="output"></div></div>
|
||||
<div id="editor_container">
|
||||
<div id="editor"></div>
|
||||
</div>
|
||||
<div id="output_container">
|
||||
<div id="output"></div>
|
||||
</div>
|
||||
<script src="../vendor/require/require.js"></script>
|
||||
<script src="../app/require.config.js"></script>
|
||||
<script src="lib/qunit-1.10.0.js"></script>
|
||||
<script>
|
||||
/* global QUnit */
|
||||
QUnit.config.autostart = false;
|
||||
/* global QUnit */
|
||||
QUnit.config.autostart = false;
|
||||
|
||||
require.config({
|
||||
baseUrl: '../app'
|
||||
});
|
||||
require(["require","ace"], function (require) {
|
||||
require.config({
|
||||
baseUrl: '../app'
|
||||
});
|
||||
require(["require", "ace"], function (require) {
|
||||
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
|
||||
var tests = [
|
||||
'../tests/src/curl_tests.js',
|
||||
'../tests/src/kb_tests.js',
|
||||
'../tests/src/mapping_tests.js',
|
||||
'../tests/src/editor_tests.js',
|
||||
'../tests/src/tokenization_tests.js',
|
||||
'../tests/src/integration_tests.js'
|
||||
];
|
||||
var tests = [
|
||||
'../tests/src/url_autocomplete_tests.js',
|
||||
'../tests/src/curl_tests.js',
|
||||
'../tests/src/kb_tests.js',
|
||||
'../tests/src/mapping_tests.js',
|
||||
'../tests/src/editor_tests.js',
|
||||
'../tests/src/tokenization_tests.js',
|
||||
'../tests/src/integration_tests.js'
|
||||
];
|
||||
|
||||
// load the tests in series
|
||||
(function next(){
|
||||
if (tests.length) {
|
||||
require(tests.splice(0, 1), next);
|
||||
} else {
|
||||
console.log('all tests loaded');
|
||||
QUnit.start();
|
||||
}
|
||||
}());
|
||||
// load the tests in series
|
||||
(function next() {
|
||||
if (tests.length) {
|
||||
require(tests.splice(0, 1), next);
|
||||
}
|
||||
else {
|
||||
console.log('all tests loaded');
|
||||
QUnit.start();
|
||||
}
|
||||
}());
|
||||
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -36,16 +36,19 @@ define([
|
|||
|
||||
mappings.clear();
|
||||
mappings.loadMappings(mapping);
|
||||
var test_api = new api.Api();
|
||||
var test_api = new api.Api('test', kb._test.globalUrlComponentFactories);
|
||||
if (kb_schemes) {
|
||||
if (kb_schemes.globals)
|
||||
if (kb_schemes.globals) {
|
||||
$.each(kb_schemes.globals, function (parent, rules) {
|
||||
test_api.addGlobalAutocompleteRules(parent, rules);
|
||||
});
|
||||
if (kb_schemes.endpoints)
|
||||
}
|
||||
if (kb_schemes.endpoints) {
|
||||
$.each(kb_schemes.endpoints, function (endpoint, scheme) {
|
||||
_.defaults(scheme, { methods: null }); // disable method testing unless specified in test
|
||||
test_api.addEndpointDescription(endpoint, scheme);
|
||||
});
|
||||
}
|
||||
}
|
||||
kb.setActiveApi(test_api);
|
||||
|
||||
|
@ -56,74 +59,80 @@ define([
|
|||
setTimeout(function () {
|
||||
input.completer = {
|
||||
base: {},
|
||||
changeListener : function () {}
|
||||
changeListener: function () {
|
||||
}
|
||||
}; // mimic auto complete
|
||||
input.autocomplete._test.getCompletions(input, input.getSession(), test.cursor, "",
|
||||
function (err, terms) {
|
||||
|
||||
if (test.no_context) {
|
||||
ok(!terms || terms.length === 0, "Expected no context bug got terms.");
|
||||
}
|
||||
else {
|
||||
ok(terms && terms.length > 0, "failed to extract terms ...");
|
||||
}
|
||||
|
||||
if (!terms || terms.length === 0) {
|
||||
start();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (test["autoCompleteSet"]) {
|
||||
var expected_terms = _.map(test["autoCompleteSet"], function (t) {
|
||||
if (typeof t !== "object") {
|
||||
t = { "name": t };
|
||||
}
|
||||
return t;
|
||||
});
|
||||
if (terms.length != expected_terms.length) {
|
||||
equal(_.pluck(terms, 'name'), _.pluck(expected_terms, 'name'), "list of completion terms is not of equal size");
|
||||
} else {
|
||||
var filtered_actual_terms = _.map(terms, function (actual_term,i) {
|
||||
var expected_term = expected_terms[i];
|
||||
var filtered_term = {};
|
||||
_.each(expected_term, function (v,p) { filtered_term[p] = actual_term[p]; });
|
||||
return filtered_term;
|
||||
});
|
||||
deepEqual(filtered_actual_terms, expected_terms);
|
||||
if (test.no_context) {
|
||||
ok(!terms || terms.length === 0, "Expected no context bug got terms.");
|
||||
}
|
||||
else {
|
||||
ok(terms && terms.length > 0, "failed to extract terms ...");
|
||||
}
|
||||
}
|
||||
|
||||
var context = terms[0].context;
|
||||
input.autocomplete._test.addReplacementInfoToContext(context, test.cursor, terms[0].value);
|
||||
if (!terms || terms.length === 0) {
|
||||
start();
|
||||
return;
|
||||
}
|
||||
|
||||
function ac(prop, prop_test) {
|
||||
if (typeof test[prop] != "undefined")
|
||||
if (prop_test)
|
||||
prop_test(context[prop], test[prop], prop);
|
||||
else
|
||||
deepEqual(context[prop], test[prop], 'context.' + prop + ' should equal ' + JSON.stringify(test[prop]));
|
||||
}
|
||||
|
||||
function pos_compare(actual, expected, name) {
|
||||
equal(actual.row, expected.row + rowOffset, "row of " + name + " position is not as expected");
|
||||
equal(actual.column, expected.column, "column of " + name + " position is not as expected");
|
||||
}
|
||||
if (test["autoCompleteSet"]) {
|
||||
var expected_terms = _.map(test["autoCompleteSet"], function (t) {
|
||||
if (typeof t !== "object") {
|
||||
t = { "name": t };
|
||||
}
|
||||
return t;
|
||||
});
|
||||
if (terms.length != expected_terms.length) {
|
||||
equal(_.pluck(terms, 'name'), _.pluck(expected_terms, 'name'), "list of completion terms is not of equal size");
|
||||
}
|
||||
else {
|
||||
var filtered_actual_terms = _.map(terms, function (actual_term, i) {
|
||||
var expected_term = expected_terms[i];
|
||||
var filtered_term = {};
|
||||
_.each(expected_term, function (v, p) {
|
||||
filtered_term[p] = actual_term[p];
|
||||
});
|
||||
return filtered_term;
|
||||
});
|
||||
deepEqual(filtered_actual_terms, expected_terms);
|
||||
}
|
||||
}
|
||||
|
||||
function range_compare(actual, expected, name) {
|
||||
pos_compare(actual.start, expected.start, name + ".start");
|
||||
pos_compare(actual.end, expected.end, name + ".end");
|
||||
}
|
||||
var context = terms[0].context;
|
||||
input.autocomplete._test.addReplacementInfoToContext(context, test.cursor, terms[0].value);
|
||||
|
||||
ac("prefixToAdd");
|
||||
ac("suffixToAdd");
|
||||
ac("addTemplate");
|
||||
ac("textBoxPosition", pos_compare);
|
||||
ac("rangeToReplace", range_compare);
|
||||
function ac(prop, prop_test) {
|
||||
if (typeof test[prop] != "undefined") {
|
||||
if (prop_test) {
|
||||
prop_test(context[prop], test[prop], prop);
|
||||
}
|
||||
else {
|
||||
deepEqual(context[prop], test[prop], 'context.' + prop + ' should equal ' + JSON.stringify(test[prop]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
start();
|
||||
});
|
||||
function pos_compare(actual, expected, name) {
|
||||
equal(actual.row, expected.row + rowOffset, "row of " + name + " position is not as expected");
|
||||
equal(actual.column, expected.column, "column of " + name + " position is not as expected");
|
||||
}
|
||||
|
||||
function range_compare(actual, expected, name) {
|
||||
pos_compare(actual.start, expected.start, name + ".start");
|
||||
pos_compare(actual.end, expected.end, name + ".end");
|
||||
}
|
||||
|
||||
ac("prefixToAdd");
|
||||
ac("suffixToAdd");
|
||||
ac("addTemplate");
|
||||
ac("textBoxPosition", pos_compare);
|
||||
ac("rangeToReplace", range_compare);
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -131,7 +140,9 @@ define([
|
|||
}
|
||||
|
||||
function context_tests(data, mapping, kb_schemes, request_line, tests) {
|
||||
if (data != null && typeof data != "string") data = JSON.stringify(data, null, 3);
|
||||
if (data != null && typeof data != "string") {
|
||||
data = JSON.stringify(data, null, 3);
|
||||
}
|
||||
for (var t = 0; t < tests.length; t++) {
|
||||
process_context_test(data, mapping, kb_schemes, request_line, tests[t]);
|
||||
}
|
||||
|
@ -140,6 +151,11 @@ define([
|
|||
var SEARCH_KB = {
|
||||
endpoints: {
|
||||
_search: {
|
||||
patterns: [
|
||||
"{indices}/{types}/_search",
|
||||
"{indices}/_search",
|
||||
"_search"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
query: { match_all: {}, term: { "$FIELD$": ""}},
|
||||
size: {},
|
||||
|
@ -314,6 +330,9 @@ define([
|
|||
{
|
||||
endpoints: {
|
||||
_test: {
|
||||
patterns: [
|
||||
"_test"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
object: { bla: 1 },
|
||||
array: [ 1 ],
|
||||
|
@ -381,7 +400,9 @@ define([
|
|||
prefixToAdd: "",
|
||||
suffixToAdd: "",
|
||||
rangeToReplace: { start: { row: 5, column: 15 }, end: { row: 5, column: 15 }},
|
||||
autoCompleteSet: [{ name: "terms", meta: "API" }]
|
||||
autoCompleteSet: [
|
||||
{ name: "terms", meta: "API" }
|
||||
]
|
||||
}
|
||||
]
|
||||
);
|
||||
|
@ -394,6 +415,9 @@ define([
|
|||
{
|
||||
endpoints: {
|
||||
_test: {
|
||||
patterns: [
|
||||
"_test"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
index: "$INDEX$"
|
||||
}
|
||||
|
@ -405,7 +429,10 @@ define([
|
|||
{
|
||||
name: "$INDEX$ matching",
|
||||
cursor: { row: 1, column: 15},
|
||||
autoCompleteSet: [{ name: "index1", meta: "index"}, { name: "index2", meta: "index"}]
|
||||
autoCompleteSet: [
|
||||
{ name: "index1", meta: "index"},
|
||||
{ name: "index2", meta: "index"}
|
||||
]
|
||||
}
|
||||
]
|
||||
);
|
||||
|
@ -425,6 +452,9 @@ define([
|
|||
{
|
||||
endpoints: {
|
||||
_endpoint: {
|
||||
patterns: [
|
||||
"_endpoint"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
array: [ "a", "b"],
|
||||
number: 1,
|
||||
|
@ -441,7 +471,7 @@ define([
|
|||
name: "Templates 1",
|
||||
cursor: { row: 1, column: 0},
|
||||
autoCompleteSet: [
|
||||
tt("array", [ "a" ]), tt("fixed", { a: 1 }), tt("number",1), tt("object", {}), tt("oneof", "o1")
|
||||
tt("array", [ "a" ]), tt("fixed", { a: 1 }), tt("number", 1), tt("object", {}), tt("oneof", "o1")
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -468,6 +498,9 @@ define([
|
|||
{
|
||||
endpoints: {
|
||||
_endpoint: {
|
||||
patterns: [
|
||||
"_endpoint"
|
||||
],
|
||||
data_autocomplete_rules: {
|
||||
any_of_numbers: { __template: [1, 2], __any_of: [1, 2, 3]},
|
||||
any_of_obj: { __template: [
|
||||
|
@ -486,9 +519,11 @@ define([
|
|||
name: "Any of - templates",
|
||||
cursor: { row: 1, column: 0},
|
||||
autoCompleteSet: [
|
||||
tt("any_of_numbers", [ 1, 2 ]),
|
||||
tt("any_of_obj", [ { c: 1} ])
|
||||
]
|
||||
tt("any_of_numbers", [ 1, 2 ]),
|
||||
tt("any_of_obj", [
|
||||
{ c: 1}
|
||||
])
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Any of - numbers",
|
||||
|
@ -499,7 +534,7 @@ define([
|
|||
name: "Any of - object",
|
||||
cursor: { row: 6, column: 2},
|
||||
autoCompleteSet: [
|
||||
tt("a", 1),tt("b", 2 )
|
||||
tt("a", 1), tt("b", 2)
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -511,6 +546,7 @@ define([
|
|||
{
|
||||
endpoints: {
|
||||
_endpoint: {
|
||||
patterns: [ "_endpoint" ],
|
||||
data_autocomplete_rules: {
|
||||
"query": ""
|
||||
}
|
||||
|
@ -522,7 +558,7 @@ define([
|
|||
{
|
||||
name: "Empty string as default",
|
||||
cursor: { row: 0, column: 1},
|
||||
autoCompleteSet: [tt("query","")]
|
||||
autoCompleteSet: [tt("query", "")]
|
||||
}
|
||||
]
|
||||
);
|
||||
|
@ -548,8 +584,8 @@ define([
|
|||
},
|
||||
endpoints: {
|
||||
_current: {
|
||||
|
||||
_id: "POST _current",
|
||||
patterns: [ "_current" ],
|
||||
id: "POST _current",
|
||||
data_autocomplete_rules: {
|
||||
"a": {
|
||||
"b": {
|
||||
|
@ -573,6 +609,7 @@ define([
|
|||
}
|
||||
},
|
||||
ext: {
|
||||
patterns: [ "ext" ],
|
||||
data_autocomplete_rules: {
|
||||
target: {
|
||||
t2: 1
|
||||
|
@ -586,8 +623,10 @@ define([
|
|||
{
|
||||
name: "Relative scope link test",
|
||||
cursor: { row: 2, column: 12},
|
||||
autoCompleteSet:[
|
||||
tt("b", {}), tt("c", {}), tt("d", {}), tt("e", {}), tt("f", [ {} ])
|
||||
autoCompleteSet: [
|
||||
tt("b", {}), tt("c", {}), tt("d", {}), tt("e", {}), tt("f", [
|
||||
{}
|
||||
])
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -621,6 +660,7 @@ define([
|
|||
{
|
||||
endpoints: {
|
||||
_endpoint: {
|
||||
patterns: ["_endpoint"],
|
||||
data_autocomplete_rules: {
|
||||
"a": {},
|
||||
"b": {}
|
||||
|
@ -666,6 +706,7 @@ define([
|
|||
{
|
||||
endpoints: {
|
||||
_endpoint: {
|
||||
patterns: ["_endpoint"],
|
||||
data_autocomplete_rules: {
|
||||
"a": [
|
||||
{ b: 1}
|
||||
|
@ -726,10 +767,10 @@ define([
|
|||
|
||||
|
||||
context_tests(
|
||||
"",
|
||||
"POST _search",
|
||||
MAPPING,
|
||||
SEARCH_KB,
|
||||
"POST _search",
|
||||
null,
|
||||
[
|
||||
{
|
||||
name: "initial doc start",
|
||||
|
@ -772,15 +813,18 @@ define([
|
|||
var CLUSTER_KB = {
|
||||
endpoints: {
|
||||
"_search": {
|
||||
patterns: ["_search", "{indices}/{types}/_search", "{indices}/_search"],
|
||||
data_autocomplete_rules: {
|
||||
}
|
||||
},
|
||||
"_cluster/stats": {
|
||||
patterns: ["_cluster/stats"],
|
||||
indices_mode: "none",
|
||||
data_autocomplete_rules: {
|
||||
}
|
||||
},
|
||||
"_cluster/nodes/stats": {
|
||||
patterns: ["_cluster/nodes/stats"],
|
||||
data_autocomplete_rules: {
|
||||
}
|
||||
}
|
||||
|
@ -796,7 +840,7 @@ define([
|
|||
{
|
||||
name: "Endpoints with slashes - no slash",
|
||||
cursor: { row: 0, column: 8},
|
||||
autoCompleteSet: [ "_cluster/nodes/stats", "_cluster/stats", "_search"],
|
||||
autoCompleteSet: [ "_cluster/nodes/stats", "_cluster/stats", "_search", "index1", "index2"],
|
||||
prefixToAdd: "",
|
||||
suffixToAdd: ""
|
||||
}
|
||||
|
@ -812,14 +856,21 @@ define([
|
|||
{
|
||||
name: "Endpoints with slashes - before slash",
|
||||
cursor: { row: 0, column: 8},
|
||||
autoCompleteSet: [ "_cluster/nodes/stats", "_cluster/stats", "_search"],
|
||||
autoCompleteSet: [ "_cluster/nodes/stats", "_cluster/stats", "_search", "index1", "index2"],
|
||||
prefixToAdd: "",
|
||||
suffixToAdd: ""
|
||||
},
|
||||
{
|
||||
name: "Endpoints with slashes - on slash",
|
||||
cursor: { row: 0, column: 13},
|
||||
autoCompleteSet: [ "_cluster/nodes/stats", "_cluster/stats", "_search"],
|
||||
autoCompleteSet: [ "_cluster/nodes/stats", "_cluster/stats", "_search", "index1", "index2"],
|
||||
prefixToAdd: "",
|
||||
suffixToAdd: ""
|
||||
},
|
||||
{
|
||||
name: "Endpoints with slashes - after slash",
|
||||
cursor: { row: 0, column: 14},
|
||||
autoCompleteSet: [ "nodes/stats", "stats"],
|
||||
prefixToAdd: "",
|
||||
suffixToAdd: ""
|
||||
}
|
||||
|
@ -835,7 +886,10 @@ define([
|
|||
{
|
||||
name: "Endpoints with slashes - after slash",
|
||||
cursor: { row: 0, column: 15},
|
||||
autoCompleteSet: [ { name: "nodes/stats", meta: "endpoint" } , { name: "stats", meta: "endpoint" } ],
|
||||
autoCompleteSet: [
|
||||
{ name: "nodes/stats", meta: "endpoint" } ,
|
||||
{ name: "stats", meta: "endpoint" }
|
||||
],
|
||||
prefixToAdd: "",
|
||||
suffixToAdd: "",
|
||||
initialValue: "no"
|
||||
|
@ -860,6 +914,29 @@ define([
|
|||
]
|
||||
);
|
||||
|
||||
context_tests(
|
||||
null,
|
||||
MAPPING,
|
||||
CLUSTER_KB,
|
||||
"POST ",
|
||||
[
|
||||
{
|
||||
name: "Immediately after space + method",
|
||||
cursor: { row: 0, column: 5},
|
||||
autoCompleteSet: [
|
||||
{ name: "_cluster/nodes/stats", meta: "endpoint" },
|
||||
{ name: "_cluster/stats", meta: "endpoint" },
|
||||
{ name: "_search", meta: "endpoint" },
|
||||
{ name: "index1", meta: "index" },
|
||||
{ name: "index2", meta: "index" }
|
||||
],
|
||||
prefixToAdd: "",
|
||||
suffixToAdd: "",
|
||||
initialValue: ""
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
context_tests(
|
||||
null,
|
||||
MAPPING,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
define([
|
||||
'kb',
|
||||
'mappings',
|
||||
'kb/api'
|
||||
], function (kb, mappings, api) {
|
||||
'kb/api',
|
||||
'autocomplete/url_path_autocomplete'
|
||||
], function (kb, mappings, api, url_path_autocomplete) {
|
||||
'use strict';
|
||||
|
||||
module("Knowledge base", {
|
||||
|
@ -16,102 +17,160 @@ define([
|
|||
}
|
||||
});
|
||||
|
||||
var MAPPING = {
|
||||
"index1": {
|
||||
"type1.1": {
|
||||
"properties": {
|
||||
"field1.1.1": { "type": "string" },
|
||||
"field1.1.2": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"type1.2": {
|
||||
"properties": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"index2": {
|
||||
"type2.1": {
|
||||
"properties": {
|
||||
"field2.1.1": { "type": "string" },
|
||||
"field2.1.2": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test("Index mode filters", function () {
|
||||
var test_api = new api.Api();
|
||||
test_api.addEndpointDescription("_multi_indices", {
|
||||
indices_mode: "multi"
|
||||
});
|
||||
test_api.addEndpointDescription("_one_or_more_indices", {
|
||||
indices_mode: "required_multi"
|
||||
});
|
||||
test_api.addEndpointDescription("_single_index", {
|
||||
match: "_single_index",
|
||||
endpoint_autocomplete: [
|
||||
"_single_index"
|
||||
],
|
||||
indices_mode: "single"
|
||||
});
|
||||
test_api.addEndpointDescription("_no_index", {
|
||||
indices_mode: "none"
|
||||
});
|
||||
kb.setActiveApi(test_api);
|
||||
function testContext(tokenPath, otherTokenValues, expectedContext) {
|
||||
|
||||
deepEqual(kb.getEndpointAutocomplete([], [], null).sort(), ["_multi_indices", "_no_index" ]);
|
||||
deepEqual(kb.getEndpointAutocomplete(["index"], [], null).sort(), ["_multi_indices", "_one_or_more_indices", "_single_index"]);
|
||||
deepEqual(kb.getEndpointAutocomplete(["index1", "index2"], [], null).sort(), ["_multi_indices", "_one_or_more_indices"]);
|
||||
deepEqual(kb.getEndpointAutocomplete(["index1", "index2"], ["type"], null).sort(), ["_multi_indices", "_one_or_more_indices"]);
|
||||
});
|
||||
if (expectedContext.autoCompleteSet) {
|
||||
expectedContext.autoCompleteSet = _.map(expectedContext.autoCompleteSet, function (t) {
|
||||
if (_.isString(t)) {
|
||||
t = { name: t}
|
||||
}
|
||||
return t;
|
||||
})
|
||||
}
|
||||
|
||||
test("Type mode filters", function () {
|
||||
var test_api = new api.Api();
|
||||
var context = { otherTokenValues: otherTokenValues};
|
||||
url_path_autocomplete.populateContext(tokenPath, context, null,
|
||||
expectedContext.autoCompleteSet, kb.getTopLevelUrlCompleteComponents()
|
||||
);
|
||||
|
||||
test_api.addEndpointDescription("_multi_types", {
|
||||
indices_mode: "single",
|
||||
types_mode: "multi"
|
||||
// override context to just check on id
|
||||
if (context.endpoint) {
|
||||
context.endpoint = context.endpoint.id;
|
||||
}
|
||||
|
||||
delete context.otherTokenValues;
|
||||
|
||||
function norm(t) {
|
||||
if (_.isString(t)) {
|
||||
return { name: t };
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
if (context.autoCompleteSet) {
|
||||
context.autoCompleteSet = _.sortBy(_.map(context.autoCompleteSet, norm), 'name');
|
||||
}
|
||||
if (expectedContext.autoCompleteSet) {
|
||||
expectedContext.autoCompleteSet = _.sortBy(_.map(expectedContext.autoCompleteSet, norm), 'name');
|
||||
}
|
||||
|
||||
deepEqual(context, expectedContext);
|
||||
}
|
||||
|
||||
function t(term) {
|
||||
return { name: term, meta: "type"};
|
||||
}
|
||||
|
||||
function i(term) {
|
||||
return { name: term, meta: "index"};
|
||||
}
|
||||
|
||||
function index_test(name, tokenPath, otherTokenValues, expectedContext) {
|
||||
test(name, function () {
|
||||
var test_api = new api.Api("text", kb._test.globalUrlComponentFactories);
|
||||
test_api.addEndpointDescription("_multi_indices", {
|
||||
patterns: ["{indices}/_multi_indices"]
|
||||
});
|
||||
test_api.addEndpointDescription("_single_index", {
|
||||
patterns: ["{index}/_single_index"]
|
||||
});
|
||||
test_api.addEndpointDescription("_no_index", {
|
||||
// testing default patterns
|
||||
// patterns: ["_no_index"]
|
||||
});
|
||||
kb.setActiveApi(test_api);
|
||||
|
||||
mappings.loadMappings(MAPPING);
|
||||
testContext(tokenPath, otherTokenValues, expectedContext);
|
||||
});
|
||||
test_api.addEndpointDescription("_single_type", {
|
||||
endpoint_autocomplete: [
|
||||
"_single_type"
|
||||
],
|
||||
indices_mode: "single",
|
||||
types_mode: "single"
|
||||
});
|
||||
test_api.addEndpointDescription("_no_types", {
|
||||
indices_mode: "single",
|
||||
types_mode: "none"
|
||||
}
|
||||
|
||||
index_test("Index integration 1", [], [],
|
||||
{ autoCompleteSet: ["_no_index", i("index1"), i("index2")]}
|
||||
);
|
||||
|
||||
index_test("Index integration 2", [], ["index1"],
|
||||
// still return _no_index as index1 is not committed to yet.
|
||||
{ autoCompleteSet: ["_no_index", i("index2")]}
|
||||
);
|
||||
|
||||
index_test("Index integration 2", ["index1"], [],
|
||||
{ indices: ["index1"], autoCompleteSet: ["_multi_indices", "_single_index"]}
|
||||
);
|
||||
|
||||
index_test("Index integration 2", [
|
||||
["index1", "index2"]
|
||||
], [],
|
||||
{ indices: ["index1", "index2"], autoCompleteSet: ["_multi_indices"]}
|
||||
);
|
||||
|
||||
function type_test(name, tokenPath, otherTokenValues, expectedContext) {
|
||||
test(name, function () {
|
||||
var test_api = new api.Api("type_test", kb._test.globalUrlComponentFactories);
|
||||
|
||||
test_api.addEndpointDescription("_multi_types", {
|
||||
patterns: ["{indices}/{types}/_multi_types"]
|
||||
});
|
||||
test_api.addEndpointDescription("_single_type", {
|
||||
patterns: ["{indices}/{type}/_single_type"]
|
||||
});
|
||||
test_api.addEndpointDescription("_no_types", {
|
||||
patterns: ["{indices}/_no_types"]
|
||||
});
|
||||
kb.setActiveApi(test_api);
|
||||
|
||||
mappings.loadMappings(MAPPING);
|
||||
|
||||
testContext(tokenPath, otherTokenValues, expectedContext);
|
||||
|
||||
});
|
||||
kb.setActiveApi(test_api);
|
||||
}
|
||||
|
||||
type_test("Type integration 1", ["index1"], [],
|
||||
{ indices: ["index1"], autoCompleteSet: ["_no_types", t("type1.1"), t("type1.2")]}
|
||||
);
|
||||
type_test("Type integration 2", ["index1"], ["type1.2"],
|
||||
// we are not yet comitted to type1.2, so _no_types is returned
|
||||
{ indices: ["index1"], autoCompleteSet: ["_no_types", t("type1.1")]}
|
||||
);
|
||||
|
||||
deepEqual(kb.getEndpointAutocomplete(["index"], [], null).sort(), ["_multi_types", "_no_types" ]);
|
||||
deepEqual(kb.getEndpointAutocomplete(["index"], ["type"], null).sort(), ["_multi_types", "_single_type"]);
|
||||
deepEqual(kb.getEndpointAutocomplete(["index"], ["type", "type1"], null).sort(), ["_multi_types"]);
|
||||
});
|
||||
type_test("Type integration 3", ["index2"], [],
|
||||
{ indices: ["index2"], autoCompleteSet: ["_no_types", t("type2.1")]}
|
||||
);
|
||||
|
||||
test("Id mode filters", function () {
|
||||
var test_api = new api.Api();
|
||||
type_test("Type integration 4", ["index1", "type1.2"], [],
|
||||
{ indices: ["index1"], types: ["type1.2"], autoCompleteSet: ["_multi_types", "_single_type"]}
|
||||
);
|
||||
|
||||
test_api.addEndpointDescription("_single_id", {
|
||||
indices_mode: "single",
|
||||
types_mode: "single",
|
||||
doc_id_mode: "required_single"
|
||||
});
|
||||
test_api.addEndpointDescription("_no_id", {
|
||||
indices_mode: "single",
|
||||
types_mode: "single",
|
||||
doc_id_mode: "none"
|
||||
type_test("Type integration 5", [
|
||||
["index1", "index2"],
|
||||
["type1.2", "type1.1"]
|
||||
], [],
|
||||
{ indices: ["index1", "index2"], types: ["type1.2", "type1.1"], autoCompleteSet: ["_multi_types"]}
|
||||
);
|
||||
|
||||
});
|
||||
kb.setActiveApi(test_api);
|
||||
|
||||
|
||||
deepEqual(kb.getEndpointAutocomplete(["index"], ["type"], null).sort(), ["_no_id"].sort());
|
||||
deepEqual(kb.getEndpointAutocomplete(["index"], ["type"], "123").sort(), ["_single_id"].sort());
|
||||
});
|
||||
|
||||
test("Get active scheme by doc id", function () {
|
||||
var test_api = new api.Api();
|
||||
|
||||
test_api.addEndpointDescription("_single_id", {
|
||||
match: ".*",
|
||||
indices_mode: "single",
|
||||
types_mode: "single",
|
||||
doc_id_mode: "required_single"
|
||||
});
|
||||
test_api.addEndpointDescription("_no_id", {
|
||||
match: ".*",
|
||||
indices_mode: "single",
|
||||
types_mode: "single",
|
||||
doc_id_mode: "none"
|
||||
|
||||
});
|
||||
kb.setActiveApi(test_api);
|
||||
|
||||
|
||||
deepEqual(kb.getEndpointDescriptionByPath("bla", ["index"], ["type"], null).doc_id_mode, "none");
|
||||
deepEqual(kb.getEndpointDescriptionByPath("bla", ["index"], ["type"], "123").doc_id_mode, "required_single");
|
||||
});
|
||||
|
||||
});
|
|
@ -22,7 +22,9 @@ define([
|
|||
var iter = new token_iterator.TokenIterator(input.getSession(), 0, 0);
|
||||
var ret = [];
|
||||
var t = iter.getCurrentToken();
|
||||
if (input.parser.isEmptyToken(t)) t = input.parser.nextNonEmptyToken(iter);
|
||||
if (input.parser.isEmptyToken(t)) {
|
||||
t = input.parser.nextNonEmptyToken(iter);
|
||||
}
|
||||
while (t) {
|
||||
ret.push({ value: t.value, type: t.type });
|
||||
t = input.parser.nextNonEmptyToken(iter);
|
||||
|
@ -34,10 +36,15 @@ define([
|
|||
var testCount = 0;
|
||||
|
||||
function token_test(token_list, prefix, data) {
|
||||
if (data && typeof data != "string") data = JSON.stringify(data, null, 3);
|
||||
if (data && typeof data != "string") {
|
||||
data = JSON.stringify(data, null, 3);
|
||||
}
|
||||
if (data) {
|
||||
if (prefix) data = prefix + "\n" + data;
|
||||
} else {
|
||||
if (prefix) {
|
||||
data = prefix + "\n" + data;
|
||||
}
|
||||
}
|
||||
else {
|
||||
data = prefix;
|
||||
}
|
||||
|
||||
|
@ -57,54 +64,54 @@ define([
|
|||
}
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.endpoint", "_search" ],
|
||||
[ "method", "GET", "url.part", "_search" ],
|
||||
"GET _search"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.slash", "/", "url.endpoint", "_search" ],
|
||||
[ "method", "GET", "url.slash", "/", "url.part", "_search" ],
|
||||
"GET /_search"
|
||||
);
|
||||
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.endpoint", "_cluster", "url.slash", "/", "url.part" , "nodes" ],
|
||||
[ "method", "GET", "url.part", "_cluster", "url.slash", "/", "url.part" , "nodes" ],
|
||||
"GET _cluster/nodes"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.slash", "/", "url.endpoint", "_cluster", "url.slash", "/", "url.part" , "nodes" ],
|
||||
[ "method", "GET", "url.slash", "/", "url.part", "_cluster", "url.slash", "/", "url.part" , "nodes" ],
|
||||
"GET /_cluster/nodes"
|
||||
);
|
||||
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.index", "index", "url.slash", "/", "url.endpoint", "_search" ],
|
||||
[ "method", "GET", "url.part", "index", "url.slash", "/", "url.part", "_search" ],
|
||||
"GET index/_search"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.index", "index" ],
|
||||
[ "method", "GET", "url.part", "index" ],
|
||||
"GET index"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.index", "index", "url.slash", "/", "url.type", "type" ],
|
||||
[ "method", "GET", "url.part", "index", "url.slash", "/", "url.part", "type" ],
|
||||
"GET index/type"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.slash", "/", "url.index", "index", "url.slash", "/", "url.type", "type", "url.slash", "/" ],
|
||||
[ "method", "GET", "url.slash", "/", "url.part", "index", "url.slash", "/", "url.part", "type", "url.slash", "/" ],
|
||||
"GET /index/type/"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.index", "index", "url.slash", "/", "url.type", "type", "url.slash", "/", "url.endpoint", "_search" ],
|
||||
[ "method", "GET", "url.part", "index", "url.slash", "/", "url.part", "type", "url.slash", "/", "url.part", "_search" ],
|
||||
"GET index/type/_search"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.index", "index", "url.slash", "/", "url.type", "type", "url.slash", "/", "url.endpoint", "_search",
|
||||
[ "method", "GET", "url.part", "index", "url.slash", "/", "url.part", "type", "url.slash", "/", "url.part", "_search",
|
||||
"url.questionmark", "?", "url.param", "value", "url.equal", "=", "url.value", "1"
|
||||
],
|
||||
"GET index/type/_search?value=1"
|
||||
|
@ -112,76 +119,76 @@ define([
|
|||
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.index", "index", "url.slash", "/", "url.type", "type", "url.slash", "/", "url.id", "1" ],
|
||||
[ "method", "GET", "url.part", "index", "url.slash", "/", "url.part", "type", "url.slash", "/", "url.part", "1" ],
|
||||
"GET index/type/1"
|
||||
);
|
||||
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.slash", "/", "url.index", "index1", "url.comma", ",", "url.index", "index2", "url.slash", "/" ],
|
||||
[ "method", "GET", "url.slash", "/", "url.part", "index1", "url.comma", ",", "url.part", "index2", "url.slash", "/" ],
|
||||
"GET /index1,index2/"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.slash", "/", "url.index", "index1", "url.comma", ",", "url.index", "index2", "url.slash", "/",
|
||||
"url.endpoint", "_search"],
|
||||
[ "method", "GET", "url.slash", "/", "url.part", "index1", "url.comma", ",", "url.part", "index2", "url.slash", "/",
|
||||
"url.part", "_search"],
|
||||
"GET /index1,index2/_search"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.index", "index1", "url.comma", ",", "url.index", "index2", "url.slash", "/",
|
||||
"url.endpoint", "_search"],
|
||||
[ "method", "GET", "url.part", "index1", "url.comma", ",", "url.part", "index2", "url.slash", "/",
|
||||
"url.part", "_search"],
|
||||
"GET index1,index2/_search"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.slash", "/", "url.index", "index1", "url.comma", ",", "url.index", "index2" ],
|
||||
[ "method", "GET", "url.slash", "/", "url.part", "index1", "url.comma", ",", "url.part", "index2" ],
|
||||
"GET /index1,index2"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.index", "index1", "url.comma", ",", "url.index", "index2" ],
|
||||
[ "method", "GET", "url.part", "index1", "url.comma", ",", "url.part", "index2" ],
|
||||
"GET index1,index2"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "GET", "url.slash", "/", "url.index", "index1", "url.comma", "," ],
|
||||
[ "method", "GET", "url.slash", "/", "url.part", "index1", "url.comma", "," ],
|
||||
"GET /index1,"
|
||||
);
|
||||
|
||||
|
||||
token_test(
|
||||
[ "method", "PUT", "url.slash", "/", "url.index", "index", "url.slash", "/" ],
|
||||
[ "method", "PUT", "url.slash", "/", "url.part", "index", "url.slash", "/" ],
|
||||
"PUT /index/"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "PUT", "url.slash", "/", "url.index", "index" ],
|
||||
[ "method", "PUT", "url.slash", "/", "url.part", "index" ],
|
||||
"PUT /index"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "PUT", "url.slash", "/", "url.index", "index1", "url.comma", ",", "url.index", "index2",
|
||||
"url.slash", "/", "url.type", "type1", "url.comma", ",", "url.type", "type2"],
|
||||
[ "method", "PUT", "url.slash", "/", "url.part", "index1", "url.comma", ",", "url.part", "index2",
|
||||
"url.slash", "/", "url.part", "type1", "url.comma", ",", "url.part", "type2"],
|
||||
"PUT /index1,index2/type1,type2"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "PUT", "url.slash", "/", "url.index", "index1",
|
||||
"url.slash", "/", "url.type", "type1", "url.comma", ",", "url.type", "type2", "url.comma", ","],
|
||||
[ "method", "PUT", "url.slash", "/", "url.part", "index1",
|
||||
"url.slash", "/", "url.part", "type1", "url.comma", ",", "url.part", "type2", "url.comma", ","],
|
||||
"PUT /index1/type1,type2,"
|
||||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "PUT", "url.index", "index1", "url.comma", ",", "url.index", "index2",
|
||||
"url.slash", "/", "url.type", "type1", "url.comma", ",", "url.type", "type2", "url.slash", "/",
|
||||
"url.id", "1234"],
|
||||
[ "method", "PUT", "url.part", "index1", "url.comma", ",", "url.part", "index2",
|
||||
"url.slash", "/", "url.part", "type1", "url.comma", ",", "url.part", "type2", "url.slash", "/",
|
||||
"url.part", "1234"],
|
||||
"PUT index1,index2/type1,type2/1234"
|
||||
);
|
||||
|
||||
|
||||
token_test(
|
||||
[ "method", "POST", "url.endpoint", "_search", "paren.lparen", "{", "variable", '"q"', "punctuation.colon", ":",
|
||||
[ "method", "POST", "url.part", "_search", "paren.lparen", "{", "variable", '"q"', "punctuation.colon", ":",
|
||||
"paren.lparen", "{", "paren.rparen", "}", "paren.rparen", "}"
|
||||
],
|
||||
'POST _search\n' +
|
||||
|
@ -192,8 +199,8 @@ define([
|
|||
);
|
||||
|
||||
token_test(
|
||||
[ "method", "POST", "url.endpoint", "_search", "paren.lparen", "{", "variable", '"q"', "punctuation.colon", ":",
|
||||
"paren.lparen", "{", "variable", '"s"', "punctuation.colon", ":", "paren.lparen", "{", "paren.rparen", "}",
|
||||
[ "method", "POST", "url.part", "_search", "paren.lparen", "{", "variable", '"q"', "punctuation.colon", ":",
|
||||
"paren.lparen", "{", "variable", '"s"', "punctuation.colon", ":", "paren.lparen", "{", "paren.rparen", "}",
|
||||
"paren.rparen", "}", "paren.rparen", "}"
|
||||
],
|
||||
'POST _search\n' +
|
||||
|
@ -214,10 +221,15 @@ define([
|
|||
|
||||
|
||||
function states_test(states_list, prefix, data) {
|
||||
if (data && typeof data != "string") data = JSON.stringify(data, null, 3);
|
||||
if (data && typeof data != "string") {
|
||||
data = JSON.stringify(data, null, 3);
|
||||
}
|
||||
if (data) {
|
||||
if (prefix) data = prefix + "\n" + data;
|
||||
} else {
|
||||
if (prefix) {
|
||||
data = prefix + "\n" + data;
|
||||
}
|
||||
}
|
||||
else {
|
||||
data = prefix;
|
||||
}
|
||||
|
||||
|
|
443
sense/tests/src/url_autocomplete_tests.js
Normal file
443
sense/tests/src/url_autocomplete_tests.js
Normal file
|
@ -0,0 +1,443 @@
|
|||
define([
|
||||
'_',
|
||||
'kb/url_pattern_matcher',
|
||||
'autocomplete/url_path_autocomplete'
|
||||
], function (_, url_pattern_matcher, url_path_autocomplete) {
|
||||
'use strict';
|
||||
|
||||
module("Url autocomplete");
|
||||
|
||||
function patterns_test(name, endpoints, tokenPath, expectedContext, globalUrlComponentFactories) {
|
||||
|
||||
test(name, function () {
|
||||
var patternMatcher = new url_pattern_matcher.UrlPatternMatcher(globalUrlComponentFactories);
|
||||
_.each(endpoints, function (e, id) {
|
||||
e.id = id;
|
||||
_.each(e.patterns, function (p) {
|
||||
patternMatcher.addEndpoint(p, e);
|
||||
});
|
||||
});
|
||||
if (typeof tokenPath === "string") {
|
||||
if (tokenPath[tokenPath.length - 1] == "$") {
|
||||
tokenPath = tokenPath.substr(0, tokenPath.length - 1) + "/" + url_pattern_matcher.URL_PATH_END_MARKER;
|
||||
}
|
||||
tokenPath = _.map(tokenPath.split("/"), function (p) {
|
||||
p = p.split(",");
|
||||
if (p.length === 1) {
|
||||
return p[0];
|
||||
}
|
||||
return p;
|
||||
});
|
||||
}
|
||||
|
||||
if (expectedContext.autoCompleteSet) {
|
||||
expectedContext.autoCompleteSet = _.map(expectedContext.autoCompleteSet, function (t) {
|
||||
if (_.isString(t)) {
|
||||
t = { name: t}
|
||||
}
|
||||
return t;
|
||||
});
|
||||
expectedContext.autoCompleteSet = _.sortBy(expectedContext.autoCompleteSet, 'name');
|
||||
}
|
||||
|
||||
var context = {};
|
||||
if (expectedContext.method) {
|
||||
context.method = expectedContext.method;
|
||||
}
|
||||
url_path_autocomplete.populateContext(tokenPath, context, null,
|
||||
expectedContext.autoCompleteSet, patternMatcher.getTopLevelComponents()
|
||||
);
|
||||
|
||||
// override context to just check on id
|
||||
if (context.endpoint) {
|
||||
context.endpoint = context.endpoint.id;
|
||||
}
|
||||
|
||||
if (context.autoCompleteSet) {
|
||||
context.autoCompleteSet = _.sortBy(context.autoCompleteSet, 'name');
|
||||
}
|
||||
|
||||
deepEqual(context, expectedContext);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
(function () {
|
||||
var endpoints = {
|
||||
"1": {
|
||||
patterns: [
|
||||
"a/b"
|
||||
]
|
||||
}
|
||||
};
|
||||
patterns_test("simple single path - completion",
|
||||
endpoints,
|
||||
"a/b$",
|
||||
{ endpoint: "1"}
|
||||
);
|
||||
|
||||
|
||||
patterns_test("simple single path - completion, with auto complete",
|
||||
endpoints,
|
||||
"a/b",
|
||||
{ autoCompleteSet: [] }
|
||||
);
|
||||
|
||||
patterns_test("simple single path - partial, without auto complete",
|
||||
endpoints,
|
||||
"a",
|
||||
{ }
|
||||
);
|
||||
|
||||
patterns_test("simple single path - partial, with auto complete",
|
||||
endpoints,
|
||||
"a",
|
||||
{ autoCompleteSet: ["b"] }
|
||||
);
|
||||
|
||||
patterns_test("simple single path - partial, with auto complete",
|
||||
endpoints,
|
||||
[],
|
||||
{ autoCompleteSet: ["a/b"] }
|
||||
);
|
||||
|
||||
patterns_test("simple single path - different path",
|
||||
endpoints,
|
||||
"a/c",
|
||||
{ }
|
||||
);
|
||||
|
||||
})();
|
||||
|
||||
(function () {
|
||||
var endpoints = {
|
||||
"1": {
|
||||
patterns: [
|
||||
"a/b",
|
||||
"a/b/{p}"
|
||||
]
|
||||
},
|
||||
"2": {
|
||||
patterns: [
|
||||
"a/c"
|
||||
]
|
||||
}
|
||||
};
|
||||
patterns_test("shared path - completion 1",
|
||||
endpoints,
|
||||
"a/b$",
|
||||
{ endpoint: "1"}
|
||||
);
|
||||
|
||||
patterns_test("shared path - completion 2",
|
||||
endpoints,
|
||||
"a/c$",
|
||||
{ endpoint: "2"}
|
||||
);
|
||||
|
||||
patterns_test("shared path - completion 1 with param",
|
||||
endpoints,
|
||||
"a/b/v$",
|
||||
{ endpoint: "1", p: "v"}
|
||||
);
|
||||
|
||||
patterns_test("shared path - partial, with auto complete",
|
||||
endpoints,
|
||||
"a",
|
||||
{ autoCompleteSet: ["b", "c"] }
|
||||
);
|
||||
|
||||
patterns_test("shared path - partial, with auto complete of param, no options",
|
||||
endpoints,
|
||||
"a/b",
|
||||
{ autoCompleteSet: [] }
|
||||
);
|
||||
|
||||
patterns_test("shared path - partial, without auto complete",
|
||||
endpoints,
|
||||
"a",
|
||||
{ }
|
||||
);
|
||||
|
||||
patterns_test("shared path - different path - with auto complete",
|
||||
endpoints,
|
||||
"a/e",
|
||||
{ autoCompleteSet: []}
|
||||
);
|
||||
|
||||
patterns_test("shared path - different path - without auto complete",
|
||||
endpoints,
|
||||
"a/e",
|
||||
{ }
|
||||
);
|
||||
|
||||
})();
|
||||
|
||||
(function () {
|
||||
var endpoints = {
|
||||
"1": {
|
||||
patterns: [
|
||||
"a/{p}",
|
||||
],
|
||||
url_components: {
|
||||
p: ["a", "b"]
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
patterns: [
|
||||
"a/c"
|
||||
]
|
||||
}
|
||||
};
|
||||
patterns_test("option testing - completion 1",
|
||||
endpoints,
|
||||
"a/a$",
|
||||
{ endpoint: "1", p: ["a"]}
|
||||
);
|
||||
|
||||
patterns_test("option testing - completion 2",
|
||||
endpoints,
|
||||
"a/b$",
|
||||
{ endpoint: "1", p: ["b"]}
|
||||
);
|
||||
|
||||
patterns_test("option testing - completion 3",
|
||||
endpoints,
|
||||
"a/b,a$",
|
||||
{ endpoint: "1", p: ["b", "a"]}
|
||||
);
|
||||
|
||||
patterns_test("option testing - completion 4",
|
||||
endpoints,
|
||||
"a/c$",
|
||||
{ endpoint: "2"}
|
||||
);
|
||||
|
||||
patterns_test("option testing - completion 5",
|
||||
endpoints,
|
||||
"a/d$",
|
||||
{ }
|
||||
);
|
||||
|
||||
patterns_test("option testing - partial, with auto complete",
|
||||
endpoints,
|
||||
"a",
|
||||
{ autoCompleteSet: ["a", "b", "c"] }
|
||||
);
|
||||
|
||||
patterns_test("option testing - partial, without auto complete",
|
||||
endpoints,
|
||||
"a",
|
||||
{ }
|
||||
);
|
||||
|
||||
|
||||
patterns_test("option testing - different path - with auto complete",
|
||||
endpoints,
|
||||
"a/e",
|
||||
{ autoCompleteSet: []}
|
||||
);
|
||||
|
||||
|
||||
})();
|
||||
|
||||
(function () {
|
||||
var endpoints = {
|
||||
"1": {
|
||||
patterns: [
|
||||
"a/{p}",
|
||||
],
|
||||
url_components: {
|
||||
p: ["a", "b"]
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
patterns: [
|
||||
"b/{p}",
|
||||
]
|
||||
}
|
||||
};
|
||||
var globalFactories = {
|
||||
"p": function (name, parent) {
|
||||
return new url_pattern_matcher.ListComponent(name, ["g1", "g2"], parent);
|
||||
}
|
||||
};
|
||||
|
||||
patterns_test("global parameters testing - completion 1",
|
||||
endpoints,
|
||||
"a/a$",
|
||||
{ endpoint: "1", p: ["a"]},
|
||||
globalFactories
|
||||
);
|
||||
|
||||
patterns_test("global parameters testing - completion 2",
|
||||
endpoints,
|
||||
"b/g1$",
|
||||
{ endpoint: "2", p: ["g1"]},
|
||||
globalFactories
|
||||
);
|
||||
|
||||
|
||||
patterns_test("global parameters testing - partial, with auto complete",
|
||||
endpoints,
|
||||
"a",
|
||||
{ autoCompleteSet: ["a", "b"] },
|
||||
globalFactories
|
||||
);
|
||||
|
||||
patterns_test("global parameters testing - partial, with auto complete 2",
|
||||
endpoints,
|
||||
"b",
|
||||
{ autoCompleteSet: ["g1", "g2"] },
|
||||
globalFactories
|
||||
);
|
||||
|
||||
})();
|
||||
|
||||
(function () {
|
||||
var endpoints = {
|
||||
"1": {
|
||||
patterns: [
|
||||
"a/b/{p}/c/e"
|
||||
]
|
||||
}
|
||||
};
|
||||
patterns_test("look ahead - autocomplete before param 1",
|
||||
endpoints,
|
||||
"a",
|
||||
{ autoCompleteSet: [ "b" ]}
|
||||
);
|
||||
|
||||
patterns_test("look ahead - autocomplete before param 2",
|
||||
endpoints,
|
||||
[],
|
||||
{ autoCompleteSet: [ "a/b" ]}
|
||||
);
|
||||
|
||||
patterns_test("look ahead - autocomplete after param 1",
|
||||
endpoints,
|
||||
"a/b/v",
|
||||
{ autoCompleteSet: [ "c/e" ], "p": "v"}
|
||||
);
|
||||
|
||||
patterns_test("look ahead - autocomplete after param 2",
|
||||
endpoints,
|
||||
"a/b/v/c",
|
||||
{ autoCompleteSet: [ "e" ], "p": "v"}
|
||||
);
|
||||
})();
|
||||
|
||||
|
||||
(function () {
|
||||
var endpoints = {
|
||||
"1_param": {
|
||||
patterns: [
|
||||
"a/{p}"
|
||||
],
|
||||
methods: ["GET"]
|
||||
},
|
||||
"2_explicit": {
|
||||
patterns: [
|
||||
"a/b"
|
||||
],
|
||||
methods: ["GET"]
|
||||
}};
|
||||
|
||||
var e = _.cloneDeep(endpoints);
|
||||
e["1_param"].priority = 1;
|
||||
patterns_test("Competing endpoints - priority 1",
|
||||
e,
|
||||
"a/b$",
|
||||
{ method: "GET", endpoint: "1_param", "p": "b"}
|
||||
);
|
||||
e = _.cloneDeep(endpoints);
|
||||
e["1_param"].priority = 1;
|
||||
e["2_explicit"].priority = 0;
|
||||
patterns_test("Competing endpoints - priority 2",
|
||||
e,
|
||||
"a/b$",
|
||||
{ method: "GET", endpoint: "2_explicit"}
|
||||
);
|
||||
|
||||
e = _.cloneDeep(endpoints);
|
||||
e["2_explicit"].priority = 0;
|
||||
patterns_test("Competing endpoints - priority 3",
|
||||
e,
|
||||
"a/b$",
|
||||
{ method: "GET", endpoint: "2_explicit"}
|
||||
);
|
||||
|
||||
})();
|
||||
|
||||
(function () {
|
||||
var endpoints = {
|
||||
"1_GET": {
|
||||
patterns: [
|
||||
"a"
|
||||
],
|
||||
methods: ["GET"]
|
||||
},
|
||||
"1_PUT": {
|
||||
patterns: [
|
||||
"a"
|
||||
],
|
||||
methods: ["PUT"]
|
||||
},
|
||||
"2_GET": {
|
||||
patterns: [
|
||||
"a/b"
|
||||
],
|
||||
methods: ["GET"]
|
||||
},
|
||||
"2_DELETE": {
|
||||
patterns: [
|
||||
"a/b"
|
||||
],
|
||||
methods: ["DELETE"]
|
||||
}
|
||||
};
|
||||
patterns_test("Competing endpoint - sub url of another - auto complete",
|
||||
endpoints,
|
||||
"a",
|
||||
{ method: "GET", autoCompleteSet: [ "b" ]}
|
||||
);
|
||||
patterns_test("Competing endpoint - sub url of another, complete 1",
|
||||
endpoints,
|
||||
"a$",
|
||||
{ method: "GET", endpoint: "1_GET"}
|
||||
);
|
||||
patterns_test("Competing endpoint - sub url of another, complete 2",
|
||||
endpoints,
|
||||
"a$",
|
||||
{ method: "PUT", endpoint: "1_PUT"}
|
||||
);
|
||||
patterns_test("Competing endpoint - sub url of another, complete 3",
|
||||
endpoints,
|
||||
"a$",
|
||||
{ method: "DELETE" }
|
||||
);
|
||||
|
||||
patterns_test("Competing endpoint - extention of another, complete 1, auto complete",
|
||||
endpoints,
|
||||
"a/b$",
|
||||
{ method: "PUT", autoCompleteSet: []}
|
||||
);
|
||||
|
||||
patterns_test("Competing endpoint - extention of another, complete 1",
|
||||
endpoints,
|
||||
"a/b$",
|
||||
{ method: "GET", endpoint: "2_GET"}
|
||||
);
|
||||
|
||||
patterns_test("Competing endpoint - extention of another, complete 1",
|
||||
endpoints,
|
||||
"a/b$",
|
||||
{ method: "DELETE", endpoint: "2_DELETE"}
|
||||
);
|
||||
patterns_test("Competing endpoint - extention of another, complete 1",
|
||||
endpoints,
|
||||
"a/b$",
|
||||
{ method: "PUT"}
|
||||
);
|
||||
})();
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue