diff --git a/Documentation/Books/Users/Foxx/FoxxExports.mdpp b/Documentation/Books/Users/Foxx/FoxxExports.mdpp new file mode 100644 index 0000000000..3e2d4cf196 --- /dev/null +++ b/Documentation/Books/Users/Foxx/FoxxExports.mdpp @@ -0,0 +1,86 @@ +!CHAPTER Working with Foxx exports + +Instead of (or in addition to) defining controllers, Foxx apps can also define exports. + +Foxx exports are not intended to replace regular npm modules. They simply allow you to make your app's collections and *applicationContext* available in other Foxx apps or bundling ArangoDB-specific modules in re-usable Foxx apps. + +!SECTION Define an export module + +In order to export modules in a Foxx app, you need to list the files in your manifest: + +```json +{ + "name": "foxx_exports_example", + "version": "1.0.0", + "description": "Demonstrates Foxx exports.", + "exports": { + "doodads": "./doodads.js", + "anotherModule": "./someOtherFilename.js" + } +} +``` + +The file *doodads.js* in the app's base path could look like this: + +```js +var Foxx = require('org/arangodb/foxx'); +var Doodad = Foxx.Model.extend({}, {}); +var doodadRepo = new Foxx.Repository( + applicationContext.collection('doodads'), + {model: Doodad} +); +exports.repo = doodadRepo; +exports.model = Doodad; +``` + +This module would then export the name "repo" bound to the variable *doodads* as well as the name "model" bound to the *Doodad* model. + +Note that the *applicationContext* is available to your Foxx exports just like in your Foxx controllers. + +**Warning** + +Foxx exports only support CommonJS exports using the special *exports* variable. Node-style exports via *module.exports* are not supported. + +!SECTION Import from another app + +In order to import from another app, you need to know where the app is mounted. + +Let's say we have mounted the example app above at */my-doodads*. We could now access the app's exports in another app like so: + +```js +var Foxx = require('org/arangodb/foxx'); +var doodads = Foxx.requireApp('/my-doodads').doodads; +var Doodad = doodads.model; +var doodadRepo = doodads.repo; + +// use the imported model and repository +var myDoodad = new Doodad(); +doodadRepo.save(myDoodad); +``` + +**Warning** + +When using Foxx exports in other apps, the load order of apps determines when which app's exports will become available. + +In order to use Foxx exports in another app's controllers it is recommended you use *controller.addInjector* to delay the import until all mounted apps have been loaded: + +```js +var Foxx = require('org/arangodb/foxx'); +var controller = new Foxx.Controller(applicationContext); +controller.addInjector({ + doodads: function() { + return Foxx.requireApp('/my-doodads').doodads; + } +}); + +// use the imported model and repository +controller.post('/doodads', function(request, response, injected) { + var myDoodad = new injected.doodads.model(); + injected.doodads.repo.save(myDoodad); + response.json(myDoodad.forClient()); +}); +``` + +There is currently no workaround to allow using one app's Foxx exports in another app's Foxx exports. + +If you don't need direct access to ArangoDB's functionality or the `applicationContext`, it is a better idea to use a regular npm module instead. \ No newline at end of file diff --git a/Documentation/Books/Users/Foxx/FoxxInjection.mdpp b/Documentation/Books/Users/Foxx/FoxxInjection.mdpp new file mode 100644 index 0000000000..bc8698a698 --- /dev/null +++ b/Documentation/Books/Users/Foxx/FoxxInjection.mdpp @@ -0,0 +1,71 @@ +!CHAPTER Foxx Dependency Injection + +If you have runtime dependencies you want to access in your route handlers but don't want to define at load time (e.g. dependencies between multiple Foxx apps), *FoxxController* allows you to inject these dependencies into your route handlers by adding injectors to it. + +!SECTION Add an injector + +Registers a dependency factory with the controller. + +`controller.addInjector(name, factory)` + +The injected dependency will be available as a property with the chosen *name* on the third argument passed to each route handler. + +If *factory* is a function, it will be called the first time a route of that controller is handled and its result will be injected into each route handler. Otherwise the value will be injected as it is. + +If you want to inject a function as a dependency, you need to wrap it in a function. + +*Parameter* + +* *name*: the name under which the dependency will be available in the route handler. +* *factory*: a function returning the dependency or an arbitrary value that will be passed as-is. + +@EXAMPLES + +```js +function myFunc() { + return 'Hello'; +} +controller.addInjector('something', function() {return 2;}); +controller.addInjector('other', 'just a string'); +controller.addInjector('fn', function() {return myFunc;}); + +controller.get('/some/route', function(request, response, injected) { + response.json({ + something: injected.something, // 2 + other: injected.other, // 'just a string' + fn: injected.fn.name // 'myFunc' + }); +}); +``` + +!SECTION Add multiple injectors + +Registers multiple dependency factories with the controller. + +`controller.addInjector(object)` + +Equivalent to calling *addInjector(name, value)* for each property of the object. + +*Parameter* + +* *object*: an object mapping dependency names to dependency factories. + +@EXAMPLES + +```js +function myFunc() { + return 'Hello'; +} +controller.addInjector({ + something: function() {return 2;}, + other: 'just a string', + fn: function() {return myFunc;} +}); + +controller.get('/some/route', function(request, response, injected) { + response.json({ + something: injected.something, // 2 + other: injected.other, // 'just a string' + fn: injected.fn.name // 'myFunc' + }); +}); \ No newline at end of file diff --git a/Documentation/Books/Users/Foxx/FoxxManifest.mdpp b/Documentation/Books/Users/Foxx/FoxxManifest.mdpp index dc53051334..42d6449477 100644 --- a/Documentation/Books/Users/Foxx/FoxxManifest.mdpp +++ b/Documentation/Books/Users/Foxx/FoxxManifest.mdpp @@ -8,6 +8,7 @@ attributes are required though): * *author*: The author name * *contributors*: An array containing objects, each represents a contributor (with *name* and optional *email*) * *controllers*: Map routes to FoxxControllers +* *exports*: Map names to Foxx exports * *defaultDocument*: The default document when the applicated root (*/*) is called (defaults to *index.html*) * *description*: A short description of the application (Meta information) * *engines*: Should be an object with *arangodb* set to the ArangoDB version your Foxx app is compatible with. diff --git a/Documentation/Books/Users/SUMMARY.md b/Documentation/Books/Users/SUMMARY.md index 702474347d..2e151a1a6e 100644 --- a/Documentation/Books/Users/SUMMARY.md +++ b/Documentation/Books/Users/SUMMARY.md @@ -91,6 +91,8 @@ * [FoxxModel](Foxx/FoxxModel.md) * [FoxxRepository](Foxx/FoxxRepository.md) * [Developing Applications](Foxx/DevelopingAnApplication.md) + * [Dependency Injection](Foxx/FoxxInjection.md) + * [Foxx Exports](Foxx/FoxxExports.md) * [Optional Functionality](Foxx/FoxxOptional.md) * [Foxx Manager](FoxxManager/README.md)