1
0
Fork 0

Merge branch 'devel' of https://github.com/arangodb/arangodb into devel

This commit is contained in:
Jan Steemann 2015-06-03 14:57:27 +02:00
commit 7426e9908d
12 changed files with 1844 additions and 1832 deletions

View File

@ -5,6 +5,9 @@ The ArangoDB server can listen for incoming requests on multiple *endpoints*.
The endpoints are normally specified either in ArangoDB's configuration file or on The endpoints are normally specified either in ArangoDB's configuration file or on
the command-line, using the ["--server.endpoint"](../ConfigureArango/Arangod.md) option. the command-line, using the ["--server.endpoint"](../ConfigureArango/Arangod.md) option.
The default endpoint for ArangoDB is *tcp://127.0.0.1:8529* or *tcp://localhost:8529*. The default endpoint for ArangoDB is *tcp://127.0.0.1:8529* or *tcp://localhost:8529*.
ArangoDB can also do a so called *broadcast bind* using *tcp://0.0.0.0:8529*. This way
it will be reachable on all interfaces of the host. This may be useful
on development systems that frequently change their network setup like laptops.
The number of endpoints can also be changed at runtime using the API described The number of endpoints can also be changed at runtime using the API described
below. Each endpoint can optionally be restricted to a specific list of databases below. Each endpoint can optionally be restricted to a specific list of databases
@ -14,6 +17,23 @@ This may be useful in multi-tenant setups.
A multi-endpoint setup may also be useful to turn on encrypted communication for A multi-endpoint setup may also be useful to turn on encrypted communication for
just specific databases. just specific databases.
Endpoints equal TCP ports to be bound. On one specific ethernet interface each port
can only be bound **exactly once**. You can look up your available interfaces using
the *ifconfig* command on Linux / MacOSX - the Windows equivalent is *ipconfig*
([See Wikipedia for more details](http://en.wikipedia.org/wiki/Ifconfig)).
The general names of the interfaces differ on OS's and hardwares they run on.
However, typically every host has a so called
[loopback interface](http://en.wikipedia.org/wiki/Loop_device), which is a
virtual interface. By convention it always has the address *127.0.0.1* or *::1* (ipv6),
and can only be reached from exactly the very same host.
Ethernet interfaces usually have names like *eth0*, *wlan0*, *eth1:17*, *le0* or
a plain text name in Windows.
To find out which services already use ports (so ArangoDB can't bind them anymore),
you can use the [netstat command](http://en.wikipedia.org/wiki/Netstat)
(it behaves a little different on each platform, run it with *-lnpt* on Linux, *-p tcp*
on MacOSX or with *-an* on windows for valuable information).
The JavaScript interface for endpoints provides operations to add new endpoints at The JavaScript interface for endpoints provides operations to add new endpoints at
runtime, and optionally restrict them for use with specific databases. The interface runtime, and optionally restrict them for use with specific databases. The interface
also can be used to update existing endpoints or remove them at runtime. also can be used to update existing endpoints or remove them at runtime.

View File

@ -12,5 +12,8 @@
"top": 35, "top": 35,
"bottom": 35 "bottom": 35
} }
},
"styles": {
"website": "styles/website.css"
} }
} }

View File

@ -0,0 +1 @@
div.example_show_button { border: medium solid lightgray; text-align: center; position: relative; top: -10px; } .book .book-body .navigation.navigation-next { right: 10px !important; } .book .book-summary ul.summary li.active>a,.book .book-summary ul.summary li a:hover { color: #000 !important; background: #80A54D !important; text-decoration: none; } .book .book-body .page-wrapper .page-inner section.normal .deprecated{ background-color: rgba(240,240,0,0.4); } .gsib_a { padding: 0px !important; } .gsc-control-cse { border: 0px !important; background-color: transparent !important; } .gsc-input { margin: 0px !important; }

View File

@ -1993,16 +1993,10 @@ int TRI_StartServer (TRI_server_t* server,
if (server->_appPath != nullptr && if (server->_appPath != nullptr &&
strlen(server->_appPath) > 0 && strlen(server->_appPath) > 0 &&
! TRI_IsDirectory(server->_appPath)) { ! TRI_IsDirectory(server->_appPath)) {
if (! performUpgrade) {
LOG_ERROR("specified --javascript.app-path directory '%s' does not exist. "
"Please start again with --upgrade option to create it.",
server->_appPath);
return TRI_ERROR_BAD_PARAMETER;
}
long systemError; long systemError;
std::string errorMessage; std::string errorMessage;
res = TRI_CreateDirectory(server->_appPath, systemError, errorMessage); int res = TRI_CreateRecursiveDirectory(server->_appPath, systemError, errorMessage);
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
LOG_ERROR("unable to create --javascript.app-path directory '%s': %s", LOG_ERROR("unable to create --javascript.app-path directory '%s': %s",
@ -2010,6 +2004,10 @@ int TRI_StartServer (TRI_server_t* server,
errorMessage.c_str()); errorMessage.c_str());
return res; return res;
} }
else {
LOG_INFO("created --javascript.app-path directory '%s'.",
server->_appPath);
}
} }
// create subdirectories if not yet present // create subdirectories if not yet present

View File

@ -28,6 +28,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "LogfileManager.h" #include "LogfileManager.h"
#include "Basics/files.h"
#include "Basics/hashes.h" #include "Basics/hashes.h"
#include "Basics/json.h" #include "Basics/json.h"
#include "Basics/logging.h" #include "Basics/logging.h"
@ -266,7 +267,18 @@ bool LogfileManager::prepare () {
_directory = (*_databasePath); _directory = (*_databasePath);
if (! basics::FileUtils::isDirectory(_directory)) { if (! basics::FileUtils::isDirectory(_directory)) {
LOG_FATAL_AND_EXIT("database directory '%s' does not exist.", _directory.c_str()); std::string systemErrorStr;
long errorNo;
int res = TRI_CreateRecursiveDirectory(_directory.c_str(), errorNo, systemErrorStr);
if (res != TRI_ERROR_NO_ERROR) {
LOG_FATAL_AND_EXIT("unable to create database directory: %s",
systemErrorStr.c_str());
}
else {
LOG_INFO("created database directory '%s'.",
_directory.c_str());
}
} }
// append "/journals" // append "/journals"

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/*jslint continue:true */ 'use strict';
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Foxx application store /// @brief Foxx application store
@ -27,26 +27,23 @@
/// @author Copyright 2015, triAGENS GmbH, Cologne, Germany /// @author Copyright 2015, triAGENS GmbH, Cologne, Germany
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
(function() {
'use strict';
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- global variables // --SECTION-- global variables
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
var checkedFishBowl = false; var checkedFishBowl = false;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- imports // --SECTION-- imports
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
var arangodb = require("org/arangodb"); var arangodb = require("org/arangodb");
var db = arangodb.db; var db = arangodb.db;
var download = require("internal").download; var download = require("internal").download;
var fs = require("fs"); var fs = require("fs");
var throwDownloadError = arangodb.throwDownloadError; var throwDownloadError = arangodb.throwDownloadError;
var utils = require("org/arangodb/foxx/manager-utils"); var utils = require("org/arangodb/foxx/manager-utils");
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private functions // --SECTION-- private functions
@ -56,9 +53,9 @@
/// @brief returns the fishbowl repository /// @brief returns the fishbowl repository
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function getFishbowlUrl () { function getFishbowlUrl () {
return "arangodb/foxx-apps"; return "arangodb/foxx-apps";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief returns the fishbowl collection /// @brief returns the fishbowl collection
@ -68,190 +65,190 @@
/// used in context of the database. /// used in context of the database.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var getFishbowlStorage = function() { var getFishbowlStorage = function() {
var c = db._collection('_fishbowl'); var c = db._collection('_fishbowl');
if (c === null) { if (c === null) {
c = db._create('_fishbowl', { isSystem : true }); c = db._create('_fishbowl', { isSystem : true });
} }
if (c !== null && ! checkedFishBowl) { if (c !== null && ! checkedFishBowl) {
// ensure indexes // ensure indexes
c.ensureFulltextIndex("description"); c.ensureFulltextIndex("description");
c.ensureFulltextIndex("name"); c.ensureFulltextIndex("name");
checkedFishBowl = true; checkedFishBowl = true;
} }
return c; return c;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief comparator for applications /// @brief comparator for applications
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var compareApps = function(l, r) { var compareApps = function(l, r) {
var left = l.name.toLowerCase(); var left = l.name.toLowerCase();
var right = r.name.toLowerCase(); var right = r.name.toLowerCase();
if (left < right) { if (left < right) {
return -1; return -1;
} }
if (right < left) { if (right < left) {
return 1; return 1;
} }
return 0; return 0;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief comparator for versions /// @brief comparator for versions
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var compareVersions = function (a, b) { var compareVersions = function (a, b) {
var i; var i;
if (a === b) { if (a === b) {
return 0;
}
// error handling
if (typeof a !== "string") {
return -1;
}
if (typeof b !== "string") {
return 1;
}
var aComponents = a.split(".");
var bComponents = b.split(".");
var len = Math.min(aComponents.length, bComponents.length);
// loop while the components are equal
for (i = 0; i < len; i++) {
// A bigger than B
if (parseInt(aComponents[i], 10) > parseInt(bComponents[i], 10)) {
return 1;
}
// B bigger than A
if (parseInt(aComponents[i], 10) < parseInt(bComponents[i], 10)) {
return -1;
}
}
// If one's a prefix of the other, the longer one is bigger one.
if (aComponents.length > bComponents.length) {
return 1;
}
if (aComponents.length < bComponents.length) {
return -1;
}
// Otherwise they are the same.
return 0; return 0;
}; }
// error handling
if (typeof a !== "string") {
return -1;
}
if (typeof b !== "string") {
return 1;
}
var aComponents = a.split(".");
var bComponents = b.split(".");
var len = Math.min(aComponents.length, bComponents.length);
// loop while the components are equal
for (i = 0; i < len; i++) {
// A bigger than B
if (parseInt(aComponents[i], 10) > parseInt(bComponents[i], 10)) {
return 1;
}
// B bigger than A
if (parseInt(aComponents[i], 10) < parseInt(bComponents[i], 10)) {
return -1;
}
}
// If one's a prefix of the other, the longer one is bigger one.
if (aComponents.length > bComponents.length) {
return 1;
}
if (aComponents.length < bComponents.length) {
return -1;
}
// Otherwise they are the same.
return 0;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief updates the fishbowl from a zip archive /// @brief updates the fishbowl from a zip archive
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var updateFishbowlFromZip = function(filename) { var updateFishbowlFromZip = function(filename) {
var i; var i;
var tempPath = fs.getTempPath(); var tempPath = fs.getTempPath();
var toSave = [ ]; var toSave = [ ];
try { try {
fs.makeDirectoryRecursive(tempPath); fs.makeDirectoryRecursive(tempPath);
var root = fs.join(tempPath, "foxx-apps-master/applications"); var root = fs.join(tempPath, "foxx-apps-master/applications");
// remove any previous files in the directory
fs.listTree(root).forEach(function (file) {
if (file.match(/\.json$/)) {
try {
fs.remove(fs.join(root, file));
}
catch (ignore) {
}
}
});
fs.unzipFile(filename, tempPath, false, true);
if (! fs.exists(root)) {
throw new Error("'applications' directory is missing in foxx-apps-master, giving up");
}
var m = fs.listTree(root);
var reSub = /(.*)\.json$/;
var f, match, app, desc;
for (i = 0; i < m.length; ++i) {
f = m[i];
match = reSub.exec(f);
if (match === null) {
continue;
}
app = fs.join(root, f);
// remove any previous files in the directory
fs.listTree(root).forEach(function (file) {
if (file.match(/\.json$/)) {
try { try {
desc = JSON.parse(fs.read(app)); fs.remove(fs.join(root, file));
}
catch (err1) {
arangodb.printf("Cannot parse description for app '" + f + "': %s\n", String(err1));
continue;
}
desc._key = match[1];
if (! desc.hasOwnProperty("name")) {
desc.name = match[1];
}
toSave.push(desc);
}
if (toSave.length > 0) {
var fishbowl = getFishbowlStorage();
db._executeTransaction({
collections: {
write: fishbowl.name()
},
action: function (params) {
var c = require("internal").db._collection(params.collection);
c.truncate();
params.apps.forEach(function(app) {
c.save(app);
});
},
params: {
apps: toSave,
collection: fishbowl.name()
}
});
arangodb.printf("Updated local repository information with %d application(s)\n",
toSave.length);
}
}
catch (err) {
if (tempPath !== undefined && tempPath !== "") {
try {
fs.removeDirectoryRecursive(tempPath);
} }
catch (ignore) { catch (ignore) {
} }
} }
});
throw err; fs.unzipFile(filename, tempPath, false, true);
if (! fs.exists(root)) {
throw new Error("'applications' directory is missing in foxx-apps-master, giving up");
} }
};
var m = fs.listTree(root);
var reSub = /(.*)\.json$/;
var f, match, app, desc;
for (i = 0; i < m.length; ++i) {
f = m[i];
match = reSub.exec(f);
if (match === null) {
continue;
}
app = fs.join(root, f);
try {
desc = JSON.parse(fs.read(app));
}
catch (err1) {
arangodb.printf("Cannot parse description for app '" + f + "': %s\n", String(err1));
continue;
}
desc._key = match[1];
if (! desc.hasOwnProperty("name")) {
desc.name = match[1];
}
toSave.push(desc);
}
if (toSave.length > 0) {
var fishbowl = getFishbowlStorage();
db._executeTransaction({
collections: {
write: fishbowl.name()
},
action: function (params) {
var c = require("internal").db._collection(params.collection);
c.truncate();
params.apps.forEach(function(app) {
c.save(app);
});
},
params: {
apps: toSave,
collection: fishbowl.name()
}
});
arangodb.printf("Updated local repository information with %d application(s)\n",
toSave.length);
}
}
catch (err) {
if (tempPath !== undefined && tempPath !== "") {
try {
fs.removeDirectoryRecursive(tempPath);
}
catch (ignore) {
}
}
throw err;
}
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- public functions // --SECTION-- public functions
@ -261,87 +258,87 @@
/// @brief returns the search result for FOXX applications /// @brief returns the search result for FOXX applications
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var searchJson = function (name) { var searchJson = function (name) {
var fishbowl = getFishbowlStorage(); var fishbowl = getFishbowlStorage();
if (fishbowl.count() === 0) { if (fishbowl.count() === 0) {
arangodb.print("Repository is empty, please use 'update'"); arangodb.print("Repository is empty, please use 'update'");
return []; return [];
}
var docs;
if (name === undefined || (typeof name === "string" && name.length === 0)) {
docs = fishbowl.toArray();
}
else {
name = name.replace(/[^a-zA-Z0-9]/g, ' ');
// get results by looking in "description" attribute
docs = fishbowl.fulltext("description", "prefix:" + name).toArray();
// build a hash of keys
var i;
var keys = { };
for (i = 0; i < docs.length; ++i) {
keys[docs[i]._key] = 1;
} }
var docs; // get results by looking in "name" attribute
var docs2= fishbowl.fulltext("name", "prefix:" + name).toArray();
if (name === undefined || (typeof name === "string" && name.length === 0)) { // merge the two result sets, avoiding duplicates
docs = fishbowl.toArray(); for (i = 0; i < docs2.length; ++i) {
} if (!keys.hasOwnProperty(docs2[i]._key)) {
else { docs.push(docs2[i]);
name = name.replace(/[^a-zA-Z0-9]/g, ' ');
// get results by looking in "description" attribute
docs = fishbowl.fulltext("description", "prefix:" + name).toArray();
// build a hash of keys
var i;
var keys = { };
for (i = 0; i < docs.length; ++i) {
keys[docs[i]._key] = 1;
} }
// get results by looking in "name" attribute
var docs2= fishbowl.fulltext("name", "prefix:" + name).toArray();
// merge the two result sets, avoiding duplicates
for (i = 0; i < docs2.length; ++i) {
if (!keys.hasOwnProperty(docs2[i]._key)) {
docs.push(docs2[i]);
}
}
} }
}
return docs; return docs;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief searchs for an available FOXX applications /// @brief searchs for an available FOXX applications
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var search = function (name) { var search = function (name) {
var docs = searchJson(name); var docs = searchJson(name);
arangodb.printTable( arangodb.printTable(
docs.sort(compareApps), docs.sort(compareApps),
[ "name", "author", "description" ], [ "name", "author", "description" ],
{ {
prettyStrings: true, prettyStrings: true,
totalString: "%s application(s) found", totalString: "%s application(s) found",
emptyString: "no applications found", emptyString: "no applications found",
rename: { rename: {
name : "Name", name : "Name",
author : "Author", author : "Author",
description : "Description" description : "Description"
}
} }
); }
}; );
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief extracts the highest version number from the document /// @brief extracts the highest version number from the document
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function extractMaxVersion (versionDoc) { function extractMaxVersion (versionDoc) {
var maxVersion = "-"; var maxVersion = "-";
var versions = Object.keys(versionDoc); var versions = Object.keys(versionDoc);
versions.sort(compareVersions); versions.sort(compareVersions);
if (versions.length > 0) { if (versions.length > 0) {
versions.reverse(); versions.reverse();
maxVersion = versions[0]; maxVersion = versions[0];
} }
return maxVersion; return maxVersion;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -349,26 +346,26 @@ function extractMaxVersion (versionDoc) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function availableJson() { function availableJson() {
var fishbowl = getFishbowlStorage(); var fishbowl = getFishbowlStorage();
var cursor = fishbowl.all(); var cursor = fishbowl.all();
var result = []; var result = [];
var doc, maxVersion, res; var doc, maxVersion, res;
while (cursor.hasNext()) { while (cursor.hasNext()) {
doc = cursor.next(); doc = cursor.next();
maxVersion = extractMaxVersion(doc.versions); maxVersion = extractMaxVersion(doc.versions);
res = { res = {
name: doc.name, name: doc.name,
description: doc.description || "", description: doc.description || "",
author: doc.author || "", author: doc.author || "",
latestVersion: maxVersion latestVersion: maxVersion
}; };
result.push(res); result.push(res);
} }
return result; return result;
} }
@ -379,181 +376,179 @@ function availableJson() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var update = function() { var update = function() {
var url = utils.buildGithubUrl(getFishbowlUrl()); var url = utils.buildGithubUrl(getFishbowlUrl());
var filename = fs.getTempFile("downloads", false); var filename = fs.getTempFile("downloads", false);
var path = fs.getTempFile("zip", false); var path = fs.getTempFile("zip", false);
try {
var result = download(url, "", {
method: "get",
followRedirects: true,
timeout: 30
}, filename);
if (result.code < 200 || result.code > 299) {
throwDownloadError("Github download from '" + url + "' failed with error code " + result.code);
}
updateFishbowlFromZip(filename);
filename = undefined;
}
catch (err) {
if (filename !== undefined && fs.exists(filename)) {
fs.remove(filename);
}
try { try {
var result = download(url, "", { fs.removeDirectoryRecursive(path);
method: "get",
followRedirects: true,
timeout: 30
}, filename);
if (result.code < 200 || result.code > 299) {
throwDownloadError("Github download from '" + url + "' failed with error code " + result.code);
}
updateFishbowlFromZip(filename);
filename = undefined;
} }
catch (err) { catch (ignore) {
if (filename !== undefined && fs.exists(filename)) {
fs.remove(filename);
}
try {
fs.removeDirectoryRecursive(path);
}
catch (ignore) {
}
throw err;
} }
};
throw err;
}
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief prints all available FOXX applications /// @brief prints all available FOXX applications
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var available = function () { var available = function () {
var list = availableJson(); var list = availableJson();
arangodb.printTable( arangodb.printTable(
list.sort(compareApps), list.sort(compareApps),
[ "name", "author", "description", "latestVersion" ], [ "name", "author", "description", "latestVersion" ],
{ {
prettyStrings: true, prettyStrings: true,
totalString: "%s application(s) found", totalString: "%s application(s) found",
emptyString: "no applications found, please use 'update'", emptyString: "no applications found, please use 'update'",
rename: { rename: {
"name" : "Name", "name" : "Name",
"author" : "Author", "author" : "Author",
"description" : "Description", "description" : "Description",
"latestVersion" : "Latest Version" "latestVersion" : "Latest Version"
}
} }
); }
}; );
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief gets json-info for an available FOXX application /// @brief gets json-info for an available FOXX application
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var infoJson = function (name) { var infoJson = function (name) {
utils.validateAppName(name); utils.validateAppName(name);
var fishbowl = getFishbowlStorage(); var fishbowl = getFishbowlStorage();
if (fishbowl.count() === 0) { if (fishbowl.count() === 0) {
arangodb.print("Repository is empty, please use 'update'"); arangodb.print("Repository is empty, please use 'update'");
return; return;
} }
var desc; var desc;
try { try {
desc = fishbowl.document(name); desc = fishbowl.document(name);
return desc; return desc;
} }
catch (err) { catch (err) {
arangodb.print("No application '" + name + "' available, please try 'search'"); arangodb.print("No application '" + name + "' available, please try 'search'");
return; return;
} }
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create a download URL for the given app information /// @brief create a download URL for the given app information
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var buildUrl = function(appInfo) { var buildUrl = function(appInfo) {
// TODO Validate // TODO Validate
var infoSplit = appInfo.split(":"); var infoSplit = appInfo.split(":");
var name = infoSplit[0]; var name = infoSplit[0];
var version = infoSplit[1]; var version = infoSplit[1];
var storeInfo = infoJson(name); var storeInfo = infoJson(name);
if (storeInfo === undefined) { if (storeInfo === undefined) {
throw "Application not found"; throw "Application not found";
}
var versions = storeInfo.versions;
var versionInfo;
if (version === undefined) {
versionInfo = versions[extractMaxVersion(versions)];
} else {
if (!versions.hasOwnProperty(version)) {
throw "Unknown version";
} }
var versions = storeInfo.versions; versionInfo = versions[version];
var versionInfo; }
if (version === undefined) { return utils.buildGithubUrl(versionInfo.location, versionInfo.tag);
versionInfo = versions[extractMaxVersion(versions)]; };
} else {
if (!versions.hasOwnProperty(version)) {
throw "Unknown version";
}
versionInfo = versions[version];
}
return utils.buildGithubUrl(versionInfo.location, versionInfo.tag);
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief prints info for an available FOXX application /// @brief prints info for an available FOXX application
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
var info = function (name) { var info = function (name) {
var desc = infoJson(name); var desc = infoJson(name);
arangodb.printf("Name: %s\n", desc.name); arangodb.printf("Name: %s\n", desc.name);
if (desc.hasOwnProperty('author')) { if (desc.hasOwnProperty('author')) {
arangodb.printf("Author: %s\n", desc.author); arangodb.printf("Author: %s\n", desc.author);
}
var isSystem = desc.hasOwnProperty('isSystem') && desc.isSystem;
arangodb.printf("System: %s\n", JSON.stringify(isSystem));
if (desc.hasOwnProperty('description')) {
arangodb.printf("Description: %s\n\n", desc.description);
}
var header = false;
var versions = Object.keys(desc.versions);
versions.sort(compareVersions);
versions.forEach(function (v) {
var version = desc.versions[v];
if (! header) {
arangodb.print("Versions:");
header = true;
} }
var isSystem = desc.hasOwnProperty('isSystem') && desc.isSystem; if (version.type === "github") {
arangodb.printf("System: %s\n", JSON.stringify(isSystem)); if (version.hasOwnProperty("tag")) {
arangodb.printf('%s: fetch github "%s" "%s"\n', v, version.location, version.tag);
if (desc.hasOwnProperty('description')) { }
arangodb.printf("Description: %s\n\n", desc.description); else if (v.hasOwnProperty("branch")) {
arangodb.printf('%s: fetch github "%s" "%s"\n', v, version.location, version.branch);
}
else {
arangodb.printf('%s: fetch "github" "%s"\n', v, version.location);
}
} }
});
var header = false; arangodb.printf("\n");
var versions = Object.keys(desc.versions); };
versions.sort(compareVersions);
versions.forEach(function (v) {
var version = desc.versions[v];
if (! header) {
arangodb.print("Versions:");
header = true;
}
if (version.type === "github") {
if (version.hasOwnProperty("tag")) {
arangodb.printf('%s: fetch github "%s" "%s"\n', v, version.location, version.tag);
}
else if (v.hasOwnProperty("branch")) {
arangodb.printf('%s: fetch github "%s" "%s"\n', v, version.location, version.branch);
}
else {
arangodb.printf('%s: fetch "github" "%s"\n', v, version.location);
}
}
});
arangodb.printf("\n");
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- export public API // --SECTION-- export public API
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
exports.available = available; exports.available = available;
exports.availableJson = availableJson; exports.availableJson = availableJson;
exports.buildUrl = buildUrl; exports.buildUrl = buildUrl;
exports.getFishbowlStorage = getFishbowlStorage; exports.getFishbowlStorage = getFishbowlStorage;
exports.info = info; exports.info = info;
exports.search = search; exports.search = search;
exports.searchJson = searchJson; exports.searchJson = searchJson;
exports.update = update; exports.update = update;
// Temporary export to avoid breaking the client // Temporary export to avoid breaking the client
exports.compareVersions = compareVersions; exports.compareVersions = compareVersions;
}());
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE // --SECTION-- END-OF-FILE

View File

@ -1,4 +1,4 @@
/*jshint strict: false */ 'use strict';
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Graph Data for Example /// @brief Graph Data for Example
@ -26,92 +26,90 @@
/// @author Michael Hackstein /// @author Michael Hackstein
/// @author Copyright 2011-2014, triAGENS GmbH, Cologne, Germany /// @author Copyright 2011-2014, triAGENS GmbH, Cologne, Germany
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
(function() {
var Graph = require("org/arangodb/general-graph"); var Graph = require("org/arangodb/general-graph");
var createTraversalExample = function() { var createTraversalExample = function() {
var g = Graph._create("knows_graph", var g = Graph._create("knows_graph",
[Graph._relation("knows", "persons", "persons")] [Graph._relation("knows", "persons", "persons")]
); );
var a = g.persons.save({name: "Alice", _key: "alice"})._id; var a = g.persons.save({name: "Alice", _key: "alice"})._id;
var b = g.persons.save({name: "Bob", _key: "bob"})._id; var b = g.persons.save({name: "Bob", _key: "bob"})._id;
var c = g.persons.save({name: "Charlie", _key: "charlie"})._id; var c = g.persons.save({name: "Charlie", _key: "charlie"})._id;
var d = g.persons.save({name: "Dave", _key: "dave"})._id; var d = g.persons.save({name: "Dave", _key: "dave"})._id;
var e = g.persons.save({name: "Eve", _key: "eve"})._id; var e = g.persons.save({name: "Eve", _key: "eve"})._id;
g.knows.save(a, b, {}); g.knows.save(a, b, {});
g.knows.save(b, c, {}); g.knows.save(b, c, {});
g.knows.save(b, d, {}); g.knows.save(b, d, {});
g.knows.save(e, a, {}); g.knows.save(e, a, {});
g.knows.save(e, b, {}); g.knows.save(e, b, {});
return g; return g;
}; };
var createSocialGraph = function() { var createSocialGraph = function() {
var edgeDefinition = []; var edgeDefinition = [];
edgeDefinition.push(Graph._relation("relation", ["female", "male"], ["female", "male"])); edgeDefinition.push(Graph._relation("relation", ["female", "male"], ["female", "male"]));
var g = Graph._create("social", edgeDefinition); var g = Graph._create("social", edgeDefinition);
var a = g.female.save({name: "Alice", _key: "alice"}); var a = g.female.save({name: "Alice", _key: "alice"});
var b = g.male.save({name: "Bob", _key: "bob"}); var b = g.male.save({name: "Bob", _key: "bob"});
var c = g.male.save({name: "Charly", _key: "charly"}); var c = g.male.save({name: "Charly", _key: "charly"});
var d = g.female.save({name: "Diana", _key: "diana"}); var d = g.female.save({name: "Diana", _key: "diana"});
g.relation.save(a._id, b._id, {type: "married", _key: "aliceAndBob"}); g.relation.save(a._id, b._id, {type: "married", _key: "aliceAndBob"});
g.relation.save(a._id, c._id, {type: "friend", _key: "aliceAndCharly"}); g.relation.save(a._id, c._id, {type: "friend", _key: "aliceAndCharly"});
g.relation.save(c._id, d._id, {type: "married", _key: "charlyAndDiana"}); g.relation.save(c._id, d._id, {type: "married", _key: "charlyAndDiana"});
g.relation.save(b._id, d._id, {type: "friend", _key: "bobAndDiana"}); g.relation.save(b._id, d._id, {type: "friend", _key: "bobAndDiana"});
return g; return g;
}; };
var createRoutePlannerGraph = function() { var createRoutePlannerGraph = function() {
var edgeDefinition = []; var edgeDefinition = [];
edgeDefinition.push(Graph._relation( edgeDefinition.push(Graph._relation(
"germanHighway", ["germanCity"], ["germanCity"]) "germanHighway", ["germanCity"], ["germanCity"])
); );
edgeDefinition.push( edgeDefinition.push(
Graph._relation("frenchHighway", ["frenchCity"], ["frenchCity"]) Graph._relation("frenchHighway", ["frenchCity"], ["frenchCity"])
); );
edgeDefinition.push(Graph._relation( edgeDefinition.push(Graph._relation(
"internationalHighway", ["frenchCity", "germanCity"], ["frenchCity", "germanCity"]) "internationalHighway", ["frenchCity", "germanCity"], ["frenchCity", "germanCity"])
); );
var g = Graph._create("routeplanner", edgeDefinition); var g = Graph._create("routeplanner", edgeDefinition);
var berlin = g.germanCity.save({_key: "Berlin", population : 3000000, isCapital : true}); var berlin = g.germanCity.save({_key: "Berlin", population : 3000000, isCapital : true});
var cologne = g.germanCity.save({_key: "Cologne", population : 1000000, isCapital : false}); var cologne = g.germanCity.save({_key: "Cologne", population : 1000000, isCapital : false});
var hamburg = g.germanCity.save({_key: "Hamburg", population : 1000000, isCapital : false}); var hamburg = g.germanCity.save({_key: "Hamburg", population : 1000000, isCapital : false});
var lyon = g.frenchCity.save({_key: "Lyon", population : 80000, isCapital : false}); var lyon = g.frenchCity.save({_key: "Lyon", population : 80000, isCapital : false});
var paris = g.frenchCity.save({_key: "Paris", population : 4000000, isCapital : true}); var paris = g.frenchCity.save({_key: "Paris", population : 4000000, isCapital : true});
g.germanHighway.save(berlin._id, cologne._id, {distance: 850}); g.germanHighway.save(berlin._id, cologne._id, {distance: 850});
g.germanHighway.save(berlin._id, hamburg._id, {distance: 400}); g.germanHighway.save(berlin._id, hamburg._id, {distance: 400});
g.germanHighway.save(hamburg._id, cologne._id, {distance: 500}); g.germanHighway.save(hamburg._id, cologne._id, {distance: 500});
g.frenchHighway.save(paris._id, lyon._id, {distance: 550}); g.frenchHighway.save(paris._id, lyon._id, {distance: 550});
g.internationalHighway.save(berlin._id, lyon._id, {distance: 1100}); g.internationalHighway.save(berlin._id, lyon._id, {distance: 1100});
g.internationalHighway.save(berlin._id, paris._id, {distance: 1200}); g.internationalHighway.save(berlin._id, paris._id, {distance: 1200});
g.internationalHighway.save(hamburg._id, paris._id, {distance: 900}); g.internationalHighway.save(hamburg._id, paris._id, {distance: 900});
g.internationalHighway.save(hamburg._id, lyon._id, {distance: 1300}); g.internationalHighway.save(hamburg._id, lyon._id, {distance: 1300});
g.internationalHighway.save(cologne._id, lyon._id, {distance: 700}); g.internationalHighway.save(cologne._id, lyon._id, {distance: 700});
g.internationalHighway.save(cologne._id, paris._id, {distance: 550}); g.internationalHighway.save(cologne._id, paris._id, {distance: 550});
return g; return g;
}; };
var dropGraph = function(name) { var dropGraph = function(name) {
if (Graph._exists(name)) { if (Graph._exists(name)) {
return Graph._drop(name, true); return Graph._drop(name, true);
} }
}; };
var loadGraph = function(name) { var loadGraph = function(name) {
dropGraph(name); dropGraph(name);
switch (name) { switch (name) {
case "knows_graph": case "knows_graph":
return createTraversalExample(); return createTraversalExample();
case "routeplanner": case "routeplanner":
return createRoutePlannerGraph(); return createRoutePlannerGraph();
case "social": case "social":
return createSocialGraph(); return createSocialGraph();
} }
}; };
exports.loadGraph = loadGraph; exports.loadGraph = loadGraph;
exports.dropGraph = dropGraph; exports.dropGraph = dropGraph;
}());

View File

@ -1,4 +1,4 @@
/*jshint strict: false */ 'use strict';
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Foxx application module /// @brief Foxx application module
@ -28,40 +28,37 @@
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany /// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
(function() {
'use strict';
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- imports // --SECTION-- imports
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
var fs = require("fs"); var fs = require("fs");
var internal = require("internal"); var internal = require("internal");
var db = internal.db; var db = internal.db;
var _= require("underscore"); var _= require("underscore");
var utils = require("org/arangodb/foxx/manager-utils"); var utils = require("org/arangodb/foxx/manager-utils");
var console = require("console"); var console = require("console");
var arangodb = require("org/arangodb"); var arangodb = require("org/arangodb");
var ArangoError = arangodb.ArangoError; var ArangoError = arangodb.ArangoError;
var errors = arangodb.errors; var errors = arangodb.errors;
var throwFileNotFound = arangodb.throwFileNotFound; var throwFileNotFound = arangodb.throwFileNotFound;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private functions // --SECTION-- private functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function applyDefaultConfig(config) { function applyDefaultConfig(config) {
var res = {}; var res = {};
if (config !== undefined) { if (config !== undefined) {
Object.keys(config).forEach(function (attr) { Object.keys(config).forEach(function (attr) {
if (config[attr].default !== undefined) { if (config[attr].default !== undefined) {
res[attr] = config[attr].default; res[attr] = config[attr].default;
} }
}); });
}
return res;
} }
return res;
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors // --SECTION-- constructors and destructors
@ -71,56 +68,56 @@
// --SECTION-- AppContext // --SECTION-- AppContext
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function AppContext(app) { function AppContext(app) {
var prefix = fs.safeJoin(app._root, app._path); var prefix = fs.safeJoin(app._root, app._path);
this._prefix = prefix; this._prefix = prefix;
this.comments = []; this.comments = [];
this.name = app._name; this.name = app._name;
this.version = app._version; this.version = app._version;
this.mount = app._mount; this.mount = app._mount;
this.collectionPrefix = app._collectionPrefix; this.collectionPrefix = app._collectionPrefix;
this.options = app._options; this.options = app._options;
this.configuration = app._options.configuration; this.configuration = app._options.configuration;
this.dependencies = app._dependencies; this.dependencies = app._dependencies;
this.basePath = prefix; this.basePath = prefix;
this.baseUrl = '/_db/' + encodeURIComponent(db._name()) + app._mount; this.baseUrl = '/_db/' + encodeURIComponent(db._name()) + app._mount;
this.isDevelopment = app._isDevelopment; this.isDevelopment = app._isDevelopment;
this.isProduction = ! app._isDevelopment; this.isProduction = ! app._isDevelopment;
this.manifest = app._manifest; this.manifest = app._manifest;
}
AppContext.prototype.foxxFilename = function (path) {
return fs.safeJoin(this._prefix, path);
};
AppContext.prototype.collectionName = function (name) {
var replaced = this.collectionPrefix.replace(/[:\.]+/g, '_') +
name.replace(/[^a-zA-Z0-9]/g, '_').replace(/(^_+|_+$)/g, '').substr(0, 64);
if (replaced.length === 0) {
throw new Error("Cannot derive collection name from '" + name + "'");
} }
AppContext.prototype.foxxFilename = function (path) { return replaced;
return fs.safeJoin(this._prefix, path); };
};
AppContext.prototype.collectionName = function (name) { AppContext.prototype.collection = function (name) {
var replaced = this.collectionPrefix.replace(/[:\.]+/g, '_') + return db._collection(this.collectionName(name));
name.replace(/[^a-zA-Z0-9]/g, '_').replace(/(^_+|_+$)/g, '').substr(0, 64); };
if (replaced.length === 0) { AppContext.prototype.path = function (name) {
throw new Error("Cannot derive collection name from '" + name + "'"); return fs.join(this._prefix, name);
} };
return replaced;
};
AppContext.prototype.collection = function (name) {
return db._collection(this.collectionName(name));
};
AppContext.prototype.path = function (name) {
return fs.join(this._prefix, name);
};
AppContext.prototype.comment = function (str) { AppContext.prototype.comment = function (str) {
this.comments.push(str); this.comments.push(str);
}; };
AppContext.prototype.clearComments = function () { AppContext.prototype.clearComments = function () {
this.comments = []; this.comments = [];
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- ArangoApp // --SECTION-- ArangoApp
@ -131,7 +128,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function isSystemMount(mount) { function isSystemMount(mount) {
return (/^\/_/).test(mount); return (/^\/_/).test(mount);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -139,72 +136,72 @@ function isSystemMount(mount) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function computeRootAppPath(mount, isValidation) { function computeRootAppPath(mount, isValidation) {
if (isValidation) { if (isValidation) {
return ""; return "";
} }
if (isSystemMount(mount)) { if (isSystemMount(mount)) {
return module.systemAppPath(); return module.systemAppPath();
} }
return module.appPath(); return module.appPath();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief ArangoApp constructor /// @brief ArangoApp constructor
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function ArangoApp(config) { function ArangoApp(config) {
if (config.error) { if (config.error) {
this._error = config.error; this._error = config.error;
this._isBroken = true; this._isBroken = true;
} }
this._manifest = config.manifest || { this._manifest = config.manifest || {
name: "unknown", name: "unknown",
version: "error" version: "error"
}; };
if (!this._manifest.configuration) { if (!this._manifest.configuration) {
this._manifest.configuration = {}; this._manifest.configuration = {};
} }
if (!this._manifest.dependencies) { if (!this._manifest.dependencies) {
this._manifest.dependencies = {}; this._manifest.dependencies = {};
} }
this._name = this._manifest.name; this._name = this._manifest.name;
this._version = this._manifest.version; this._version = this._manifest.version;
this._root = computeRootAppPath(config.mount, config.id === "__internal"); this._root = computeRootAppPath(config.mount, config.id === "__internal");
this._path = config.path; this._path = config.path;
this._options = config.options; this._options = config.options;
this._mount = config.mount; this._mount = config.mount;
this._isSystem = config.isSystem || false; this._isSystem = config.isSystem || false;
this._isDevelopment = config.isDevelopment || false; this._isDevelopment = config.isDevelopment || false;
this._exports = {}; this._exports = {};
this._collectionPrefix = this._mount.substr(1).replace(/-/g, "_").replace(/\//g, "_") + "_"; this._collectionPrefix = this._mount.substr(1).replace(/-/g, "_").replace(/\//g, "_") + "_";
// Apply the default configuration and ignore all missing options // Apply the default configuration and ignore all missing options
var cfg = config.options.configuration; var cfg = config.options.configuration;
this._options.configuration = applyDefaultConfig(this._manifest.configuration); this._options.configuration = applyDefaultConfig(this._manifest.configuration);
this.configure(cfg); this.configure(cfg);
var deps = config.options.dependencies; var deps = config.options.dependencies;
this._options.dependencies = {}; this._options.dependencies = {};
this._dependencies = {}; this._dependencies = {};
this.updateDeps(deps); this.updateDeps(deps);
this._context = new AppContext(this); this._context = new AppContext(this);
this._context.appPackage = module.createAppPackage(this); this._context.appPackage = module.createAppPackage(this);
this._context.appModule = this._context.appPackage.createAppModule(this); this._context.appModule = this._context.appPackage.createAppModule(this);
if (! this._manifest.hasOwnProperty("defaultDocument")) { if (! this._manifest.hasOwnProperty("defaultDocument")) {
this._manifest.defaultDocument = "index.html"; this._manifest.defaultDocument = "index.html";
} }
if (this._manifest.hasOwnProperty("thumbnail")) { if (this._manifest.hasOwnProperty("thumbnail")) {
var thumbfile = fs.join(this._root, this._path, this._manifest.thumbnail); var thumbfile = fs.join(this._root, this._path, this._manifest.thumbnail);
try { try {
this._thumbnail = fs.read64(thumbfile); this._thumbnail = fs.read64(thumbfile);
} catch (err) { } catch (err) {
console.warnLines( console.warnLines(
"Cannot read thumbnail '%s' : %s", thumbfile, err); "Cannot read thumbnail '%s' : %s", thumbfile, err);
}
} }
} }
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private methods // --SECTION-- private methods
@ -214,9 +211,9 @@ function computeRootAppPath(mount, isValidation) {
/// @brief prints a package /// @brief prints a package
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype._PRINT = function (context) { ArangoApp.prototype._PRINT = function (context) {
context.output += '[app "' + this._name + '" (' + this._version + ')]'; context.output += '[app "' + this._name + '" (' + this._version + ')]';
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- public methods // --SECTION-- public methods
@ -226,216 +223,215 @@ function computeRootAppPath(mount, isValidation) {
/// @brief creates a Json representation of itself to be persisted /// @brief creates a Json representation of itself to be persisted
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.toJSON = function () { ArangoApp.prototype.toJSON = function () {
var json = { var json = {
manifest: this._manifest, manifest: this._manifest,
name: this._name, name: this._name,
version: this._version, version: this._version,
path: this._path, path: this._path,
options: this._options, options: this._options,
mount: this._mount, mount: this._mount,
root: this._root, root: this._root,
isSystem: this._isSystem, isSystem: this._isSystem,
isDevelopment: this._isDevelopment isDevelopment: this._isDevelopment
};
if (this.hasOwnProperty("_error")) {
json.error = this._error;
}
if (this._manifest.hasOwnProperty("author")) {
json.author = this._manifest.author;
}
if (this._manifest.hasOwnProperty("description")) {
json.description = this._manifest.description;
}
if (this.hasOwnProperty("_thumbnail")) {
json.thumbnail = this._thumbnail;
}
return json;
}; };
if (this.hasOwnProperty("_error")) {
json.error = this._error;
}
if (this._manifest.hasOwnProperty("author")) {
json.author = this._manifest.author;
}
if (this._manifest.hasOwnProperty("description")) {
json.description = this._manifest.description;
}
if (this.hasOwnProperty("_thumbnail")) {
json.thumbnail = this._thumbnail;
}
return json;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief creates a reduced Json representation of itself for output /// @brief creates a reduced Json representation of itself for output
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.simpleJSON = function () { ArangoApp.prototype.simpleJSON = function () {
var json = { var json = {
name: this._name, name: this._name,
version: this._version, version: this._version,
mount: this._mount mount: this._mount
};
return json;
}; };
return json;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief toggles development mode /// @brief toggles development mode
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.development = function(activate) { ArangoApp.prototype.development = function(activate) {
this._isDevelopment = activate; this._isDevelopment = activate;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief set app dependencies /// @brief set app dependencies
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.updateDeps = function (deps) { ArangoApp.prototype.updateDeps = function (deps) {
var expected = this._manifest.dependencies; var expected = this._manifest.dependencies;
var invalid = []; var invalid = [];
_.each(deps, function (mount, name) { _.each(deps, function (mount, name) {
if (!expected[name]) { if (!expected[name]) {
invalid.push("Unexpected dependency " + name); invalid.push("Unexpected dependency " + name);
}
this._options.dependencies[name] = mount;
}, this);
_.each(this._options.dependencies, function (mount, name) {
Object.defineProperty(this._dependencies, name, {
configurable: true,
enumerable: true,
get: function () {
return require("org/arangodb/foxx").requireApp(mount);
} }
this._options.dependencies[name] = mount; });
}, this); }, this);
_.each(this._options.dependencies, function (mount, name) { return invalid;
Object.defineProperty(this._dependencies, name, { };
configurable: true,
enumerable: true,
get: function () {
return require("org/arangodb/foxx").requireApp(mount);
}
});
}, this);
return invalid;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief set app configuration /// @brief set app configuration
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.configure = function(config) { ArangoApp.prototype.configure = function(config) {
var expected = this._manifest.configuration; var expected = this._manifest.configuration;
var invalid = []; var invalid = [];
this._options.configuration = this._options.configuration || {}; this._options.configuration = this._options.configuration || {};
_.each(config, function (value, name) { _.each(config, function (value, name) {
if (!expected[name]) { if (!expected[name]) {
invalid.push("Unexpected Option " + name); invalid.push("Unexpected Option " + name);
} else {
var type = expected[name].type;
var result = utils.parameterTypes[type].validate(value);
if (result.error) {
invalid.push(result.error.message.replace(/^"value"/, '"' + name + '"'));
} else { } else {
var type = expected[name].type; this._options.configuration[name] = result.value;
var result = utils.parameterTypes[type].validate(value);
if (result.error) {
invalid.push(result.error.message.replace(/^"value"/, '"' + name + '"'));
} else {
this._options.configuration[name] = result.value;
}
} }
}, this); }
}, this);
return invalid; return invalid;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get app configuration /// @brief get app configuration
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.getConfiguration = function (simple) { ArangoApp.prototype.getConfiguration = function (simple) {
var config = {}; var config = {};
var definitions = this._manifest.configuration; var definitions = this._manifest.configuration;
var options = this._options.configuration; var options = this._options.configuration;
_.each(definitions, function (dfn, name) { _.each(definitions, function (dfn, name) {
var value = options[name] === undefined ? dfn.default : options[name]; var value = options[name] === undefined ? dfn.default : options[name];
config[name] = simple ? value : _.extend(_.clone(dfn), { config[name] = simple ? value : _.extend(_.clone(dfn), {
title: utils.getReadableName(name), title: utils.getReadableName(name),
current: value current: value
});
}); });
return config; });
}; return config;
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get app dependencies /// @brief get app dependencies
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.getDependencies = function(simple) { ArangoApp.prototype.getDependencies = function(simple) {
var deps = {}; var deps = {};
var definitions = this._manifest.dependencies; var definitions = this._manifest.dependencies;
var options = this._options.dependencies; var options = this._options.dependencies;
_.each(definitions, function (dfn, name) { _.each(definitions, function (dfn, name) {
deps[name] = simple ? options[name] : { deps[name] = simple ? options[name] : {
definition: dfn, definition: dfn,
title: utils.getReadableName(name), title: utils.getReadableName(name),
current: options[name] current: options[name]
}; };
}); });
return deps; return deps;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief App needs to be configured /// @brief App needs to be configured
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.needsConfiguration = function() { ArangoApp.prototype.needsConfiguration = function() {
var config = this.getConfiguration(); var config = this.getConfiguration();
var deps = this.getDependencies(); var deps = this.getDependencies();
return _.any(config, function (cfg) { return _.any(config, function (cfg) {
return cfg.current === undefined; return cfg.current === undefined;
}) || _.any(deps, function (dep) { }) || _.any(deps, function (dep) {
return dep.current === undefined; return dep.current === undefined;
}); });
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief loadAppScript /// @brief loadAppScript
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ArangoApp.prototype.loadAppScript = function (filename, options) { ArangoApp.prototype.loadAppScript = function (filename, options) {
options = options || {}; options = options || {};
var appContext = _.extend({}, options.appContext, this._context); var appContext = _.extend({}, options.appContext, this._context);
var full = fs.join(this._root, this._path, filename); var full = fs.join(this._root, this._path, filename);
if (!fs.exists(full)) { if (!fs.exists(full)) {
throwFileNotFound(full); throwFileNotFound(full);
}
var fileContent = fs.read(full);
if (options.transform) {
fileContent = options.transform(fileContent);
} else if (/\.coffee$/.test(filename)) {
var cs = require("coffee-script");
fileContent = cs.compile(fileContent, {bare: true});
}
var context = {};
if (options.context) {
Object.keys(options.context).forEach(function (key) {
context[key] = options.context[key];
});
}
var localModule = appContext.appPackage.createAppModule(this, filename);
context.__filename = full;
context.__dirname = module.normalizeModuleName(full + "/..");
context.console = require("org/arangodb/foxx/console")(this._mount);
context.applicationContext = appContext;
try {
return localModule.run(fileContent, context);
} catch(e) {
if (e instanceof ArangoError) {
throw e;
} }
var err = new ArangoError({
errorNum: errors.ERROR_FAILED_TO_EXECUTE_SCRIPT.code,
errorMessage: errors.ERROR_FAILED_TO_EXECUTE_SCRIPT.message
+ "\nFile: " + filename
});
err.stack = e.stack;
err.cause = e;
throw err;
}
};
var fileContent = fs.read(full); exports.ArangoApp = ArangoApp;
if (options.transform) {
fileContent = options.transform(fileContent);
} else if (/\.coffee$/.test(filename)) {
var cs = require("coffee-script");
fileContent = cs.compile(fileContent, {bare: true});
}
var context = {};
if (options.context) {
Object.keys(options.context).forEach(function (key) {
context[key] = options.context[key];
});
}
var localModule = appContext.appPackage.createAppModule(this, filename);
context.__filename = full;
context.__dirname = module.normalizeModuleName(full + "/..");
context.console = require("org/arangodb/foxx/console")(this._mount);
context.applicationContext = appContext;
try {
return localModule.run(fileContent, context);
} catch(e) {
if (e instanceof ArangoError) {
throw e;
}
var err = new ArangoError({
errorNum: errors.ERROR_FAILED_TO_EXECUTE_SCRIPT.code,
errorMessage: errors.ERROR_FAILED_TO_EXECUTE_SCRIPT.message
+ "\nFile: " + filename
});
err.stack = e.stack;
err.cause = e;
throw err;
}
};
exports.ArangoApp = ArangoApp;
}());
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE // --SECTION-- END-OF-FILE

File diff suppressed because it is too large Load Diff

View File

@ -174,9 +174,6 @@ function Sessions(opts) {
if (opts.cookie.secret && typeof opts.cookie.secret !== 'string') { if (opts.cookie.secret && typeof opts.cookie.secret !== 'string') {
throw new Error('Cookie secret must be a string or empty.'); throw new Error('Cookie secret must be a string or empty.');
} }
if (!opts.cookie.name) {
opts.cookie.name = 'sid';
}
} else if (opts.type === 'header') { } else if (opts.type === 'header') {
if (opts.header && typeof opts.header !== 'string') { if (opts.header && typeof opts.header !== 'string') {
throw new Error('Header name must be a string or empty.'); throw new Error('Header name must be a string or empty.');

View File

@ -1,3 +1,4 @@
'use strict';
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Foxx Swagger documentation /// @brief Foxx Swagger documentation
@ -26,67 +27,63 @@
/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany /// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
(function() { var foxxInternal = require("org/arangodb/foxx/internals");
'use strict'; var _ = require("underscore");
var internal = require("internal");
var foxxInternal = require("org/arangodb/foxx/internals"); // Wraps the docs object of a route to add swagger compatible documentation
var _ = require("underscore"); var SwaggerDocs = function (docs, models) {
var internal = require("internal"); this.docs = docs;
this.models = models;
};
// Wraps the docs object of a route to add swagger compatible documentation SwaggerDocs.prototype.addNickname = function (httpMethod, match) {
var SwaggerDocs = function (docs, models) { this.docs.nickname = foxxInternal.constructNickname(httpMethod, match);
this.docs = docs; };
this.models = models;
};
SwaggerDocs.prototype.addNickname = function (httpMethod, match) { SwaggerDocs.prototype.addPathParam = function (paramName, description, dataType, required) {
this.docs.nickname = foxxInternal.constructNickname(httpMethod, match); this.docs.parameters.push(foxxInternal.constructPathParamDoc(paramName, description, dataType, required));
}; };
SwaggerDocs.prototype.addPathParam = function (paramName, description, dataType, required) { SwaggerDocs.prototype.addQueryParam = function (paramName, description, dataType, required, allowMultiple) {
this.docs.parameters.push(foxxInternal.constructPathParamDoc(paramName, description, dataType, required)); this.docs.parameters.push(foxxInternal.constructQueryParamDoc(
}; paramName,
description,
dataType,
required,
allowMultiple
));
};
SwaggerDocs.prototype.addQueryParam = function (paramName, description, dataType, required, allowMultiple) { SwaggerDocs.prototype.addBodyParam = function (paramName, description, jsonSchema) {
this.docs.parameters.push(foxxInternal.constructQueryParamDoc(
paramName,
description,
dataType,
required,
allowMultiple
));
};
SwaggerDocs.prototype.addBodyParam = function (paramName, description, jsonSchema) { var token = internal.genRandomAlphaNumbers(32);
this.models[token] = jsonSchema;
var token = internal.genRandomAlphaNumbers(32); var param = _.find(this.docs.parameters, function (parameter) {
this.models[token] = jsonSchema; return parameter.name === 'undocumented body';
});
var param = _.find(this.docs.parameters, function (parameter) { if (_.isUndefined(param)) {
return parameter.name === 'undocumented body'; this.docs.parameters.push({
name: paramName,
paramType: "body",
description: description,
dataType: token
}); });
} else {
param.name = paramName;
param.description = description;
param.dataType = token;
}
};
if (_.isUndefined(param)) { SwaggerDocs.prototype.addSummary = function (summary) {
this.docs.parameters.push({ this.docs.summary = summary;
name: paramName, };
paramType: "body",
description: description,
dataType: token
});
} else {
param.name = paramName;
param.description = description;
param.dataType = token;
}
};
SwaggerDocs.prototype.addSummary = function (summary) { SwaggerDocs.prototype.addNotes = function (notes) {
this.docs.summary = summary; this.docs.notes = notes;
}; };
SwaggerDocs.prototype.addNotes = function (notes) {
this.docs.notes = notes;
};
exports.Docs = SwaggerDocs; exports.Docs = SwaggerDocs;
}());