1
0
Fork 0

Improved the documentation for Foxx controller

This commit is contained in:
Michael Hackstein 2015-08-18 16:14:39 +02:00
parent 580066fe8a
commit 602c3d0d59
6 changed files with 282 additions and 158 deletions

View File

@ -1,4 +1,4 @@
!CHAPTER Details on FoxxController !CHAPTER Details on Controller
!SUBSECTION Create !SUBSECTION Create
<!-- js/server/modules/org/arangodb/foxx/controller.js --> <!-- js/server/modules/org/arangodb/foxx/controller.js -->
@ -86,12 +86,16 @@ API by chaining the following methods onto your path definition:
<!-- js/server/modules/org/arangodb/foxx/request_context.js --> <!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContext_notes @startDocuBlock JSF_foxx_RequestContext_notes
!SUBSECTION pathParams in buffer
@startDocuBlock JSF_foxx_RequestContextBuffer_pathParam
!SUBSECTION bodyParams in buffer !SUBSECTION extend
@startDocuBlock JSF_foxx_RequestContextBuffer_queryParam
In many use-cases several of the functions are always used in a certain combination (e.g.: `onlyIf` with `errorResponse`).
In order to avoid duplicating this equal usage for several routes in your application you can
extend the controller with your own functions.
These functions can simply combine several of the above on a single name, so you only have to
invoke your self defined single function on all routes using these extensions.
@startDocuBlock JSF_foxx_controller_extend
!SECTION Documenting and constraining all routes !SECTION Documenting and constraining all routes
@ -123,18 +127,24 @@ ctrl.get('/another/route', function (req, res) {
}); // no errorResponse needed here either }); // no errorResponse needed here either
``` ```
!SUBSECTION Buffer errorResponse !SUBSECTION errorResponse
<!-- js/server/modules/org/arangodb/foxx/request_context.js --> <!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_errorResponse @startDocuBlock JSF_foxx_RequestContextBuffer_errorResponse
!SUBSECTION Buffer onlyIf !SUBSECTION onlyIf
<!-- js/server/modules/org/arangodb/foxx/request_context.js --> <!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_onlyIf @startDocuBlock JSF_foxx_RequestContextBuffer_onlyIf
!SUBSECTION Buffer onlyIfAuthenticated !SUBSECTION onlyIfAuthenticated
<!-- js/server/modules/org/arangodb/foxx/request_context.js --> <!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_onlyIfAuthenticated @startDocuBlock JSF_foxx_RequestContextBuffer_onlyIfAuthenticated
!SUBSECTION pathParam
@startDocuBlock JSF_foxx_RequestContextBuffer_pathParam
!SUBSECTION bodyParam
@startDocuBlock JSF_foxx_RequestContextBuffer_queryParam
!SECTION Before and After Hooks !SECTION Before and After Hooks
@ -222,9 +232,6 @@ convenience methods:
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js --> <!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_rawBodyBuffer @startDocuBlock JSF_foxx_BaseMiddleware_request_rawBodyBuffer
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_requestParts
!SUBSECTION params !SUBSECTION params
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js --> <!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_params @startDocuBlock JSF_foxx_BaseMiddleware_request_params
@ -233,6 +240,10 @@ convenience methods:
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js --> <!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_cookie @startDocuBlock JSF_foxx_BaseMiddleware_request_cookie
!SUBSECTION requestParts
Only useful for multi-part requests.
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_requestParts
!SECTION The Response Object !SECTION The Response Object
@ -341,6 +352,3 @@ To use the application-specific authentication in your own app, first activate i
!SUBSUBSECTION Restricting routes !SUBSUBSECTION Restricting routes
To restrict routes, see the documentation for Documenting and Restraining the routes. To restrict routes, see the documentation for Documenting and Restraining the routes.
@startDocuBlock JSF_foxx_controller_extend

View File

@ -1,3 +0,0 @@
@startDocuBlock JSF_foxx_TemplateMiddleware_initializer
@startDocuBlock JSF_foxx_TemplateMiddleware_response_render

View File

@ -5,7 +5,7 @@
* [Windows](Installing/Windows.md) * [Windows](Installing/Windows.md)
* [Compiling](Installing/Compiling.md) * [Compiling](Installing/Compiling.md)
* [Upgrading](Installing/Upgrading.md) * [Upgrading](Installing/Upgrading.md)
* [Incompatible changes in 2.6](Upgrading/UpgradingChanges27.md) * [Incompatible changes in 2.7](Upgrading/UpgradingChanges27.md)
* [Incompatible changes in 2.6](Upgrading/UpgradingChanges26.md) * [Incompatible changes in 2.6](Upgrading/UpgradingChanges26.md)
* [Upgrading to 2.6](Upgrading/Upgrading26.md) * [Upgrading to 2.6](Upgrading/Upgrading26.md)
* [Incompatible changes in 2.5](Upgrading/UpgradingChanges25.md) * [Incompatible changes in 2.5](Upgrading/UpgradingChanges25.md)
@ -112,7 +112,6 @@
* [Controller](Foxx/Develop/Controller.md) * [Controller](Foxx/Develop/Controller.md)
* [Scripts](Foxx/Develop/Scripts.md) * [Scripts](Foxx/Develop/Scripts.md)
* [Model](Foxx/Develop/Model.md) * [Model](Foxx/Develop/Model.md)
* [View](Foxx/Develop/View.md)
* [Repository](Foxx/Develop/Repository.md) * [Repository](Foxx/Develop/Repository.md)
* [Queries](Foxx/Develop/Queries.md) * [Queries](Foxx/Develop/Queries.md)
* [Sessions](Foxx/Develop/Sessions.md) * [Sessions](Foxx/Develop/Sessions.md)

View File

@ -275,7 +275,7 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_initializer /// @startDocuBlock JSF_foxx_controller_initializer
/// ///
/// `new FoxxController(applicationContext, options)` /// `new Controller(applicationContext, options)`
/// ///
/// This creates a new Controller. The first argument is the controller /// This creates a new Controller. The first argument is the controller
/// context available in the variable *applicationContext*. The second one is an /// context available in the variable *applicationContext*. The second one is an
@ -417,11 +417,25 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_head /// @startDocuBlock JSF_foxx_controller_head
/// ///
/// `FoxxController#head(path, callback)` /// `Controller.head(path, callback)`
///
/// Defines a new route on `path` that handles requests from the HTTP verb `head`.
/// This route can also be 'parameterized' like `/goose/:barn`.
/// In this case you can later get the value the user provided for `barn`
/// via the `params` function in the `request`.
/// The function defined in `callback` will be invoked whenever this type of
/// request is recieved.
/// `callback` get's two arguments `request` and `response`, see below for further
/// information about these objects.
///
/// @EXAMPLES
///
/// ```js
/// app.head('/goose/barn', function (req, res) {
/// // Take this request and deal with it!
/// });
/// ```
/// ///
/// This handles requests from the HTTP verb *head*. You have to give a
/// function as *callback*. It will get a request and response object as its
/// arguments
/// @endDocuBlock /// @endDocuBlock
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -432,14 +446,16 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_get /// @startDocuBlock JSF_foxx_controller_get
/// ///
/// `FoxxController#get(path, callback)` /// `Controller.get(path, callback)`
/// ///
/// This handles requests from the HTTP verb *get*. /// Defines a new route on `path` that handles requests from the HTTP verb `get`.
/// /// This route can also be 'parameterized' like `/goose/:barn`.
/// When defining a route you can also define a so called 'parameterized' /// In this case you can later get the value the user provided for `barn`
/// *path* like */goose/:barn*. In this case you can later get the value /// via the `params` function in the `request`.
/// the user provided for *barn* via the *params* function (see the Request /// The function defined in `callback` will be invoked whenever this type of
/// object). /// request is recieved.
/// `callback` get's two arguments `request` and `response`, see below for further
/// information about these objects.
/// ///
/// @EXAMPLES /// @EXAMPLES
/// ///
@ -459,10 +475,16 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_post /// @startDocuBlock JSF_foxx_controller_post
/// ///
/// `FoxxController#post(path, callback)` /// `Controller.post(path, callback)`
/// ///
/// This handles requests from the HTTP verb *post*. See above for the /// Defines a new route on `path` that handles requests from the HTTP verb `post`.
/// arguments you can give. /// This route can also be 'parameterized' like `/goose/:barn`.
/// In this case you can later get the value the user provided for `barn`
/// via the `params` function in the `request`.
/// The function defined in `callback` will be invoked whenever this type of
/// request is recieved.
/// `callback` get's two arguments `request` and `response`, see below for further
/// information about these objects.
/// ///
/// @EXAMPLES /// @EXAMPLES
/// ///
@ -482,10 +504,16 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_put /// @startDocuBlock JSF_foxx_controller_put
/// ///
/// `FoxxController#put(path, callback)` /// `Controller.put(path, callback)`
/// ///
/// This handles requests from the HTTP verb *put*. See above for the arguments /// Defines a new route on `path` that handles requests from the HTTP verb `put`.
/// you can give. /// This route can also be 'parameterized' like `/goose/:barn`.
/// In this case you can later get the value the user provided for `barn`
/// via the `params` function in the `request`.
/// The function defined in `callback` will be invoked whenever this type of
/// request is recieved.
/// `callback` get's two arguments `request` and `response`, see below for further
/// information about these objects.
/// ///
/// @EXAMPLES /// @EXAMPLES
/// ///
@ -505,10 +533,16 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_patch /// @startDocuBlock JSF_foxx_controller_patch
/// ///
/// `FoxxController#patch(path, callback)` /// `Controller.patch(path, callback)`
/// ///
/// This handles requests from the HTTP verb *patch*. See above for the /// Defines a new route on `path` that handles requests from the HTTP verb `patch`.
/// arguments you can give. /// This route can also be 'parameterized' like `/goose/:barn`.
/// In this case you can later get the value the user provided for `barn`
/// via the `params` function in the `request`.
/// The function defined in `callback` will be invoked whenever this type of
/// request is recieved.
/// `callback` get's two arguments `request` and `response`, see below for further
/// information about these objects.
/// ///
/// @EXAMPLES /// @EXAMPLES
/// ///
@ -528,10 +562,16 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_delete /// @startDocuBlock JSF_foxx_controller_delete
/// ///
/// `FoxxController#delete(path, callback)` /// `Controller.delete(path, callback)`
/// ///
/// This handles requests from the HTTP verb *delete*. See above for the /// Defines a new route on `path` that handles requests from the HTTP verb `delete`.
/// arguments you can give. /// This route can also be 'parameterized' like `/goose/:barn`.
/// In this case you can later get the value the user provided for `barn`
/// via the `params` function in the `request`.
/// The function defined in `callback` will be invoked whenever this type of
/// request is recieved.
/// `callback` get's two arguments `request` and `response`, see below for further
/// information about these objects.
/// ///
/// @EXAMPLES /// @EXAMPLES
/// ///
@ -556,14 +596,16 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_before /// @startDocuBlock JSF_foxx_controller_before
/// ///
/// `FoxxController#before(path, callback)` /// `Controller.before(path, callback)`
/// ///
/// The before function takes a *path* on which it should watch and a /// Defines an additional function on the route `path` which will be executed
/// function that it should execute before the routing takes place. If you do /// before the callback defined for a specific HTTP verb is executed.
/// omit the path, the function will be executed before each request, no matter /// The `callback` function has the same signature as the `callback` in the
/// the path. Your function gets a Request and a Response object. /// specific route.
/// You can also omit the `path`, in this case `callback` will be executed
/// before handleing any request in this Controller.
/// ///
/// If your callback returns the Boolean value *false*, the route handling /// If `callback` returns the Boolean value `false`, the route handling
/// will not proceed. You can use this to intercept invalid or unauthorized /// will not proceed. You can use this to intercept invalid or unauthorized
/// requests and prevent them from being passed to the matching routes. /// requests and prevent them from being passed to the matching routes.
/// ///
@ -601,10 +643,10 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_after /// @startDocuBlock JSF_foxx_controller_after
/// ///
/// `FoxxController#after(path, callback)` /// `Controller.after(path, callback)`
/// ///
/// This works pretty similar to the before function. But it acts after the /// Similar to `Controller.before(path, callback)` but `callback` will be invoked
/// execution of the handlers (Big surprise, I suppose). /// after the request is handled in the specific route.
/// ///
/// @EXAMPLES /// @EXAMPLES
/// ///
@ -635,14 +677,17 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_around /// @startDocuBlock JSF_foxx_controller_around
/// ///
/// `FoxxController#around(path, callback)` /// `Controller.around(path, callback)`
/// ///
/// The around function takes a *path* on which it should watch and a function /// Similar to `Controller.before(path, callback)` `callback` will be invoked
/// that it should execute around the function which normally handles the /// instead of the specific handler.
/// route. If you do omit the path, the function will be executed before each /// `callback` takes two additional paramaters `opts` and `next` where
/// request, no matter the path. Your function gets a Request and a Response /// `opts` contains options assigned to the route and `next` is a function.
/// object and a next function, which you must call to execute the handler for /// Whenever you call `next` in `callback` the specific handler is invoked,
/// that route. /// if you do not call `next` the specific handler will not be invoked at all.
/// So using around you can execute code before and after a specific handler
/// and even call the handler only under certain circumstances.
/// If you omit `path` `callback` will be called on every request.
/// ///
/// @EXAMPLES /// @EXAMPLES
/// ///
@ -677,10 +722,10 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_activateAuthentication /// @startDocuBlock JSF_foxx_controller_activateAuthentication
/// ///
/// `FoxxController#activateAuthentication(opts)` /// `Controller.activateAuthentication(opts)`
/// ///
/// To activate authentication for this controller, first call this function. /// To activate authentication for this controller, call this function before defining any routes.
/// Provide the following arguments: /// In the `opts` object you can set the following keys:
/// ///
/// * *type*: Currently we only support *cookie*, but this will change in the future /// * *type*: Currently we only support *cookie*, but this will change in the future
/// * *cookieLifetime*: An integer. Lifetime of cookies in seconds /// * *cookieLifetime*: An integer. Lifetime of cookies in seconds
@ -712,10 +757,10 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_activateSessions /// @startDocuBlock JSF_foxx_controller_activateSessions
/// ///
/// `FoxxController#activateAuthentication(opts)` /// `Controller.activateSessions(opts)`
/// ///
/// To activate sessions for this sessions, first call this function. /// To activate sessions for this controller, call this function before defining any routes.
/// Provide the following arguments: /// In the `opts` object you can set the following keys:
/// ///
/// * *type*: Currently we only support *cookie*, but this will change in the future. Defaults to *"cookie"*. /// * *type*: Currently we only support *cookie*, but this will change in the future. Defaults to *"cookie"*.
/// * *cookieName*: A string used as the name of the cookie. Defaults to *"sid"*. /// * *cookieName*: A string used as the name of the cookie. Defaults to *"sid"*.
@ -737,6 +782,7 @@ class Controller {
/// ///
/// @endDocuBlock /// @endDocuBlock
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
activateSessions(opts) { activateSessions(opts) {
var sessions = require('org/arangodb/foxx/sessions'); var sessions = require('org/arangodb/foxx/sessions');
_.extend(this, sessionControllerProps); _.extend(this, sessionControllerProps);
@ -748,11 +794,11 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_apiDocumentation /// @startDocuBlock JSF_foxx_controller_apiDocumentation
/// ///
/// `FoxxController#apiDocumentation(path, [opts])` /// `Controller.apiDocumentation(path, [opts])`
/// ///
/// Mounts the API documentation (Swagger) at the given *path*. /// Mounts the API documentation (Swagger) at the given `path`.
/// ///
/// Note that the **path** can use URL parameters as usual but must not use any /// Note that the `path` can use URL parameters as usual but must not use any
/// wildcard (`*`) or optional (`:name?`) parameters. /// wildcard (`*`) or optional (`:name?`) parameters.
/// ///
/// The optional **opts** can be an object with any of the following properties: /// The optional **opts** can be an object with any of the following properties:
@ -819,12 +865,49 @@ class Controller {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_controller_extend /// @startDocuBlock JSF_foxx_controller_extend
/// ///
/// `FoxxController#extend(extensions)` /// `Controller.extend(extensions)`
///
/// Extends all functions to define routes in this controller.
/// This allows to combine several route extensions with the invocation
/// of a single function.
/// This is especially useful if you use the same input parameter in several routes of
/// your controller and want to apply the same validation, documentation and error handling
/// for it.
///
/// The `extensions` parameter is a JSON object with arbitrary keys.
/// Each key is used as the name of the function you want to define (you cannot overwrite
/// internal functions like `pathParam`) and the value is a function that will be invoked.
/// This function can get arbitrary many arguments and the `this` of the function is bound
/// to the route definition object (e.g. you can use `this.pathParam()`).
/// Your newly defined function is chainable similar to the internal functions.
/// ///
/// **Examples** /// **Examples**
/// ///
/// Define a validator for a queryParameter, including documentation and errorResponses
/// in a single command:
///
/// ```js
/// controller.extend({
/// myParam: function (maxValue) {
/// this.queryParam("value", {type: joi.number().required()});
/// this.onlyIf(function(req) {
/// var v = req.param("value");
/// if (v > maxValue) {
/// throw new NumberTooLargeError();
/// }
/// });
/// this.errorResponse(NumberTooLargeError, 400, "The given value is too large");
/// }
/// });
///
/// controller.get("/goose/barn", function(req, res) {
/// // Will only be invoked if the request has parameter value and it is less or equal 5.
/// }).myParam(5);
/// ```
///
/// @endDocuBlock /// @endDocuBlock
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
extend(extensions) { extend(extensions) {
var attr; var attr;
var extensionWrapper = function(scope, functionName) { var extensionWrapper = function(scope, functionName) {

View File

@ -146,8 +146,15 @@ class RequestContext {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContext_pathParam /// @startDocuBlock JSF_foxx_RequestContext_pathParam
/// ///
/// If you defined a route "/foxx/:id", you can constrain which format a path /// `Route.pathParam(id, options)`
/// parameter (*/foxx/12*) can have by giving it a *joi* type. ///
/// If you defined a route "/foxx/:name", containing a parameter called `name` you can
/// constrain which format this parameter is allowed to have.
/// This format is defined using *joi* in the `options` parameter.
/// Using this function will at first allow you to access this parameter in your
/// route handler using `req.params(id)`, will reject any request having a paramter
/// that does not match the *joi* definition and creates a documentation for this
/// parameter in ArangoDBs WebInterface.
/// ///
/// For more information on *joi* see [the official Joi documentation](https://github.com/spumko/joi). /// For more information on *joi* see [the official Joi documentation](https://github.com/spumko/joi).
/// ///
@ -162,20 +169,20 @@ class RequestContext {
/// *Examples* /// *Examples*
/// ///
/// ```js /// ```js
/// app.get("/foxx/:id", function { /// app.get("/foxx/:name", function {
/// // Do something /// // Do something
/// }).pathParam("id", joi.number().integer().required().description("Id of the Foxx")); /// }).pathParam("name", joi.number().integer().required().description("Name of the Foxx"));
/// ``` /// ```
/// ///
/// You can also pass in a configuration object instead: /// You can also pass in a configuration object instead:
/// ///
/// ```js /// ```js
/// app.get("/foxx/:id", function { /// app.get("/foxx/:name", function {
/// // Do something /// // Do something
/// }).pathParam("id", { /// }).pathParam("name", {
/// type: joi.number().integer(), /// type: joi.number().integer(),
/// required: true, /// required: true,
/// description: "Id of the Foxx" /// description: "Name of the Foxx"
/// }); /// });
/// ``` /// ```
/// @endDocuBlock /// @endDocuBlock
@ -243,12 +250,16 @@ class RequestContext {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContext_queryParam /// @startDocuBlock JSF_foxx_RequestContext_queryParam
/// ///
/// `FoxxController#queryParam(id, options)` /// `Route.queryParam(id, options)`
/// ///
/// Describe a query parameter: /// Describe a query parameter:
/// ///
/// If you defined a route "/foxx", you can constrain which format a query /// If you defined a route "/foxx", you can allow a query paramter with the
/// parameter (*/foxx?a=12*) can have by giving it a *joi* type. /// name `id` on it and constrain the format of this parameter by giving it a *joi* type in the `options` parameter.
/// Using this function will at first allow you to access this parameter in your
/// route handler using `req.params(id)`, will reject any request having a paramter
/// that does not match the *joi* definition and creates a documentation for this
/// parameter in ArangoDBs WebInterface.
/// ///
/// For more information on *joi* see [the official Joi documentation](https://github.com/spumko/joi). /// For more information on *joi* see [the official Joi documentation](https://github.com/spumko/joi).
/// ///
@ -360,29 +371,29 @@ class RequestContext {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContext_bodyParam /// @startDocuBlock JSF_foxx_RequestContext_bodyParam
/// ///
/// `FoxxController#bodyParam(paramName, options)` /// `Route.bodyParam(paramName, options)`
/// ///
/// Expect the body of the request to be a JSON with the attributes you annotated /// Defines that this route expects a JSON body when requested and binds it to
/// in your model. It will appear alongside the provided description in your /// a pseudo parameter with the name `paramName`.
/// Documentation. /// The body can than be read in the the handler using `req.params(paramName)` on the request object.
/// This will initialize a *Model* with the data and provide it to you via the /// In the `options` parameter you can define how a valid request body should look like.
/// params as *paramName*. /// This definition can be done in two ways, either using *joi* directly.
/// Accessing the body in this case will give you a JSON object.
/// The other way is to use a Foxx *Model*.
/// Accessing the body in this case will give you an instance of this Model.
/// For both ways an entry for the body will be added in the Documentation in ArangoDBs WebInterface.
/// For information about how to annotate your models, see the Model section. /// For information about how to annotate your models, see the Model section.
/// If you provide the Model in an array, the response will take multiple models /// All requests sending a body that does not match the validation given this way
/// instead of one. /// will automatically be rejected.
/// ///
/// If you wrap the provided model in an array, the body param is always an array /// You can also wrap the definition into an array, in this case this route
/// and accordingly the return value of the *params* for the body call will also /// expects a body of type array containing arbitrary many valid objects.
/// return an array of models. /// Accessing the body parameter will then of course return an array of objects.
/// ///
/// Alternatively you can provide a joi schema instead of a model to allow /// Note: The behavior of `bodyParam` changes depending on the `rootElement` option
/// arbitrary data. When using a joi schema or a model that has a joi schema, /// set in the [manifest](../Develop/Manifest.md). If it is set to `true`, it is
/// well-formed request bodies will be rejected if they don't pass schema validation.
///
/// The behavior of *bodyParam* changes depending on the *rootElement* option
/// set in the [manifest](../Develop/Manifest.md). If it is set to true, it is
/// expected that the body is an /// expected that the body is an
/// object with a key of the same name as the *paramName* argument. /// object with a key of the same name as the `paramName` argument.
/// The value of this object is either a single object or in the case of a multi /// The value of this object is either a single object or in the case of a multi
/// element an array of objects. /// element an array of objects.
/// ///
@ -506,10 +517,37 @@ class RequestContext {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContext_summary /// @startDocuBlock JSF_foxx_RequestContext_summary
/// ///
/// `FoxxController#summary(description)` /// `Route.summary(description)`
/// ///
/// Set the summary for this route in the documentation. /// Set the summary for this route in the documentation.
/// Can't be longer than 8192 characters /// Can't be longer than 8192 characters.
/// This is equal to using JavaDoc style comments right above your function.
/// If you provide both comment and `summary()` the call to `summary()` wins
/// and will be used.
///
/// *Examples*
///
/// Version with comment:
///
/// ```js
/// /** Short description
/// *
/// * Longer description
/// * with multiple lines
/// */
/// app.get("/foxx", function() {
/// });
/// ```
///
/// is identical to:
///
/// ```js
/// app.get("/foxx", function() {
/// })
/// .summary("Short description")
/// .notes(["Longer description", "with multiple lines"]);
/// ```
///
/// @endDocuBlock /// @endDocuBlock
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -524,9 +562,33 @@ class RequestContext {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContext_notes /// @startDocuBlock JSF_foxx_RequestContext_notes
/// ///
/// `FoxxController#notes(...description)` /// `Route.notes(...description)`
///
/// Set the long description for this route in the documentation
//
/// *Examples*
///
/// Version with comment:
///
/// ```js
/// /** Short description
/// *
/// * Longer description
/// * with multiple lines
/// */
/// app.get("/foxx", function() {
/// });
/// ```
///
/// is identical to:
///
/// ```js
/// app.get("/foxx", function() {
/// })
/// .summary("Short description")
/// .notes(["Longer description", "with multiple lines"]);
/// ```
/// ///
/// Set the notes for this route in the documentation
/// @endDocuBlock /// @endDocuBlock
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -539,15 +601,16 @@ class RequestContext {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContext_errorResponse /// @startDocuBlock JSF_foxx_RequestContext_errorResponse
/// ///
/// `FoxxController#errorResponse(errorClassOrName, code, description)` /// `Route.errorResponse(errorClassOrName, code, description, [callback])`
/// ///
/// Define a reaction to a thrown error for this route: If your handler throws an error /// Define a reaction to a thrown error for this route: If your handler throws an error
/// of the errorClass or with the name, it will be caught and the response will have the given /// of the errorClass defined in `errorClassOrName` or the error has an attribute `name` equal to `errorClassOrName`,
/// it will be caught and the response object will be filled with the given
/// status code and a JSON with error set to your description as the body. /// status code and a JSON with error set to your description as the body.
/// ///
/// If you want more control over the returned JSON, you can give an optional fourth /// If you want more control over the returned JSON, you can give an optional fourth
/// parameter in form of a function. It gets the error as an argument, the return /// parameter in form of a function. It gets the error as an argument, the return
/// value will transformed into JSON and then be used as the body. /// value will be transformed into JSON and then be used as the body.
/// The status code will be used as described above. The description will be used for /// The status code will be used as described above. The description will be used for
/// the documentation. /// the documentation.
/// ///
@ -593,11 +656,14 @@ class RequestContext {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContext_onlyIf /// @startDocuBlock JSF_foxx_RequestContext_onlyIf
/// ///
/// `FoxxController#onlyIf(check)` /// `Route.onlyIf(check)`
/// ///
/// Provide it with a function that throws an exception if the normal processing should /// This functionality is used to secure a route by applying a checking function
/// not be executed. Provide an `errorResponse` to define the behavior in this case. /// on the request beforehand, for example the check authorization.
/// This can be used for authentication or authorization for example. /// It expects `check` to be a function that takes the request object as first parameter.
/// This function is executed before the actual handler is invoked.
/// If `check` throws an error the actual handler will not be invoked.
/// Remember to provide an `errorResponse` on the route as well to define the behavior in this case.
/// ///
/// *Examples* /// *Examples*
/// ///
@ -680,40 +746,31 @@ _.each([
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContextBuffer_pathParam /// @startDocuBlock JSF_foxx_RequestContextBuffer_pathParam
/// ///
/// If you defined a route "/foxx/:id", you can constrain which format a path /// `Controller.allRoutes.pathParam(id, options)`
/// parameter (*/foxx/12*) can have by giving it a *joi* type.
/// ///
/// For more information on *joi* see [the official Joi documentation](https://github.com/spumko/joi). /// This is equal to invoking `Route.pathParam` on all routes bound to this controller.
///
/// *Parameter*
///
/// * *id*: name of the param.
/// * *options*: a joi schema or an object with the following properties:
/// * *type*: a joi schema.
/// * *description*: documentation description for the parameter.
/// * *required* (optional): whether the parameter is required. Default: determined by *type*.
/// ///
/// *Examples* /// *Examples*
/// ///
/// ```js /// ```js
/// app.allroutes.pathParam("id", joi.number().integer().required().description("Id of the Foxx")); /// app.allRoutes.pathParam("id", joi.number().integer().required().description("Id of the Foxx"));
/// ///
/// app.get("/foxx/:id", function { /// app.get("/foxx/:id", function {
/// // Do something /// // Secured by pathParam
/// }); /// });
/// ``` /// ```
/// ///
/// You can also pass in a configuration object instead: /// You can also pass in a configuration object instead:
/// ///
/// ```js /// ```js
/// app.allroutes.pathParam("id", { /// app.allRoutes.pathParam("id", {
/// type: joi.number().integer(), /// type: joi.number().integer(),
/// required: true, /// required: true,
/// description: "Id of the Foxx" /// description: "Id of the Foxx"
/// }); /// });
/// ///
/// app.get("/foxx/:id", function { /// app.get("/foxx/:id", function {
/// // Do something /// // Secured by pathParam
/// }); /// });
/// ``` /// ```
/// @endDocuBlock /// @endDocuBlock
@ -722,26 +779,9 @@ _.each([
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContextBuffer_queryParam /// @startDocuBlock JSF_foxx_RequestContextBuffer_queryParam
/// ///
/// `FoxxController#queryParam(id, options)` /// `Controller.allRoutes.queryParam(id, options)`
/// ///
/// Describe a query parameter: /// This is equal to invoking `Route.queryParam` on all routes bound to this controller.
///
/// If you defined a route "/foxx", you can constrain which format a query
/// parameter (*/foxx?a=12*) can have by giving it a *joi* type.
///
/// For more information on *joi* see [the official Joi documentation](https://github.com/spumko/joi).
///
/// You can also provide a description of this parameter and
/// whether you can provide the parameter multiple times.
///
/// *Parameter*
///
/// * *id*: name of the parameter
/// * *options*: a joi schema or an object with the following properties:
/// * *type*: a joi schema
/// * *description*: documentation description for this param.
/// * *required* (optional): whether the param is required. Default: determined by *type*.
/// * *allowMultiple* (optional): whether the param can be specified more than once. Default: `false`.
/// ///
/// *Examples* /// *Examples*
/// ///
@ -777,15 +817,14 @@ _.each([
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContextBuffer_errorResponse /// @startDocuBlock JSF_foxx_RequestContextBuffer_errorResponse
/// ///
/// `RequestContextBuffer#errorResponse(errorClass, code, description)` /// `Controller.allRoutes.errorResponse(errorClass, code, description)`
/// ///
/// Defines an *errorResponse* for all routes of this controller. For details on /// This is equal to invoking `Route.errorResponse` on all routes bound to this controller.
/// *errorResponse* see the according method on routes.
/// ///
/// *Examples* /// *Examples*
/// ///
/// ```js /// ```js
/// app.allroutes.errorResponse(FoxxyError, 303, "This went completely wrong. Sorry!"); /// app.allRoutes.errorResponse(FoxxyError, 303, "This went completely wrong. Sorry!");
/// ///
/// app.get("/foxx", function { /// app.get("/foxx", function {
/// // Do something /// // Do something
@ -798,15 +837,14 @@ _.each([
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContextBuffer_onlyIf /// @startDocuBlock JSF_foxx_RequestContextBuffer_onlyIf
/// ///
/// `RequestContextBuffer#onlyIf(code, reason)` /// `Controller.allRoutes.onlyIf(code, reason)`
/// ///
/// Defines an *onlyIf* for all routes of this controller. For details on /// This is equal to invoking `Route.onlyIf` on all routes bound to this controller.
/// *onlyIf* see the according method on routes.
/// ///
/// *Examples* /// *Examples*
/// ///
/// ```js /// ```js
/// app.allroutes.onlyIf(myPersonalCheck); /// app.allRoutes.onlyIf(myPersonalCheck);
/// ///
/// app.get("/foxx", function { /// app.get("/foxx", function {
/// // Do something /// // Do something
@ -819,15 +857,14 @@ _.each([
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_RequestContextBuffer_onlyIfAuthenticated /// @startDocuBlock JSF_foxx_RequestContextBuffer_onlyIfAuthenticated
/// ///
/// `RequestContextBuffer#onlyIfAuthenticated(code, description)` /// `Controller.allRoutes.onlyIfAuthenticated(code, description)`
/// ///
/// Defines an *onlyIfAuthenticated* for all routes of this controller. For details on /// This is equal to invoking `Route.onlyIfAuthenticated` on all routes bound to this controller.
/// *onlyIfAuthenticated* see the according method on routes.
/// ///
/// *Examples* /// *Examples*
/// ///
/// ```js /// ```js
/// app.allroutes.onlyIfAuthenticated(401, "You need to be authenticated"); /// app.allRoutes.onlyIfAuthenticated(401, "You need to be authenticated");
/// ///
/// app.get("/foxx", function { /// app.get("/foxx", function {
/// // Do something /// // Do something

View File

@ -31,7 +31,7 @@ var db = require("org/arangodb").db,
_ = require("underscore"); _ = require("underscore");
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_TemplateMiddleware_initializer /// @start Docu Block JSF_foxx_TemplateMiddleware_initializer
/// ///
/// Initialize with the name of a collection or a collection and optionally /// Initialize with the name of a collection or a collection and optionally
/// a set of helper functions. /// a set of helper functions.
@ -48,7 +48,7 @@ var db = require("org/arangodb").db,
/// ///
/// app.before(templateMiddleware); /// app.before(templateMiddleware);
/// ``` /// ```
/// @endDocuBlock /// @end Docu Block
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function TemplateMiddleware(templateCollection, helper) { function TemplateMiddleware(templateCollection, helper) {
@ -59,7 +59,7 @@ function TemplateMiddleware(templateCollection, helper) {
responseFunctions = { responseFunctions = {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_TemplateMiddleware_response_render /// @start Docu Block JSF_foxx_TemplateMiddleware_response_render
/// ///
/// `response.render(templatePath, data)` /// `response.render(templatePath, data)`
/// ///
@ -74,7 +74,7 @@ function TemplateMiddleware(templateCollection, helper) {
/// ```js /// ```js
/// response.render("high/way", {username: 'Application'}) /// response.render("high/way", {username: 'Application'})
/// ``` /// ```
/// @endDocuBlock /// @end Docu Block
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
render: function (templatePath, data) { render: function (templatePath, data) {