mirror of https://gitee.com/bigwinds/arangodb
Foxx: Tear apart Foxx.Application
This commit is contained in:
parent
98fe5fd6c1
commit
0f6009a3ba
|
@ -165,8 +165,8 @@ function DocumentationAndConstraintsSpec () {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setUp: function () {
|
setUp: function () {
|
||||||
app = new FoxxApplication({prefix: "", foxxes: []}),
|
app = new FoxxApplication({prefix: "", foxxes: []});
|
||||||
routes = app.routingInfo.routes;
|
routes = app.routingInfo.routes;
|
||||||
},
|
},
|
||||||
|
|
||||||
testDefinePathParam: function () {
|
testDefinePathParam: function () {
|
||||||
|
@ -185,7 +185,7 @@ function DocumentationAndConstraintsSpec () {
|
||||||
assertEqual(routes[0].docs.parameters[0].dataType, "int");
|
assertEqual(routes[0].docs.parameters[0].dataType, "int");
|
||||||
assertEqual(routes[0].docs.parameters[0].required, true);
|
assertEqual(routes[0].docs.parameters[0].required, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
testDefinePathCaseParam: function () {
|
testDefinePathCaseParam: function () {
|
||||||
app.get('/foxx/:idParam', function () {
|
app.get('/foxx/:idParam', function () {
|
||||||
//nothing
|
//nothing
|
||||||
|
|
|
@ -29,51 +29,17 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var Application,
|
var Application,
|
||||||
RequestContext,
|
RequestContext = require("org/arangodb/foxx/request_context").RequestContext,
|
||||||
db = require("org/arangodb").db,
|
db = require("org/arangodb").db,
|
||||||
BaseMiddleware = require("org/arangodb/foxx/base_middleware").BaseMiddleware,
|
BaseMiddleware = require("org/arangodb/foxx/base_middleware").BaseMiddleware,
|
||||||
_ = require("underscore"),
|
extend = require("underscore").extend,
|
||||||
internal = {};
|
is = require("org/arangodb/is"),
|
||||||
|
internal = require("org/arangodb/foxx/internals");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- Application
|
// --SECTION-- Application
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @fn JSF_foxx_createUrlObject
|
|
||||||
/// @brief create a new url object
|
|
||||||
///
|
|
||||||
/// This creates a new `UrlObject`.
|
|
||||||
///
|
|
||||||
/// ArangoDB uses a certain structure we refer to as `UrlObject`. With the
|
|
||||||
/// following function (which is only internal, and not exported) you can create
|
|
||||||
/// an UrlObject with a given URL, a constraint and a method. For example:
|
|
||||||
///
|
|
||||||
/// @EXAMPLES
|
|
||||||
///
|
|
||||||
/// @code
|
|
||||||
/// internal.createUrlObject('/lecker/gans', null, 'get');
|
|
||||||
/// @endcode
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
internal.createUrlObject = function (url, constraint, method) {
|
|
||||||
'use strict';
|
|
||||||
var urlObject = {};
|
|
||||||
|
|
||||||
if (!_.isString(url)) {
|
|
||||||
throw new Error("URL has to be a String");
|
|
||||||
}
|
|
||||||
|
|
||||||
urlObject.match = url;
|
|
||||||
urlObject.methods = [method];
|
|
||||||
|
|
||||||
if (!_.isUndefined(constraint)) {
|
|
||||||
urlObject.constraint = constraint;
|
|
||||||
}
|
|
||||||
|
|
||||||
return urlObject;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @fn JSF_foxx_application_initializer
|
/// @fn JSF_foxx_application_initializer
|
||||||
/// @brief Create a new Application
|
/// @brief Create a new Application
|
||||||
|
@ -83,7 +49,7 @@ internal.createUrlObject = function (url, constraint, method) {
|
||||||
/// This creates a new Application. The first argument is the application
|
/// This creates a new Application. The first argument is the application
|
||||||
/// context available in the variable `applicationContext`. The second one is an
|
/// context available in the variable `applicationContext`. The second one is an
|
||||||
/// options array with the following attributes:
|
/// options array with the following attributes:
|
||||||
///
|
///
|
||||||
/// * `urlPrefix`: All routes you define within will be prefixed with it.
|
/// * `urlPrefix`: All routes you define within will be prefixed with it.
|
||||||
///
|
///
|
||||||
/// @EXAMPLES
|
/// @EXAMPLES
|
||||||
|
@ -99,24 +65,21 @@ Application = function (context, options) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var urlPrefix, baseMiddleware;
|
var urlPrefix, baseMiddleware;
|
||||||
|
|
||||||
if (typeof context === "undefined") {
|
if (is.notExisty(context)) {
|
||||||
throw new Error("parameter <context> is missing");
|
throw new Error("parameter <context> is missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
this.routingInfo = {
|
this.routingInfo = {
|
||||||
routes: []
|
routes: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
urlPrefix = options.urlPrefix || "";
|
urlPrefix = options.urlPrefix || "";
|
||||||
|
|
||||||
if (urlPrefix === "") {
|
if (urlPrefix === "") {
|
||||||
urlPrefix = context.prefix;
|
urlPrefix = context.prefix;
|
||||||
} else {
|
} else if (context.prefix !== "") {
|
||||||
if (context.prefix !== "") {
|
urlPrefix = context.prefix + "/" + urlPrefix;
|
||||||
urlPrefix = context.prefix + "/" + urlPrefix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.routingInfo.urlPrefix = urlPrefix;
|
this.routingInfo.urlPrefix = urlPrefix;
|
||||||
|
@ -147,39 +110,39 @@ Application = function (context, options) {
|
||||||
this.applicationContext = context;
|
this.applicationContext = context;
|
||||||
};
|
};
|
||||||
|
|
||||||
_.extend(Application.prototype, {
|
extend(Application.prototype, {
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @fn JSF_foxx_application_createRepository
|
/// @fn JSF_foxx_application_createRepository
|
||||||
/// @brief Create a repository
|
/// @brief Create a repository
|
||||||
///
|
///
|
||||||
/// @FUN{FoxxApplication::createRepository(@FA{name}, @FA{options})}
|
/// @FUN{FoxxApplication::createRepository(@FA{name}, @FA{options})}
|
||||||
///
|
///
|
||||||
/// A repository is a module that gets data from the database or saves data to
|
/// A repository is a module that gets data from the database or saves data to
|
||||||
/// it. A model is a representation of data which will be used by the
|
/// it. A model is a representation of data which will be used by the
|
||||||
/// repository. Use this method to create a repository and a corresponding
|
/// repository. Use this method to create a repository and a corresponding
|
||||||
/// model.
|
/// model.
|
||||||
///
|
///
|
||||||
/// @code
|
/// @code
|
||||||
/// Foxx = require("org/arangodb/foxx");
|
/// Foxx = require("org/arangodb/foxx");
|
||||||
///
|
///
|
||||||
/// app = new Foxx.Application(applicationContext);
|
/// app = new Foxx.Application(applicationContext);
|
||||||
///
|
///
|
||||||
/// var todos = app.createRepository("todos", {
|
/// var todos = app.createRepository("todos", {
|
||||||
/// model: "models/todos",
|
/// model: "models/todos",
|
||||||
/// repository: "repositories/todos"
|
/// repository: "repositories/todos"
|
||||||
/// });
|
/// });
|
||||||
/// @endcode
|
/// @endcode
|
||||||
///
|
///
|
||||||
//// If you do not give a repository, it will default to the
|
/// If you do not give a repository, it will default to the
|
||||||
/// `Foxx.Repository`. If you need more than the methods provided by it, you
|
/// `Foxx.Repository`. If you need more than the methods provided by it, you
|
||||||
/// must give the path (relative to your lib directory) to your repository
|
/// must give the path (relative to your lib directory) to your repository
|
||||||
/// module there. Then you can extend the Foxx.Repository prototype and add your
|
/// module there. Then you can extend the Foxx.Repository prototype and add your
|
||||||
/// own methods.
|
/// own methods.
|
||||||
///
|
///
|
||||||
/// If you don't need either of those, you don't need to give an empty
|
/// If you don't need either of those, you don't need to give an empty
|
||||||
/// object. You can then just call:
|
/// object. You can then just call:
|
||||||
///
|
///
|
||||||
/// @code
|
/// @code
|
||||||
/// var todos = app.createRepository("todos");
|
/// var todos = app.createRepository("todos");
|
||||||
/// @endcode
|
/// @endcode
|
||||||
|
@ -245,18 +208,7 @@ _.extend(Application.prototype, {
|
||||||
|
|
||||||
handleRequest: function (method, route, callback) {
|
handleRequest: function (method, route, callback) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var newRoute = {
|
var newRoute = internal.constructRoute(method, route, callback);
|
||||||
url: internal.createUrlObject(route, undefined, method),
|
|
||||||
action: {
|
|
||||||
callback: callback
|
|
||||||
},
|
|
||||||
docs: {
|
|
||||||
parameters: [],
|
|
||||||
errorResponses: [],
|
|
||||||
httpMethod: method.toUpperCase()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.routingInfo.routes.push(newRoute);
|
this.routingInfo.routes.push(newRoute);
|
||||||
return new RequestContext(newRoute);
|
return new RequestContext(newRoute);
|
||||||
},
|
},
|
||||||
|
@ -431,11 +383,13 @@ _.extend(Application.prototype, {
|
||||||
|
|
||||||
before: function (path, func, options) {
|
before: function (path, func, options) {
|
||||||
'use strict';
|
'use strict';
|
||||||
if (_.isUndefined(func)) {
|
if (is.notExisty(func)) {
|
||||||
func = path;
|
func = path;
|
||||||
path = "/*";
|
path = "/*";
|
||||||
}
|
}
|
||||||
options = options || { };
|
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
this.routingInfo.middleware.push({
|
this.routingInfo.middleware.push({
|
||||||
priority: options.priority || 1,
|
priority: options.priority || 1,
|
||||||
url: {match: path},
|
url: {match: path},
|
||||||
|
@ -470,7 +424,7 @@ _.extend(Application.prototype, {
|
||||||
|
|
||||||
after: function (path, func) {
|
after: function (path, func) {
|
||||||
'use strict';
|
'use strict';
|
||||||
if (_.isUndefined(func)) {
|
if (is.notExisty(func)) {
|
||||||
func = path;
|
func = path;
|
||||||
path = "/*";
|
path = "/*";
|
||||||
}
|
}
|
||||||
|
@ -485,159 +439,6 @@ _.extend(Application.prototype, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
internal.constructNickname = function (httpMethod, url) {
|
|
||||||
'use strict';
|
|
||||||
return (httpMethod + "_" + url)
|
|
||||||
.replace(/\W/g, '_')
|
|
||||||
.replace(/((_){2,})/g, '_')
|
|
||||||
.toLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @fn JSF_foxx_RequestContext_initializer
|
|
||||||
/// @brief Context of a Request Definition
|
|
||||||
///
|
|
||||||
/// Used for documenting and constraining the routes.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
RequestContext = function (route) {
|
|
||||||
'use strict';
|
|
||||||
this.route = route;
|
|
||||||
this.typeToRegex = {
|
|
||||||
"int": "/[0-9]+/",
|
|
||||||
"string": "/.+/"
|
|
||||||
};
|
|
||||||
this.route.docs.nickname = internal.constructNickname(route.docs.httpMethod, route.url.match);
|
|
||||||
};
|
|
||||||
|
|
||||||
_.extend(RequestContext.prototype, {
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @fn JSF_foxx_RequestContext_pathParam
|
|
||||||
/// @brief Describe a path parameter
|
|
||||||
///
|
|
||||||
/// meow
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
pathParam: function (paramName, attributes) {
|
|
||||||
'use strict';
|
|
||||||
var url = this.route.url,
|
|
||||||
docs = this.route.docs,
|
|
||||||
constraint = url.constraint || {};
|
|
||||||
|
|
||||||
constraint[paramName] = this.typeToRegex[attributes.dataType];
|
|
||||||
this.route.url = internal.createUrlObject(url.match, constraint, url.methods[0]);
|
|
||||||
this.route.docs.parameters.push({
|
|
||||||
paramType: "path",
|
|
||||||
name: paramName,
|
|
||||||
description: attributes.description,
|
|
||||||
dataType: attributes.dataType,
|
|
||||||
required: true
|
|
||||||
});
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @fn JSF_foxx_RequestContext_queryParam
|
|
||||||
/// @brief Describe a Query Parameter
|
|
||||||
///
|
|
||||||
/// @FUN{FoxxApplication::queryParam(@FA{id}, @FA{options})}
|
|
||||||
///
|
|
||||||
/// Describe a query parameter:
|
|
||||||
///
|
|
||||||
/// If you defined a route "/foxx", you can constrain which format a query
|
|
||||||
/// parameter (`/foxx?a=12`) can have by giving it a type. We currently support
|
|
||||||
/// the following types:
|
|
||||||
///
|
|
||||||
/// * int
|
|
||||||
/// * string
|
|
||||||
///
|
|
||||||
/// You can also provide a description of this parameter, if it is required and
|
|
||||||
/// if you can provide the parameter multiple times.
|
|
||||||
///
|
|
||||||
/// @EXAMPLES
|
|
||||||
///
|
|
||||||
/// @code
|
|
||||||
/// app.get("/foxx", function {
|
|
||||||
/// // Do something
|
|
||||||
/// }).queryParam("id", {
|
|
||||||
/// description: "Id of the Foxx",
|
|
||||||
/// dataType: "int",
|
|
||||||
/// required: true,
|
|
||||||
/// allowMultiple: false
|
|
||||||
/// });
|
|
||||||
/// @endcode
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
queryParam: function (paramName, attributes) {
|
|
||||||
'use strict';
|
|
||||||
this.route.docs.parameters.push({
|
|
||||||
paramType: "query",
|
|
||||||
name: paramName,
|
|
||||||
description: attributes.description,
|
|
||||||
dataType: attributes.dataType,
|
|
||||||
required: attributes.required,
|
|
||||||
allowMultiple: attributes.allowMultiple
|
|
||||||
});
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @fn JSF_foxx_RequestContext_summary
|
|
||||||
/// @brief Set the summary for this route in the documentation
|
|
||||||
///
|
|
||||||
/// @FUN{FoxxApplication::summary(@FA{description})}
|
|
||||||
///
|
|
||||||
/// Set the summary for this route in the documentation. Can't be longer than 60.
|
|
||||||
/// characters
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
summary: function (summary) {
|
|
||||||
'use strict';
|
|
||||||
if (summary.length > 60) {
|
|
||||||
throw new Error("Summary can't be longer than 60 characters");
|
|
||||||
}
|
|
||||||
this.route.docs.summary = summary;
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @fn JSF_foxx_RequestContext_notes
|
|
||||||
/// @brief Set the notes for this route in the documentation
|
|
||||||
///
|
|
||||||
/// @FUN{FoxxApplication::notes(@FA{description})}
|
|
||||||
///
|
|
||||||
/// Set the notes for this route in the documentation
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
notes: function (notes) {
|
|
||||||
'use strict';
|
|
||||||
this.route.docs.notes = notes;
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @fn JSF_foxx_RequestContext_errorResponse
|
|
||||||
/// @brief Document an error response
|
|
||||||
///
|
|
||||||
/// @FUN{FoxxApplication::errorResponse(@FA{code}, @FA{description})}
|
|
||||||
///
|
|
||||||
/// Document the error response for a given error @FA{code} with a reason for
|
|
||||||
/// the occurrence.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
errorResponse: function (code, reason) {
|
|
||||||
'use strict';
|
|
||||||
this.route.docs.errorResponses.push({
|
|
||||||
code: code,
|
|
||||||
reason: reason
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
exports.Application = Application;
|
exports.Application = Application;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*jslint indent: 2, nomen: true, maxlen: 120 */
|
||||||
|
/*global module, require, exports */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Foxx internals
|
||||||
|
///
|
||||||
|
/// @file
|
||||||
|
///
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2013 triagens GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Lucas Dohmen
|
||||||
|
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var is = require("org/arangodb/is"),
|
||||||
|
constructUrlObject,
|
||||||
|
constructNickname,
|
||||||
|
constructRoute,
|
||||||
|
constructPathParamDoc,
|
||||||
|
constructQueryParamDoc,
|
||||||
|
constructErrorResponseDoc;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JSF_foxx_internals_constructUrlObject
|
||||||
|
/// @brief create a new url object
|
||||||
|
///
|
||||||
|
/// This creates a new `UrlObject`.
|
||||||
|
///
|
||||||
|
/// ArangoDB uses a certain structure we refer to as `UrlObject`. With the
|
||||||
|
/// following function (which is only internal, and not exported) you can create
|
||||||
|
/// an UrlObject with a given URL, a constraint and a method. For example:
|
||||||
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
///
|
||||||
|
/// @code
|
||||||
|
/// internal.constructUrlObject('/lecker/gans', null, 'get');
|
||||||
|
/// @endcode
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
constructUrlObject = function (url, constraint, method) {
|
||||||
|
'use strict';
|
||||||
|
var urlObject = {};
|
||||||
|
|
||||||
|
if (is.noString(url)) {
|
||||||
|
throw new Error("URL has to be a String");
|
||||||
|
}
|
||||||
|
|
||||||
|
urlObject.match = url;
|
||||||
|
urlObject.methods = [method];
|
||||||
|
|
||||||
|
if (is.truthy(constraint)) {
|
||||||
|
urlObject.constraint = constraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return urlObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JSF_foxx_internals_constructNickname
|
||||||
|
/// @brief Construct a swagger-compatible nickname from a httpMethod and URL
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
constructNickname = function (httpMethod, url) {
|
||||||
|
'use strict';
|
||||||
|
return (httpMethod + "_" + url)
|
||||||
|
.replace(/\W/g, '_')
|
||||||
|
.replace(/((_){2,})/g, '_')
|
||||||
|
.toLowerCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
constructRoute = function (method, route, callback) {
|
||||||
|
'use strict';
|
||||||
|
return {
|
||||||
|
url: constructUrlObject(route, undefined, method),
|
||||||
|
action: {
|
||||||
|
callback: callback
|
||||||
|
},
|
||||||
|
docs: {
|
||||||
|
parameters: [],
|
||||||
|
errorResponses: [],
|
||||||
|
httpMethod: method.toUpperCase()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
constructPathParamDoc = function (paramName, description, dataType) {
|
||||||
|
'use strict';
|
||||||
|
return {
|
||||||
|
paramType: "path",
|
||||||
|
name: paramName,
|
||||||
|
description: description,
|
||||||
|
dataType: dataType,
|
||||||
|
required: true
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
constructQueryParamDoc = function (paramName, description, dataType, required, allowMultiple) {
|
||||||
|
'use strict';
|
||||||
|
return {
|
||||||
|
paramType: "query",
|
||||||
|
name: paramName,
|
||||||
|
description: description,
|
||||||
|
dataType: dataType,
|
||||||
|
required: required,
|
||||||
|
allowMultiple: allowMultiple
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
constructErrorResponseDoc = function (code, reason) {
|
||||||
|
'use strict';
|
||||||
|
return {
|
||||||
|
code: code,
|
||||||
|
reason: reason
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.constructUrlObject = constructUrlObject;
|
||||||
|
exports.constructNickname = constructNickname;
|
||||||
|
exports.constructRoute = constructRoute;
|
||||||
|
exports.constructPathParamDoc = constructPathParamDoc;
|
||||||
|
exports.constructQueryParamDoc = constructQueryParamDoc;
|
||||||
|
exports.constructErrorResponseDoc = constructErrorResponseDoc;
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*jslint indent: 2, nomen: true, maxlen: 120 */
|
||||||
|
/*global module, require, exports */
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Foxx Request Context
|
||||||
|
///
|
||||||
|
/// @file
|
||||||
|
///
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2013 triagens GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Lucas Dohmen
|
||||||
|
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var RequestContext,
|
||||||
|
extend = require("underscore").extend,
|
||||||
|
internal = require("org/arangodb/foxx/internals");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JSF_foxx_RequestContext_initializer
|
||||||
|
/// @brief Context of a Request Definition
|
||||||
|
///
|
||||||
|
/// Used for documenting and constraining the routes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
RequestContext = function (route) {
|
||||||
|
'use strict';
|
||||||
|
this.route = route;
|
||||||
|
this.typeToRegex = {
|
||||||
|
"int": "/[0-9]+/",
|
||||||
|
"string": "/.+/"
|
||||||
|
};
|
||||||
|
this.route.docs.nickname = internal.constructNickname(route.docs.httpMethod, route.url.match);
|
||||||
|
};
|
||||||
|
|
||||||
|
extend(RequestContext.prototype, {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JSF_foxx_RequestContext_pathParam
|
||||||
|
/// @brief Describe a path parameter
|
||||||
|
///
|
||||||
|
/// meow
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
pathParam: function (paramName, attributes) {
|
||||||
|
'use strict';
|
||||||
|
var url = this.route.url,
|
||||||
|
docs = this.route.docs,
|
||||||
|
constraint = url.constraint || {};
|
||||||
|
|
||||||
|
constraint[paramName] = this.typeToRegex[attributes.dataType];
|
||||||
|
this.route.url = internal.constructUrlObject(url.match, constraint, url.methods[0]);
|
||||||
|
this.route.docs.parameters.push(internal.constructPathParamDoc(
|
||||||
|
paramName,
|
||||||
|
attributes.description,
|
||||||
|
attributes.dataType
|
||||||
|
));
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JSF_foxx_RequestContext_queryParam
|
||||||
|
/// @brief Describe a Query Parameter
|
||||||
|
///
|
||||||
|
/// @FUN{FoxxApplication::queryParam(@FA{id}, @FA{options})}
|
||||||
|
///
|
||||||
|
/// Describe a query parameter:
|
||||||
|
///
|
||||||
|
/// If you defined a route "/foxx", you can constrain which format a query
|
||||||
|
/// parameter (`/foxx?a=12`) can have by giving it a type. We currently support
|
||||||
|
/// the following types:
|
||||||
|
///
|
||||||
|
/// * int
|
||||||
|
/// * string
|
||||||
|
///
|
||||||
|
/// You can also provide a description of this parameter, if it is required and
|
||||||
|
/// if you can provide the parameter multiple times.
|
||||||
|
///
|
||||||
|
/// @EXAMPLES
|
||||||
|
///
|
||||||
|
/// @code
|
||||||
|
/// app.get("/foxx", function {
|
||||||
|
/// // Do something
|
||||||
|
/// }).queryParam("id", {
|
||||||
|
/// description: "Id of the Foxx",
|
||||||
|
/// dataType: "int",
|
||||||
|
/// required: true,
|
||||||
|
/// allowMultiple: false
|
||||||
|
/// });
|
||||||
|
/// @endcode
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
queryParam: function (paramName, attributes) {
|
||||||
|
'use strict';
|
||||||
|
this.route.docs.parameters.push(internal.constructQueryParamDoc(
|
||||||
|
paramName,
|
||||||
|
attributes.description,
|
||||||
|
attributes.dataType,
|
||||||
|
attributes.required,
|
||||||
|
attributes.allowMultiple
|
||||||
|
));
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JSF_foxx_RequestContext_summary
|
||||||
|
/// @brief Set the summary for this route in the documentation
|
||||||
|
///
|
||||||
|
/// @FUN{FoxxApplication::summary(@FA{description})}
|
||||||
|
///
|
||||||
|
/// Set the summary for this route in the documentation. Can't be longer than 60.
|
||||||
|
/// characters
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
summary: function (summary) {
|
||||||
|
'use strict';
|
||||||
|
if (summary.length > 60) {
|
||||||
|
throw new Error("Summary can't be longer than 60 characters");
|
||||||
|
}
|
||||||
|
this.route.docs.summary = summary;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JSF_foxx_RequestContext_notes
|
||||||
|
/// @brief Set the notes for this route in the documentation
|
||||||
|
///
|
||||||
|
/// @FUN{FoxxApplication::notes(@FA{description})}
|
||||||
|
///
|
||||||
|
/// Set the notes for this route in the documentation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
notes: function (notes) {
|
||||||
|
'use strict';
|
||||||
|
this.route.docs.notes = notes;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @fn JSF_foxx_RequestContext_errorResponse
|
||||||
|
/// @brief Document an error response
|
||||||
|
///
|
||||||
|
/// @FUN{FoxxApplication::errorResponse(@FA{code}, @FA{description})}
|
||||||
|
///
|
||||||
|
/// Document the error response for a given error @FA{code} with a reason for
|
||||||
|
/// the occurrence.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
errorResponse: function (code, reason) {
|
||||||
|
'use strict';
|
||||||
|
this.route.docs.errorResponses.push(internal.constructErrorResponseDoc(code, reason));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
exports.RequestContext = RequestContext;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- END-OF-FILE
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Local Variables:
|
||||||
|
/// mode: outline-minor
|
||||||
|
/// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
|
||||||
|
/// End:
|
Loading…
Reference in New Issue