Linking services together

    • or APIs for managing shared data(e.g. application users or session data)
    • common middleware that requires some that would be identicalfor multiple services
    • reusable routers that provide the same APIfor different services

    For scenarios like these, Foxx provides a way to link services together andallow them to export JS APIs other services can use.In Foxx these JS APIs are called dependencies,the services implementing them are called providers,the services using them are called consumers.

    This chapter is about Foxx dependencies as described above. In JavaScript theterm dependencies can also refer to, which are an unrelated concept.

    Foxx dependencies can be declared in theservice manifestusing the and dependencies fields:

    • provides lists the dependencies a given service provides,i.e. which APIs it claims to be compatible with

    • dependencies lists the dependencies a given service consumes,i.e. which APIs its dependencies need to be compatible with

    A dependency name should be an alphanumeric identifier, optionally using anamespace prefix (i.e. dependency-name or @namespace/dependency-name).For example, services maintained by the ArangoDB Foxx team typically usethe @foxx namespace whereas the @arangodb namespaceis reserved for internal use.

    There is no official registry for dependency names but we recommend ensuringthe dependency names you use are unambiguous and meaningfulto other developers using your services.

    A provides definition maps each provided dependency’s nameto the provided version:

    A dependencies definition maps the local alias of each consumed dependencyagainst a short definition that includes the name and version range:

    1. "dependencies": {
    2. "myAuth": {
    3. "name": "@example/auth",
    4. "description": "This description is entirely optional.",
    5. "required": false,
    6. "multiple": false
    7. }
    8. }

    The local alias should be a valid JavaScript identifier(e.g. a valid variable name). When a dependency has been assigned,its JS API will be exposed in a corresponding property of the,e.g. module.context.dependencies.myAuth.

    The value for each dependency should be the database-relative mount path ofthe service (including the leading slash). Both services need to be mounted inthe same database. The same service can be used to provide a dependencyfor multiple services.

    Also as with configuration, a service that declares required dependencies whichhave not been assigned will not be mounted by Foxx until all requireddependencies have been assigned. Instead any attempt to access the service’sHTTP API will result in an error code.

    In order to provide a JS API other services can consume as a dependency,the service’s main file needs to export something other services can use.You can do this by assigning a value to the module.exports or propertiesof the exports object as with any other module export:

    This also includes collections. In the following example, the collectionexported by the provider will use the provider’scollection prefix rather than the consumer’s,allowing both services to share the same collection:

    1. module.exports = module.context.collection("shared_documents");

    Let’s imagine we have a service managing our application’s users.Rather than allowing any consuming service to access the collection directly,we can provide a number of methods to manipulate it:

    1. const auth = require("./util/auth");
    2. const users = module.context.collection("users");
    3. module.exports = (BadCredentialsError = Error) => {
    4. return {
    5. const user = users.firstExample({ username });
    6. if (!user) throw new BadCredentialsError("Wrong username");
    7. const valid = auth.verify(user.authData, password);
    8. if (!valid) throw new BadCredentialsError("Wrong password");
    9. return user;
    10. },
    11. setPassword(user, password) {
    12. const authData = auth.create(password);
    13. users.update(user, { authData });
    14. return user;
    15. }
    16. };

    Example usage (the consumer uses the local alias usersApi):