mirror of https://gitee.com/bigwinds/arangodb
added install command
This commit is contained in:
parent
1b6dfad627
commit
709e09d04e
|
@ -4,76 +4,79 @@ Foxx {#UserManualFoxx}
|
||||||
@NAVIGATE_UserManualFoxx
|
@NAVIGATE_UserManualFoxx
|
||||||
@EMBEDTOC{UserManualFoxxTOC}
|
@EMBEDTOC{UserManualFoxxTOC}
|
||||||
|
|
||||||
Foxx: Build APIs and simple web applications in ArangoDB
|
Foxx: Build APIs and simple web applications in ArangoDB{#UserManualFoxxIntro}
|
||||||
========================================================
|
==============================================================================
|
||||||
|
|
||||||
Foxx is an easy way to create APIs and simple web applications from within **ArangoDB**. It is inspired by Sinatra,
|
Foxx is an easy way to create APIs and simple web applications from within
|
||||||
the classy Ruby web framework. If FoxxApplication is Sinatra,
|
**ArangoDB**. It is inspired by Sinatra, the classy Ruby web framework. If
|
||||||
[ArangoDB Actions](http://www.arangodb.org/manuals/current/UserManualActions.html) are the corresponding `Rack`.
|
FoxxApplication is Sinatra,
|
||||||
They provide all the HTTP goodness.
|
[ArangoDB Actions](http://www.arangodb.org/manuals/current/UserManualActions.html)
|
||||||
|
are the corresponding `Rack`. They provide all the HTTP goodness.
|
||||||
|
|
||||||
So let's get started, shall we?
|
So let's get started, shall we?
|
||||||
|
|
||||||
An application build with Foxx is written in JavaScript and deployed to ArangoDB directly. ArangoDB serves this
|
An application build with Foxx is written in JavaScript and deployed to ArangoDB
|
||||||
application, you do not need a separate application server.
|
directly. ArangoDB serves this application, you do not need a separate
|
||||||
|
application server.
|
||||||
|
|
||||||
So given you want to build an application that sends a plain-text response "Worked!" for all requests to `/my/wiese`.
|
So given you want to build an application that sends a plain-text response
|
||||||
How would you achieve that with Foxx?
|
"Worked!" for all requests to `/my/wiese`. How would you achieve that with
|
||||||
|
Foxx?
|
||||||
|
|
||||||
First, create a directory `apps` somewhere in your filesystem. Let's assume from now on that the absolute path for
|
First, create a directory `apps` somewhere in your filesystem. Let's assume from
|
||||||
this directory is `/home/user/apps`.
|
now on that the absolute path for this directory is `/home/user/apps`.
|
||||||
|
|
||||||
After that, create a sub-directory `my_app` in the `apps` directory and save the following content in a file named `app.js` there:
|
After that, create a sub-directory `my_app` in the `apps` directory and save the
|
||||||
|
following content in a file named `app.js` there:
|
||||||
|
|
||||||
var Foxx = require("org/arangodb/foxx");
|
var Foxx = require("org/arangodb/foxx");
|
||||||
|
var app = new Foxx.Application(applicationContext);
|
||||||
var app = new Foxx.Application();
|
|
||||||
|
|
||||||
app.get("/wiese", function(req, res) {
|
app.get("/wiese", function(req, res) {
|
||||||
res.set("Content-Type", "text/plain");
|
res.set("Content-Type", "text/plain");
|
||||||
res.body = "Worked!"
|
res.body = "Worked!"
|
||||||
});
|
});
|
||||||
|
|
||||||
app.start(applicationContext);
|
Beside the app.js we need a manifest file. In order to achieve that, we create a
|
||||||
|
file called `manifest.json` in our `my_app` directory with the following
|
||||||
|
content:
|
||||||
|
|
||||||
Beside the app.js we need a manifest file. In order to achieve that, we create a file called `manifest.json` in our
|
{
|
||||||
`my_app` directory with the following content:
|
"name": "my_app",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"apps": {
|
||||||
|
"/": "app.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
You **must** specify a name and a version number for your application, otherwise
|
||||||
"name": "my_app",
|
it won't be loaded into ArangoDB.
|
||||||
"version": "0.0.1",
|
|
||||||
"apps": {
|
|
||||||
"/": "app.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
You **must** specify a name and a version number for your application, otherwise it won't be loaded into ArangoDB.
|
You should now have the following files and directories with your application
|
||||||
|
(starting at `/home/user` in our example):
|
||||||
You should now have the following files and directories with your application (starting at `/home/user` in our example):
|
|
||||||
|
|
||||||
apps/
|
apps/
|
||||||
my_app/
|
my_app/
|
||||||
manifest.json
|
manifest.json
|
||||||
app.js
|
app.js
|
||||||
|
|
||||||
This is your application. Now we need to mount it to the path `/my`.
|
This is your application.
|
||||||
|
|
||||||
Now your application is done. Start ArangoDB as follows:
|
Now your application is done. Start ArangoDB as follows:
|
||||||
|
|
||||||
$ arangod --javascript.dev-app-path /home/user/apps /tmp/fancy_db
|
$ arangod --javascript.dev-app-path /home/user/apps /tmp/fancy_db
|
||||||
|
|
||||||
Replace `/home/user/apps` with the apps path that you initially created. This is the path that you created the `my_app`
|
This will start the ArangoDB server in a development mode using the directory
|
||||||
directory in. Replace `/tmp/fancy_db` with the directory your database is located in.
|
'/home/user/apps' as workspace. Produktion application are installed using the
|
||||||
|
Foxx manager and should not be changed. In development mode the server
|
||||||
|
automatically monitors the workspace and detects any change made to the files.
|
||||||
|
|
||||||
To include your app in the list of apps running on your ArangoDB instance, start the ArangoDB shell and add your
|
Replace `/home/user/apps` with the apps path that you initially created. This is
|
||||||
new application:
|
the path that you created the `my_app` directory in. Replace `/tmp/fancy_db`
|
||||||
|
with the directory your database is located in.
|
||||||
|
|
||||||
$ arangosh
|
Now point your browser to `http://localhost:8529/dev/my_app/wiese` and you
|
||||||
arangosh> aal = require('org/arangodb/aal');
|
should see "Worked!". After this short overview, let's get into the details.
|
||||||
arangosh> aal.installDevApp('my_app', '/my');
|
|
||||||
|
|
||||||
Now point your browser to `http://localhost:8529/my/wiese` and you should see "Worked!". After this short overview,
|
|
||||||
let's get into the details.
|
|
||||||
|
|
||||||
## Fishbowl - Foxx's app repository
|
## Fishbowl - Foxx's app repository
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[server]
|
[server]
|
||||||
endpoint = tcp://localhost:8529
|
endpoint = tcp://localhost:8529
|
||||||
|
password =
|
||||||
|
|
||||||
[javascript]
|
[javascript]
|
||||||
startup-directory = @PKGDATADIR@/js
|
startup-directory = @PKGDATADIR@/js
|
||||||
|
|
|
@ -172,8 +172,17 @@ actions.defineHttp({
|
||||||
fs.unzipFile(realFile, path, false, true);
|
fs.unzipFile(realFile, path, false, true);
|
||||||
|
|
||||||
foxxManager.scanAppDirectory();
|
foxxManager.scanAppDirectory();
|
||||||
|
|
||||||
|
var found = arangodb.db._collection("_aal").firstExample({
|
||||||
|
type: "app",
|
||||||
|
path: name + "-" + version
|
||||||
|
});
|
||||||
|
|
||||||
|
if (found !== null) {
|
||||||
|
found = found.app;
|
||||||
|
}
|
||||||
|
|
||||||
actions.resultOk(req, res, actions.HTTP_OK, { path: path });
|
actions.resultOk(req, res, actions.HTTP_OK, { path: path, app: found });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
actions.resultException(req, res, err);
|
actions.resultException(req, res, err);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*jslint indent: 2, nomen: true, maxlen: 120, vars: true, white: true, plusplus: true, nonpropdel: true, continue: true, regexp: true */
|
/*jslint indent: 2, nomen: true, maxlen: 120, vars: true, white: true, plusplus: true, nonpropdel: true, continue: true, regexp: true */
|
||||||
/*global require, exports */
|
/*global require, exports, module */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief ArangoDB Application Launcher
|
/// @brief ArangoDB Application Launcher
|
||||||
|
@ -521,11 +521,13 @@ function updateFishbowl () {
|
||||||
function compareApps (l, r) {
|
function compareApps (l, r) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var left = l.name.toLowerCase(), right = r.name.toLowerCase();
|
var left = l.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;
|
||||||
}
|
}
|
||||||
|
@ -538,6 +540,8 @@ function compareApps (l, r) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function cmdUsage () {
|
function cmdUsage () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
var printf = arangodb.printf;
|
var printf = arangodb.printf;
|
||||||
var fm = "foxx-manager";
|
var fm = "foxx-manager";
|
||||||
|
|
||||||
|
@ -558,6 +562,8 @@ function cmdUsage () {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
exports.run = function (args) {
|
exports.run = function (args) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
if (typeof args === 'undefined' || args.length === 0) {
|
if (typeof args === 'undefined' || args.length === 0) {
|
||||||
console.error("expecting a command, please try: ");
|
console.error("expecting a command, please try: ");
|
||||||
cmdUsage();
|
cmdUsage();
|
||||||
|
@ -568,7 +574,7 @@ exports.run = function (args) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (type === 'fetch') {
|
if (type === 'fetch') {
|
||||||
exports.fecth(args[1], args[2], args[3]);
|
exports.fetch(args[1], args[2], args[3]);
|
||||||
}
|
}
|
||||||
else if (type === 'mount') {
|
else if (type === 'mount') {
|
||||||
if (3 < args.length) {
|
if (3 < args.length) {
|
||||||
|
@ -578,6 +584,14 @@ exports.run = function (args) {
|
||||||
exports.mount(args[1], args[2]);
|
exports.mount(args[1], args[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (type === 'install') {
|
||||||
|
if (3 < args.length) {
|
||||||
|
exports.install(args[1], args[2], JSON.parse(args[3]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
exports.install(args[1], args[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (type === 'unmount') {
|
else if (type === 'unmount') {
|
||||||
exports.unmount(args[1]);
|
exports.unmount(args[1]);
|
||||||
}
|
}
|
||||||
|
@ -662,7 +676,7 @@ exports.fetch = function (type, location, version) {
|
||||||
var res = arango.POST("/_admin/foxx/fetch", JSON.stringify(req));
|
var res = arango.POST("/_admin/foxx/fetch", JSON.stringify(req));
|
||||||
arangosh.checkRequestResult(res);
|
arangosh.checkRequestResult(res);
|
||||||
|
|
||||||
return { path: res.path };
|
return { path: res.path, app: res.app };
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -720,6 +734,86 @@ exports.unmount = exports.uninstall = function (key) {
|
||||||
arangosh.checkRequestResult(res);
|
arangosh.checkRequestResult(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief installs a FOXX application
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
exports.install = function (name, mount, options) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var usage = ", usage: install(<name>, <mount>, [<options>])";
|
||||||
|
|
||||||
|
if (typeof name === "undefined") {
|
||||||
|
throwBadParameter("name missing" + usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof mount === "undefined") {
|
||||||
|
throwBadParameter("mount missing" + usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
validateMount(mount);
|
||||||
|
|
||||||
|
// .............................................................................
|
||||||
|
// latest fishbowl version
|
||||||
|
// .............................................................................
|
||||||
|
|
||||||
|
var fishbowl = getFishbowlStorage();
|
||||||
|
var available = fishbowl.firstExample({name: name});
|
||||||
|
var source = null;
|
||||||
|
var version = null;
|
||||||
|
|
||||||
|
if (available !== null) {
|
||||||
|
var keys = [];
|
||||||
|
var key;
|
||||||
|
|
||||||
|
for (key in available.versions) {
|
||||||
|
if (available.versions.hasOwnProperty(key)) {
|
||||||
|
keys.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keys = keys.sort(module.compareVersions);
|
||||||
|
version = keys[keys.length - 1];
|
||||||
|
source = available.versions[version];
|
||||||
|
}
|
||||||
|
|
||||||
|
// .............................................................................
|
||||||
|
// latest fetched version
|
||||||
|
// .............................................................................
|
||||||
|
|
||||||
|
var appId = null;
|
||||||
|
var aal = getStorage();
|
||||||
|
var cursor = aal.byExample({ type: "app", name: name });
|
||||||
|
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
var doc = cursor.next();
|
||||||
|
|
||||||
|
if (module.compareVersions(version, doc.version) <= 0) {
|
||||||
|
version = doc.version;
|
||||||
|
source = "fetched";
|
||||||
|
appId = doc.app;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// .............................................................................
|
||||||
|
// fetched latest version
|
||||||
|
// .............................................................................
|
||||||
|
|
||||||
|
if (source !== "fetched") {
|
||||||
|
appId = exports.fetch(source.type, source.location, source.tag).app;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .............................................................................
|
||||||
|
// install at path
|
||||||
|
// .............................................................................
|
||||||
|
|
||||||
|
if (appId === null) {
|
||||||
|
throw new Error("cannot extract application id");
|
||||||
|
}
|
||||||
|
|
||||||
|
return exports.mount(appId, mount, options);
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief lists all installed FOXX applications
|
/// @brief lists all installed FOXX applications
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -548,7 +548,7 @@ function require (path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If one's a prefix of the other, the longer one is greater.
|
// If one's a prefix of the other, the longer one is bigger one.
|
||||||
if (aComponents.length > bComponents.length) {
|
if (aComponents.length > bComponents.length) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue