{
    "docs": [
        {
            "location": "/gettingstarted/",
            "text": "Quickstart\n\n\nFollow this 5 minute quickstart, to setup a new web project with Baqend. We will build a simple message wall.\n\n\n\n\n\n\nCreate a Baqend Account\n\n\nTo build a new application, first \ncreate a Baqend account\n. Type in a name for your new application and a dedicated server instance will be deployed and hooked up to our global caching infrastructure (typically in 20 seconds).\n\n\n\n\n\nDownload Boilerplate Web Project\n\n\nWe'll start with \nthis empty HTML5 Bootstrap project\n (or \nconfigure a custom one\n). Unzip it, to get the following folder structure:\n\n\n\nindex.html\n          <-- here we will put some HTML to accept input data\njs\n    \nmain.js\n         <-- your application logic hooked up to Baqend\n    vendor          <-- JavaScript libraries\ncss\n    main.css        <-- our style\n    bootstrap.css   <-- \nBootstrap\n style\nimg, fonts          <-- assets\n\n\nIn a few steps your app will look like this:\n\n\n\n\n\n\n\n\nInstall Baqend\n\n\nTo install Baqend to the application (alreay included in the zip you downloaded), just add the CDN-hosted Baqend SDK \nat the end of the \n<body>\n section of the index.html using your favourite IDE (e.g. \nWebStorm\n) \nor text editor (e.g. \nSublime\n):\n\n\n<script src=\"https://www.baqend.com/js-sdk/latest/baqend.min.js\"></script>\n\n\n\n\nOther installation methods (e.g. npm) are explained \non Github\n.\n\n\n\n\n\nConnect to the Cloud\n\n\nIn the \nmain.js\n, add the following lines to connect to Baqend Cloud:\n\n\nDB.connect(\"<your-app-name>\", function() {\n    showMessages();\n});\n\n\n\n\nThe callback is invoked when the connection is established. We will use that to display the message wall in \nshowMessages\n, but first we need some data.\n\n\n\n\n\nDefine the Data Model\n\n\nIn the \ndashboard\n enter your App and create a new table named \nMessage\n in the \nData\n menu on the left. In the schema tab that is now open, add three attributes:\n\n\n\nAttribute Name\nType\n\n\nname\nString\n\n\nmessage\nString\n\n\ndate\nDateTime\n\n\n\nNow go to the \nData\n tab and click \nAdd\n to insert a dummy message to the database.\n\n\nTo learn more about data modeling in Baqend, see the \nSchema and Types documentation\n.\n\n\n\n\n\nSave Data\n\n\nNow, let's enhance the \nindex.html\n with an input for name and message as well as post button. Replace all the code starting before \n<div class=\"jumbotron\">\n just until the \n<hr>\n with this:\n\n\n<div class=\"jumbotron\">\n  <form onsubmit=\"leaveMessage(this.name.value, this.message.value);\n  this.reset(); return false;\" class=\"form-inline text-center container\">\n  <input class=\"form-control\" name=\"name\" placeholder=\"Name\">\n  <input class=\"form-control\" name=\"message\" placeholder=\"Message\">\n  <button type=\"submit\" class=\"btn btn-primary\">Leave Message</button>\n</form>\n</div>\n<div class=\"container\"><div class=\"row\" id=\"messages\"></div>\n\n\n\n\nSo when hitting enter or the button, our \nleaveMessage\n function is called. Let's add it to \nmain.js\n:\n\n\nfunction leaveMessage(name, message) {\n    //Create new message object\n    var msg = new DB.Message();\n    //Set the properties\n    msg.name = name;\n    msg.message = message;\n    msg.date = new Date();\n    //Insert it to the database\n    msg.insert().then(showMessages);\n}\n\n\n\n\nSo now we insert a new message, whenever the HTML form is submitted.\n\n\nSee the \nC\nreate \nR\nead \nU\npdate \nD\nelete documentation\n to learn more about saving and loading data.\n\n\n\n\n\nQuery Data\n\n\nNow, let's display the stored data. To show the 30 newest messages, ordered by time stamp perform a simple query:\n\n\nfunction showMessages() {\n  DB.Message.find()\n    .descending(\"date\")\n    .limit(30)\n    .resultList()\n    .then(function(result) {\n        var html = \"\";\n        result.forEach(function(msg) {\n            html += '<div class=\"col-md-4\"><h2>';\n            html += msg.name + '</h2><p>' + msg.message + '</p></div>';\n        });\n        document.getElementById(\"messages\").innerHTML = html;\n    });\n}\n\n\n\n\nAt this point the application is fully working. Just open the \nindex.html\n in the browser to use your app. If something is not working, press \nF12\n to see any error messages.\n\n\nQueries allow you do complex filtering and sorting, see the \nQuery Docs\n. All data loaded from Baqend Cloud is served with low latency from a global CDN.\n\n\n\n\n\nProtect Your Data\n\n\nBy default, public access to the \nMessage\n table is allowed. Let's restrict that to only allow \ninserts\n, \nreads\n and \nqueries\n but disallow any \nupdates\n and \ndeletes\n. Go to the \nACL\n (Access Control Lists) tab in the dashboard and revoke delete and update rights from the Public role.\n\n\nAccess rights can be granted and denied both at table level and at object level. This is explained in detail in the \nUser, Roles and Permissions documentation\n.\n\n\nBaqend has full SSL support. If you want the Baqend connection to be SSL-encrypted by default, add \ntrue\n as the second parameter of the \nDB.connect\n call.\n\n\n\n\n\nAdd User Registration and Login\n\n\nIf you would like your users to login into your application, that's easy. Your app has a predefined \nUser\n table and the Baqend SDK comes with built-in ways to register and log in users:\n\n\nDB.User.register('john.doe@example.com', 'pwd').then(function() {\n  //Now we are logged in\n  console.log(DB.User.me.username); //'john.doe@example.com'\n});\n//When coming back, just log in:\nDB.User.login('john.doe@example.com', 'pwd').then(...)\n\n\n\n\nYou can enable and customize email verification in the settings page of the dashboard. To support OAuth logins (e.g. \"Login with Facebook\"), setup OAuth as \ndescribed in the User docs\n, then you can simply call \nDB.User.loginWithFacebook\n.\n\n\n\n\n\n\nInstall the Baqend CLI and Deploy\n\n\nInstall the \nBaqend CLI\n globally with (\nnode.js and npm\n is required):\n\n\n$ npm install -g baqend\n\n\n\n\nDeploy your first app version by typing: \n\n\n$ baqend deploy --file-dir . <your-app-name>\n\n\n\n\nView it online by visiting your app domain \n<your-app-name>.app.baqend.com\n.\n\n\n\n\n\n\nStart Building\n\n\nYou can use the app you just created as a baseline for a real app. To explore Baqend's other features:\n\n\n    \nTake the \nInteractive Tutorial\n\n    \nRead the \nDeveloper Guide\n, to learn about server-side code & validations, push notifications, logging, etc.\n\n    \nRead the \nJavaScript API Docs\n\n    \nPlay with the Interative REST API: \nOpen Your App\n and go to \nAPI Explorer\n\n    \nIf you're starting from scratch, have a look at frontend bootstraping tools: \nInitializr\n (used here), \nHTML5 Boilerplate\n, \nBootstrap\n, \nYeoman\n and popular frontend frameworks: \nIonic\n, \nAngularJS\n, \nReact\n, \nEmber\n\n\n\n\n\n\n\n\n\n.getting-started-list {\n    list-style: none;\n    counter-reset: cnt;\n    margin-left: 0;\n    margin-top: 40px;\n}\n\n.getting-started-list ul li{\n    padding: 10px 0;\n}\n\n.getting-started-list h3 {\n    margin-top: -110px;\n    position: relative;\n    z-index: -1;\n}\n\n.getting-started-list>li {\n    position: relative;\n    border-left: 2px solid #1967CC;\n    padding: 0 0 60px 50px;\n    /* disable collapsed margin */\n    display: inline-block;\n    width: 100%;\n}\n\n.getting-started-list>li:last-child {\n    border: none;\n}\n\n.getting-started-list>li:before {\n    counter-increment: cnt;\n    content: counter(cnt);\n    position: absolute;\n    left: -18px;\n    border-radius: 50%;\n    background-color: #FFFFFF;\n    display: block;\n    width: 35px;\n    height: 35px;\n    line-height: 31px;\n    color: #1967CC;\n    border: 2px solid #1967CC;\n    text-align: center;\n    font-size: 21px;\n}",
            "title": "Quickstart"
        },
        {
            "location": "/gettingstarted/#quickstart",
            "text": "Follow this 5 minute quickstart, to setup a new web project with Baqend. We will build a simple message wall.",
            "title": "Quickstart"
        },
        {
            "location": "/gettingstarted/#create-a-baqend-account",
            "text": "To build a new application, first  create a Baqend account . Type in a name for your new application and a dedicated server instance will be deployed and hooked up to our global caching infrastructure (typically in 20 seconds).",
            "title": "Create a Baqend Account"
        },
        {
            "location": "/gettingstarted/#download-boilerplate-web-project",
            "text": "We'll start with  this empty HTML5 Bootstrap project  (or  configure a custom one ). Unzip it, to get the following folder structure:  index.html           <-- here we will put some HTML to accept input data\njs\n     main.js          <-- your application logic hooked up to Baqend\n    vendor          <-- JavaScript libraries\ncss\n    main.css        <-- our style\n    bootstrap.css   <--  Bootstrap  style\nimg, fonts          <-- assets \nIn a few steps your app will look like this:",
            "title": "Download Boilerplate Web Project"
        },
        {
            "location": "/gettingstarted/#install-baqend",
            "text": "To install Baqend to the application (alreay included in the zip you downloaded), just add the CDN-hosted Baqend SDK \nat the end of the  <body>  section of the index.html using your favourite IDE (e.g.  WebStorm ) \nor text editor (e.g.  Sublime ):  <script src=\"https://www.baqend.com/js-sdk/latest/baqend.min.js\"></script>  Other installation methods (e.g. npm) are explained  on Github .",
            "title": "Install Baqend"
        },
        {
            "location": "/gettingstarted/#connect-to-the-cloud",
            "text": "In the  main.js , add the following lines to connect to Baqend Cloud:  DB.connect(\"<your-app-name>\", function() {\n    showMessages();\n});  The callback is invoked when the connection is established. We will use that to display the message wall in  showMessages , but first we need some data.",
            "title": "Connect to the Cloud"
        },
        {
            "location": "/gettingstarted/#define-the-data-model",
            "text": "In the  dashboard  enter your App and create a new table named  Message  in the  Data  menu on the left. In the schema tab that is now open, add three attributes:  Attribute Name Type  name String  message String  date DateTime  \nNow go to the  Data  tab and click  Add  to insert a dummy message to the database.  To learn more about data modeling in Baqend, see the  Schema and Types documentation .",
            "title": "Define the Data Model"
        },
        {
            "location": "/gettingstarted/#save-data",
            "text": "Now, let's enhance the  index.html  with an input for name and message as well as post button. Replace all the code starting before  <div class=\"jumbotron\">  just until the  <hr>  with this:  <div class=\"jumbotron\">\n  <form onsubmit=\"leaveMessage(this.name.value, this.message.value);\n  this.reset(); return false;\" class=\"form-inline text-center container\">\n  <input class=\"form-control\" name=\"name\" placeholder=\"Name\">\n  <input class=\"form-control\" name=\"message\" placeholder=\"Message\">\n  <button type=\"submit\" class=\"btn btn-primary\">Leave Message</button>\n</form>\n</div>\n<div class=\"container\"><div class=\"row\" id=\"messages\"></div>  So when hitting enter or the button, our  leaveMessage  function is called. Let's add it to  main.js :  function leaveMessage(name, message) {\n    //Create new message object\n    var msg = new DB.Message();\n    //Set the properties\n    msg.name = name;\n    msg.message = message;\n    msg.date = new Date();\n    //Insert it to the database\n    msg.insert().then(showMessages);\n}  So now we insert a new message, whenever the HTML form is submitted.  See the  C reate  R ead  U pdate  D elete documentation  to learn more about saving and loading data.",
            "title": "Save Data"
        },
        {
            "location": "/gettingstarted/#query-data",
            "text": "Now, let's display the stored data. To show the 30 newest messages, ordered by time stamp perform a simple query:  function showMessages() {\n  DB.Message.find()\n    .descending(\"date\")\n    .limit(30)\n    .resultList()\n    .then(function(result) {\n        var html = \"\";\n        result.forEach(function(msg) {\n            html += '<div class=\"col-md-4\"><h2>';\n            html += msg.name + '</h2><p>' + msg.message + '</p></div>';\n        });\n        document.getElementById(\"messages\").innerHTML = html;\n    });\n}  At this point the application is fully working. Just open the  index.html  in the browser to use your app. If something is not working, press  F12  to see any error messages.  Queries allow you do complex filtering and sorting, see the  Query Docs . All data loaded from Baqend Cloud is served with low latency from a global CDN.",
            "title": "Query Data"
        },
        {
            "location": "/gettingstarted/#protect-your-data",
            "text": "By default, public access to the  Message  table is allowed. Let's restrict that to only allow  inserts ,  reads  and  queries  but disallow any  updates  and  deletes . Go to the  ACL  (Access Control Lists) tab in the dashboard and revoke delete and update rights from the Public role.  Access rights can be granted and denied both at table level and at object level. This is explained in detail in the  User, Roles and Permissions documentation .  Baqend has full SSL support. If you want the Baqend connection to be SSL-encrypted by default, add  true  as the second parameter of the  DB.connect  call.",
            "title": "Protect Your Data"
        },
        {
            "location": "/gettingstarted/#add-user-registration-and-login",
            "text": "If you would like your users to login into your application, that's easy. Your app has a predefined  User  table and the Baqend SDK comes with built-in ways to register and log in users:  DB.User.register('john.doe@example.com', 'pwd').then(function() {\n  //Now we are logged in\n  console.log(DB.User.me.username); //'john.doe@example.com'\n});\n//When coming back, just log in:\nDB.User.login('john.doe@example.com', 'pwd').then(...)  You can enable and customize email verification in the settings page of the dashboard. To support OAuth logins (e.g. \"Login with Facebook\"), setup OAuth as  described in the User docs , then you can simply call  DB.User.loginWithFacebook .",
            "title": "Add User Registration and Login"
        },
        {
            "location": "/gettingstarted/#install-the-baqend-cli-and-deploy",
            "text": "Install the  Baqend CLI  globally with ( node.js and npm  is required):  $ npm install -g baqend  Deploy your first app version by typing:   $ baqend deploy --file-dir . <your-app-name>  View it online by visiting your app domain  <your-app-name>.app.baqend.com .",
            "title": "Install the Baqend CLI and Deploy"
        },
        {
            "location": "/gettingstarted/#start-building",
            "text": "You can use the app you just created as a baseline for a real app. To explore Baqend's other features: \n     Take the  Interactive Tutorial \n     Read the  Developer Guide , to learn about server-side code & validations, push notifications, logging, etc. \n     Read the  JavaScript API Docs \n     Play with the Interative REST API:  Open Your App  and go to  API Explorer \n     If you're starting from scratch, have a look at frontend bootstraping tools:  Initializr  (used here),  HTML5 Boilerplate ,  Bootstrap ,  Yeoman  and popular frontend frameworks:  Ionic ,  AngularJS ,  React ,  Ember     \n.getting-started-list {\n    list-style: none;\n    counter-reset: cnt;\n    margin-left: 0;\n    margin-top: 40px;\n}\n\n.getting-started-list ul li{\n    padding: 10px 0;\n}\n\n.getting-started-list h3 {\n    margin-top: -110px;\n    position: relative;\n    z-index: -1;\n}\n\n.getting-started-list>li {\n    position: relative;\n    border-left: 2px solid #1967CC;\n    padding: 0 0 60px 50px;\n    /* disable collapsed margin */\n    display: inline-block;\n    width: 100%;\n}\n\n.getting-started-list>li:last-child {\n    border: none;\n}\n\n.getting-started-list>li:before {\n    counter-increment: cnt;\n    content: counter(cnt);\n    position: absolute;\n    left: -18px;\n    border-radius: 50%;\n    background-color: #FFFFFF;\n    display: block;\n    width: 35px;\n    height: 35px;\n    line-height: 31px;\n    color: #1967CC;\n    border: 2px solid #1967CC;\n    text-align: center;\n    font-size: 21px;\n}",
            "title": "Start Building"
        },
        {
            "location": "/",
            "text": "Baqend Guide\n\n\nLearn how to use Baqend to develop your app.\nJust click a topic below to get more details.\n\n\n\n  \n\n    \n\n    \nTutorial\n\n    \nA tutorial how \n to write a to-do \n app with Baqend.\n\n  \n\n  \n\n    \n\n    \nQuickstart\n\n    \nHow to embed Baqend \n in your JavaScript app \n to get started quickly.\n\n  \n\n  \n\n    \n\n    \nStarter Kits\n\n    \nSome starter kits for \n popular frameworks \n integrating Baqend.\n\n  \n\n  \n\n    \n\n    \nOverview\n\n    \nAn overview over \n Baqend's architecture \n and ecosystem.\n\n  \n\n  \n\n    \n\n    \nDashboard\n\n    \nManage your Baqend \n app's data, schema, \n and settings online.\n\n  \n\n  \n\n    \n\n    \nCLI\n\n    \nWork with your \n Baqend app from \n your terminal.\n\n  \n\n  \n\n    \n\n    \nSetup\n\n    \nHow you set up \n and get running \n your first app.\n\n  \n\n  \n\n    \n\n    \nCRUD\n\n    \nLearn to perform basic \n create, read, update, \n and delete operations.\n\n  \n\n  \n\n    \n\n    \nSchema and Types\n\n    \nSee how to setup \n your app's data model \n and types.\n\n  \n\n  \n\n    \n\n    \nQueries\n\n    \nRetrieve specific data \n from Baqend by \n performing queries.\n\n  \n\n  \n\n    \n\n    \nReal-Time Queries\n\n    \nTrack results of \n complex queries \n in real time.\n\n  \n\n  \n\n    \n\n    \nUser Management\n\n    \nChange access rights \n by managing users, \n roles, and permissions.\n\n  \n\n  \n\n    \n\n    \nBaqend Code\n\n    \nWrite server-side \n code and handlers \n in pure JavaScript.\n\n  \n\n  \n\n    \n\n    \nPush Notifications\n\n    \nSend push notifications \n to inform users \n of your app.\n\n  \n\n  \n\n    \n\n    \nDeep Loading\n\n    \nLearn how Baqend \n persists your data \n and use deep loading.\n\n  \n\n  \n\n    \n\n    \nHosting\n\n    \nDeliver your app \n blazingly fast to users \n using Baqend Hosting.\n\n  \n\n  \n\n    \n\n    \nFiles\n\n    \nUse the file storage to \n upload and download \n files, like images or CSS.\n\n  \n\n  \n\n    \n\n    \nCaching\n\n    \nLearn how Baqend \n caches your data and \n what it asserts.\n\n  \n\n  \n\n    \n\n    \nLogging\n\n    \nEase the debbuging \n of your app by \n logging its status.\n\n  \n\n\n\n\n\n\n  \nNote:\n If you have any questions not answered by this guide, feel free to contact us via \nsupport@baqend.com\n or the chat on the bottom.",
            "title": "Home"
        },
        {
            "location": "/#baqend-guide",
            "text": "Learn how to use Baqend to develop your app.\nJust click a topic below to get more details.  \n   \n     \n     Tutorial \n     A tutorial how   to write a to-do   app with Baqend. \n   \n   \n     \n     Quickstart \n     How to embed Baqend   in your JavaScript app   to get started quickly. \n   \n   \n     \n     Starter Kits \n     Some starter kits for   popular frameworks   integrating Baqend. \n   \n   \n     \n     Overview \n     An overview over   Baqend's architecture   and ecosystem. \n   \n   \n     \n     Dashboard \n     Manage your Baqend   app's data, schema,   and settings online. \n   \n   \n     \n     CLI \n     Work with your   Baqend app from   your terminal. \n   \n   \n     \n     Setup \n     How you set up   and get running   your first app. \n   \n   \n     \n     CRUD \n     Learn to perform basic   create, read, update,   and delete operations. \n   \n   \n     \n     Schema and Types \n     See how to setup   your app's data model   and types. \n   \n   \n     \n     Queries \n     Retrieve specific data   from Baqend by   performing queries. \n   \n   \n     \n     Real-Time Queries \n     Track results of   complex queries   in real time. \n   \n   \n     \n     User Management \n     Change access rights   by managing users,   roles, and permissions. \n   \n   \n     \n     Baqend Code \n     Write server-side   code and handlers   in pure JavaScript. \n   \n   \n     \n     Push Notifications \n     Send push notifications   to inform users   of your app. \n   \n   \n     \n     Deep Loading \n     Learn how Baqend   persists your data   and use deep loading. \n   \n   \n     \n     Hosting \n     Deliver your app   blazingly fast to users   using Baqend Hosting. \n   \n   \n     \n     Files \n     Use the file storage to   upload and download   files, like images or CSS. \n   \n   \n     \n     Caching \n     Learn how Baqend   caches your data and   what it asserts. \n   \n   \n     \n     Logging \n     Ease the debbuging   of your app by   logging its status. \n     \n   Note:  If you have any questions not answered by this guide, feel free to contact us via  support@baqend.com  or the chat on the bottom.",
            "title": "Baqend Guide"
        },
        {
            "location": "/topics/overview/",
            "text": "Overview\n\n\nBaqend Cloud hosts your application data and business logic and delivers it over a \nglobal caching infrastructure\n for performance at the physical optimum. \n\n\nWith Baqend, you use a fully managed backend service with an automatically accelerated \nJavaScript API\n directly from your application (e.g. written in Angular or React). As the platform provides a rich set of turnkey features and takes over the responsibility for backend performance, major development efforts are saved.\n\n\nIn terms of \narchitecture\n Baqend gives you the hosting of your application (e.g. HTML and JS files) plus the APIs for backend concerns such as data storage, queries, push, OAuth, user management, access control and server-side business logic:\n\n\n\n\nGetting Started\n\n\nThese are our recommendations for getting things rolling quickly:\n\n\n\n\nTo get a hands-on overview of how Baqend works, take the \ninteractive tutorial\n\n\nStart your first Baqend app\n and take the Quickstart to build a real application\n\n\nWith the \nStarter Kits\n you get convenient boilerplate projects that work seamlessly with Baqend\n\n\nThis guide covers how Baqend and the SDK work in depth",
            "title": "Overview"
        },
        {
            "location": "/topics/overview/#overview",
            "text": "Baqend Cloud hosts your application data and business logic and delivers it over a  global caching infrastructure  for performance at the physical optimum.   With Baqend, you use a fully managed backend service with an automatically accelerated  JavaScript API  directly from your application (e.g. written in Angular or React). As the platform provides a rich set of turnkey features and takes over the responsibility for backend performance, major development efforts are saved.  In terms of  architecture  Baqend gives you the hosting of your application (e.g. HTML and JS files) plus the APIs for backend concerns such as data storage, queries, push, OAuth, user management, access control and server-side business logic:",
            "title": "Overview"
        },
        {
            "location": "/topics/overview/#getting-started",
            "text": "These are our recommendations for getting things rolling quickly:   To get a hands-on overview of how Baqend works, take the  interactive tutorial  Start your first Baqend app  and take the Quickstart to build a real application  With the  Starter Kits  you get convenient boilerplate projects that work seamlessly with Baqend  This guide covers how Baqend and the SDK work in depth",
            "title": "Getting Started"
        },
        {
            "location": "/topics/dashboard/",
            "text": "Baqend Dashboard\n\n\nThe Baqend dashboard is the main tool, which you will use to manage and configure your Baqend instance. After you have\ncreated your first app, you have in the left navigation bar a quick overview over all the configurable and usable \n functionalities of Baqend.\n\n\nHere is a quick overview of those:\n\n\nBaqend Modules\n - can be used to create Baqend code, which can later be called by your app to execute trusted\nbusiness logic. See also \nBaqend Modules\n. By clicking the \n+\n you can create new modules, Afterwards a module \ncode template will be opened.\n\n\nTables\n - are the part where you can create and extend the data model of Baqend to fit your app requirements.\nBy clicking on the class name, you can view and edit the table content and its metadata like schema, access \nrules and code hooks. Each table is represented by one entity class and each row is an instance of this class in the SDK.\nOn the upper right side you can navigate with the tabs through those categories:\n\n\n\n\nData:\n This is the default view of a class and shows the stored instances in a table. You can view, navigate and search \n  in the table. In addition you can add new rows, modify fields and delete existing rows. You can im- and export\n  the entire table content and truncate (drop all rows) of the table. \nRead More\n\n\nSchema:\n Each class is described by its schema. The schema describes which fields a class have and which type \n  those fields have. When you insert data into the table, the data will always be validated against the defined \n  schema and modifications which violate the schema will be rejected. Baqend supports many common types, such as \n  primitive types, geo points, references, collections, json and embedded types. \nRead More\n\n\nACL (Access Control List):\n In many apps you would like to restrict the access who is allowed to read and write \n  the data. Therefore you can restrict the access per operation on class or object level. In this view you can modify \n  the access permission for the selected class. You can add new users and roles to the acl and can specify those access \n  restrictions. \nRead more\n\n\nHandler:\n are Baqend code hooks, which are invoked before an object is modified. Here you can implement custom\n  logic that is invoked every time when an object is inserted, updated or deleted. Within the code you can validate the \n  modification, modify some fields or can completely reject the modifications as your needs. \nRead More\n\n\n\n\nThere are three predefined classes which you can also extend with custom fields:\n\n\n\n\nUser:\n are used to represent a user which is logged in into your app. New users can be created by a registration \n  process or by a login through an \nOAuth\n provider when configured. \nRead More\n\n\nRole:\n Roles can be created to group users and together and use those groups to give them special privileges \n  such as ACLs. There are three predefined roles the admin role, the loggedin role and the node role. Roles contains a predefined users list \n  field, which contains all the members of the role. \nRead More\n\n\nDevice:\n represents registered devices which can later be used to send them push notifications out of Baqend\n  code. Devices can be queried like any other table to send a push notification to multiple devices at once. \n  \nRead More\n\n\n\n\nAdditionally you can create a new custom classes with a click on the \n+\n button near the \nData\n label. Type a none used \nname and hit enter. The schema view will appear and you can begin to model your own class schema.\n\n\nLogs\n - Here you can view the logs generated by accessing the api and your application logs.\n\n\n\n\nAccessLog:\n Each request wich is served by our Baqend servers or the CDN generates a log entry. You can view and \n  search in the access logs within a period of 30 days. \nRead More\n\n\nAppLog:\n While developing and later in production is is really common to log specific actions of your app or \n  Baqend code for debugging and usage analysis. Therefore the SDK provides a simple logging API that you can use to\n  create log entries which are kept for an period of 30 days. \nRead More\n\n\n\n\nAPI Explorer\n - The API Explorer provides a GUI to serve the underlying REST API of Baqend. Here you can explore and\nmade direct HTTP calls to your Baqend server.\n\n\nSettings\n - Her you can configure additional settings of your Baqend app like:\n\n\n\n\nE-Mailing used by the registration process\n\n\nOAuth settings to enable oauth login\n\n\nPush Notifications certificates and keys needed to actually push notifications",
            "title": "Dashboard"
        },
        {
            "location": "/topics/dashboard/#baqend-dashboard",
            "text": "The Baqend dashboard is the main tool, which you will use to manage and configure your Baqend instance. After you have\ncreated your first app, you have in the left navigation bar a quick overview over all the configurable and usable \n functionalities of Baqend.  Here is a quick overview of those:  Baqend Modules  - can be used to create Baqend code, which can later be called by your app to execute trusted\nbusiness logic. See also  Baqend Modules . By clicking the  +  you can create new modules, Afterwards a module \ncode template will be opened.  Tables  - are the part where you can create and extend the data model of Baqend to fit your app requirements.\nBy clicking on the class name, you can view and edit the table content and its metadata like schema, access \nrules and code hooks. Each table is represented by one entity class and each row is an instance of this class in the SDK.\nOn the upper right side you can navigate with the tabs through those categories:   Data:  This is the default view of a class and shows the stored instances in a table. You can view, navigate and search \n  in the table. In addition you can add new rows, modify fields and delete existing rows. You can im- and export\n  the entire table content and truncate (drop all rows) of the table.  Read More  Schema:  Each class is described by its schema. The schema describes which fields a class have and which type \n  those fields have. When you insert data into the table, the data will always be validated against the defined \n  schema and modifications which violate the schema will be rejected. Baqend supports many common types, such as \n  primitive types, geo points, references, collections, json and embedded types.  Read More  ACL (Access Control List):  In many apps you would like to restrict the access who is allowed to read and write \n  the data. Therefore you can restrict the access per operation on class or object level. In this view you can modify \n  the access permission for the selected class. You can add new users and roles to the acl and can specify those access \n  restrictions.  Read more  Handler:  are Baqend code hooks, which are invoked before an object is modified. Here you can implement custom\n  logic that is invoked every time when an object is inserted, updated or deleted. Within the code you can validate the \n  modification, modify some fields or can completely reject the modifications as your needs.  Read More   There are three predefined classes which you can also extend with custom fields:   User:  are used to represent a user which is logged in into your app. New users can be created by a registration \n  process or by a login through an  OAuth  provider when configured.  Read More  Role:  Roles can be created to group users and together and use those groups to give them special privileges \n  such as ACLs. There are three predefined roles the admin role, the loggedin role and the node role. Roles contains a predefined users list \n  field, which contains all the members of the role.  Read More  Device:  represents registered devices which can later be used to send them push notifications out of Baqend\n  code. Devices can be queried like any other table to send a push notification to multiple devices at once. \n   Read More   Additionally you can create a new custom classes with a click on the  +  button near the  Data  label. Type a none used \nname and hit enter. The schema view will appear and you can begin to model your own class schema.  Logs  - Here you can view the logs generated by accessing the api and your application logs.   AccessLog:  Each request wich is served by our Baqend servers or the CDN generates a log entry. You can view and \n  search in the access logs within a period of 30 days.  Read More  AppLog:  While developing and later in production is is really common to log specific actions of your app or \n  Baqend code for debugging and usage analysis. Therefore the SDK provides a simple logging API that you can use to\n  create log entries which are kept for an period of 30 days.  Read More   API Explorer  - The API Explorer provides a GUI to serve the underlying REST API of Baqend. Here you can explore and\nmade direct HTTP calls to your Baqend server.  Settings  - Her you can configure additional settings of your Baqend app like:   E-Mailing used by the registration process  OAuth settings to enable oauth login  Push Notifications certificates and keys needed to actually push notifications",
            "title": "Baqend Dashboard"
        },
        {
            "location": "/topics/cli/",
            "text": "Baqend CLI\n\n\nThe \nCLI\n (Command Line Interface) provides a simple way to:\n\n\n\n\nRegister a Baqend account and start an app \n\n\nDeploy application assets (HTML, images, CSS, etc.)\n\n\nRegister Baqend Code (modules and handlers)\n\n\n\n\nThe Baqend CLI can easily be installed globally with \nnpm install -g baqend\n (to get npm you just need to have \nNode.JS\n installed). Afterwards you can use the CLI\nby typing \nbaqend --help\n in any folder.\n\n\nNote:\n Ensure that your \nPATH\n system enviroment variable contains the global\n \nnpm bin path\n (\n$ npm bin -g\n) to let npm installed commands work properly.\n\n\n\n\nTip:\n A good way to manage a Baqend-based project is to manage the files and collaboration via \ngit\n and using the CLI to deploy files and code to Baqend.\n\n\nThe Baqend CLI is automatically shipped with our SDK. You can use the Baqend CLI directly in any \nnpm script\n.\nTherefore add a Baqend script entry to the scripts section in your projects \npackage.json\n\n\n  \"scripts\": {\n    \"baqend\": \"baqend\"\n  }\n\n\n\n\nAfterwards you can type \nnpm run baqend -- --help\n\n\nNote:\n The extra \n--\n are required to seperate the npm run arguments from the Baqend ones.\n\n\nRegister, Login, and Logout\n\n\nBefore you can actually deploy assets and code you have to create a Baqend account.\nThe easiest way to use it is the \nbaqend register\n command.\nIf you already have an account, you are able login the CLI by typing\n\nbaqend login\n.\nThese commands will save your credentials locally.\n\n\nIf you do not want so save your login credentials, you can skip the login step and provide the login\ncredentials each time you deploy.\n\n\n\n  \nNote:\n\n  If you have created your Baqend account with OAuth (Google, Facebook, or GitHub), you must add a password to your account first.\n  This can be done in the account settings of the dashboard.\n\n\n\n\nYou can logout the Baqend CLI and remove all locally stored credentials by typing \nbaqend logout\n\n\nDeployment\n\n\nWith the \ndeploy\n command, you can upload your static files and assets as well as Baqend Code (modules and handlers) to your Baqend app:\n\n\n$ baqend deploy\n\n\n\n\nDeploying Static Files\n\n\nYou can host the static files and assets of your web app on Baqend.\nTherefore, move your working directory to your app root folder.\nWe expect you to have a folder named \nwww\n by default that is uploaded to the \nwww\n folder in \nBaqend Files\n and served as a website.\n\n\n\n  \nTip:\n\n  If you want do upload a different directory, you can use the \n--file-dir\n or \n-f\n option to specify a directory:\n  \nbaqend deploy --file-dir dist\n.\n\n\n\n\nThe files are then hosted from Baqend.\nRead more about \nBaqend Hosting\n in the \nHosting\n chapter.\n\n\nDeploying Baqend Code\n\n\nThe CLI can additionally deploy your Baqend Code. Baqend code should be located in an folder named \nbaqend\n.\nThe following screenshot visualizes a typical project layout including Baqend code.\n\n\n\n    \n\nAll Baqend modules should sit top level within the \nbaqend\n folder.\nFor example, \nbaqend/firstModule.js\n will be uploaded as \nfirstModule\n.\n\n\nFor each code handler you should create a folder named similar to the table \nit belongs to. Within the folder the files should be named:\n\n\nbaqend/<Table>/insert.js\n for an \nonInsert\n handler \n\n\nbaqend/<Table>/update.js\n for an \nonUpdate\n handler \n\n\nbaqend/<Table>/delete.js\n for an \nonDelete\n handler \n\n\nbaqend/<Table>/validate.js\n for an \nonValidate\n handler\n\n\nTherefore \nbaqend/User/insert.js\n contains the insert handler code wich is invoked each time a new user object is inserted\nto the \nUser\n table. \n\n\nRead more about Baqend code in the \nBaqend Code\n chapter.\n\n\n\n\n\nAfter deploying your app, you can open it by typing \nbaqend open\n or use the dashboard with \nbaqend dashboard\n.\n\n\nTypeScript Support\n\n\nThe Baqend SDK itself comes with a \nTypeScript declaration file\n,\nwhich enables seamless integration into TypeScript and allows better code completion.\nThe SDK comes with a dynamic API part, which is generated on the fly depending on your current schema.\nTo make your TypeScript application work properly with this dynamic part you can generate the additional typings for your \ncurrent schema with the CLI.\n\n\nWith \nbaqend typings your-app-name\n the CLI generates the TypeScript declaration file in the current folder.\nYou can then add the generated file to your \ntsconfig.json\n file.\n\n\nYou can update the generated file each time you have changed tables or fields in the Baqend Dashboard by just repeating this step.\n\n\nTip:\n You should check the generated file into your version control system to\n share an up-to-date version of the definition file.",
            "title": "CLI"
        },
        {
            "location": "/topics/cli/#baqend-cli",
            "text": "The  CLI  (Command Line Interface) provides a simple way to:   Register a Baqend account and start an app   Deploy application assets (HTML, images, CSS, etc.)  Register Baqend Code (modules and handlers)   The Baqend CLI can easily be installed globally with  npm install -g baqend  (to get npm you just need to have  Node.JS  installed). Afterwards you can use the CLI\nby typing  baqend --help  in any folder.  Note:  Ensure that your  PATH  system enviroment variable contains the global\n  npm bin path  ( $ npm bin -g ) to let npm installed commands work properly.   Tip:  A good way to manage a Baqend-based project is to manage the files and collaboration via  git  and using the CLI to deploy files and code to Baqend.  The Baqend CLI is automatically shipped with our SDK. You can use the Baqend CLI directly in any  npm script .\nTherefore add a Baqend script entry to the scripts section in your projects  package.json    \"scripts\": {\n    \"baqend\": \"baqend\"\n  }  Afterwards you can type  npm run baqend -- --help  Note:  The extra  --  are required to seperate the npm run arguments from the Baqend ones.",
            "title": "Baqend CLI"
        },
        {
            "location": "/topics/cli/#register-login-and-logout",
            "text": "Before you can actually deploy assets and code you have to create a Baqend account.\nThe easiest way to use it is the  baqend register  command.\nIf you already have an account, you are able login the CLI by typing baqend login .\nThese commands will save your credentials locally.  If you do not want so save your login credentials, you can skip the login step and provide the login\ncredentials each time you deploy.  \n   Note: \n  If you have created your Baqend account with OAuth (Google, Facebook, or GitHub), you must add a password to your account first.\n  This can be done in the account settings of the dashboard.  You can logout the Baqend CLI and remove all locally stored credentials by typing  baqend logout",
            "title": "Register, Login, and Logout"
        },
        {
            "location": "/topics/cli/#deployment",
            "text": "With the  deploy  command, you can upload your static files and assets as well as Baqend Code (modules and handlers) to your Baqend app:  $ baqend deploy",
            "title": "Deployment"
        },
        {
            "location": "/topics/cli/#deploying-static-files",
            "text": "You can host the static files and assets of your web app on Baqend.\nTherefore, move your working directory to your app root folder.\nWe expect you to have a folder named  www  by default that is uploaded to the  www  folder in  Baqend Files  and served as a website.  \n   Tip: \n  If you want do upload a different directory, you can use the  --file-dir  or  -f  option to specify a directory:\n   baqend deploy --file-dir dist .  The files are then hosted from Baqend.\nRead more about  Baqend Hosting  in the  Hosting  chapter.",
            "title": "Deploying Static Files"
        },
        {
            "location": "/topics/cli/#deploying-baqend-code",
            "text": "The CLI can additionally deploy your Baqend Code. Baqend code should be located in an folder named  baqend .\nThe following screenshot visualizes a typical project layout including Baqend code.  \n     \nAll Baqend modules should sit top level within the  baqend  folder.\nFor example,  baqend/firstModule.js  will be uploaded as  firstModule .  For each code handler you should create a folder named similar to the table \nit belongs to. Within the folder the files should be named:  baqend/<Table>/insert.js  for an  onInsert  handler   baqend/<Table>/update.js  for an  onUpdate  handler   baqend/<Table>/delete.js  for an  onDelete  handler   baqend/<Table>/validate.js  for an  onValidate  handler  Therefore  baqend/User/insert.js  contains the insert handler code wich is invoked each time a new user object is inserted\nto the  User  table.   Read more about Baqend code in the  Baqend Code  chapter.   After deploying your app, you can open it by typing  baqend open  or use the dashboard with  baqend dashboard .",
            "title": "Deploying Baqend Code"
        },
        {
            "location": "/topics/cli/#typescript-support",
            "text": "The Baqend SDK itself comes with a  TypeScript declaration file ,\nwhich enables seamless integration into TypeScript and allows better code completion.\nThe SDK comes with a dynamic API part, which is generated on the fly depending on your current schema.\nTo make your TypeScript application work properly with this dynamic part you can generate the additional typings for your \ncurrent schema with the CLI.  With  baqend typings your-app-name  the CLI generates the TypeScript declaration file in the current folder.\nYou can then add the generated file to your  tsconfig.json  file.  You can update the generated file each time you have changed tables or fields in the Baqend Dashboard by just repeating this step.  Tip:  You should check the generated file into your version control system to\n share an up-to-date version of the definition file.",
            "title": "TypeScript Support"
        },
        {
            "location": "/topics/setup/",
            "text": "Setup\n\n\nWebsites, Apps and Recommended Tooling\n\n\nThe Baqend JavaScript SDK works best for:\n\n\n\n\nDynamic and static \nWebsites\n built with any tools of your choice. We recommend \nsingle page applications\n for the best user experience.\n\n\nHybrid apps\n based on JavaScript. Baqend works very well with \nIonic\n and \nCordova/PhoneGap\n.\n\n\n\n\nThough Baqend does not make any assumptions on the tooling, here a the tools we most frequently see used with Baqend:\n\n\n\n\nFrontend MVC Frameworks\n for structuring your code: \nAngular.js\n, \nAngular2\n, \nReact\n, \nAurelia\n, \nEmber\n and \nKnockout\n\n\nTemplating Engines\n to render data: \nHandlebars\n, \nLodash\n, \nUnderscore\n and \nMustache\n\n\nBoilerplate projects\n and \nfrontend generators\n to get started easily: \nBootstrap\n and \nIntializr\n give you nice boilerplate projects, \nyeoman\n generates many different frontend projects, Google has released a \nweb starter\n that contains a cross-device boilerplate project and useful gulp tasks for live reloading, releasing, etc.\n\n\nHybrid app frameworks\n for mobile applications with JavaScript: \nIonic\n, \nFramework7\n and \nOnsen UI\n are based on web views, \nReact Native\n is based on native UIs with JavaScript logic\n\n\nBuild tools\n for bundling, deployment and development: \nWebpack\n, \nGulp\n and \nGrunt\n all work well with Baqend\n\n\nIDEs\n and \nText Editors\n for developing: \nWebStorm\n and \nNetbeans\n are full-fledged IDEs, \nSublime\n, \nVisual Studio Code\n and \nAtom\n are powerful text and code editors\n\n\nBaqend Starter Kits\n: Boilerplate projects connected to Baqend\n\n\n\n\nJavascript SDK\n\n\nThe JavaScript SDK is packaged as an UMD module, it can be used with RequireJS, browserify or without any module loader.\nTo get started please install the Baqend SDK with \nnpm\n or \nbower\n or \ndownload the complete package from \nGitHub\n.\n\n\nNote:\n If you are not using JavaScript you can use Baqend via its \nREST API\n from the programming language of your choice. Baqend's REST API is documented with \nSwagger\n and can be explored \nhere\n. In the \ndashboard of you Baqend app\n you can goto \"API Explorer\" to explore and use the REST API of your own instance.\n\n\n\nTo install Baqend, just add our CDN-hosted script in your website (available both over HTTPS and HTTP).\n\n\n\n<script src=\"//www.baqend.com/js-sdk/latest/baqend.min.js\"></script>\n\n\n\n\n\nFor additional setup information visit our \nGitHub page\n.\n\n\nTip:\n\nIf you use our \nStarter Kits\n the Baqend SDK is already included and you can skip this setup.\n\n\n\nNote:\n\nIt is generally a good idea to use the latest SDK version from \n//www.baqend.com/js-sdk/latest/baqend.min.js\n in development to always be up-to-date. In production, however, you should use the last exact version you tested with. Be aware that otherwise minor changes in a newly released version may break parts of your production application. See our \nlatest changes\n to the SDK.\n\n\n\nThe Baqend SDK is written and tested for Chrome 24+, Firefox 18+, Internet Explorer 9+, Safari 7+, Node 4+, IOS 7+, Android 4+ and PhantomJS 1.9+\n\n\nThe Baqend SDK does not require any additional dependencies, however it is shipped with a few bundled dependencies:\n\n\n\n\ncore-js, a shim library\n\n\nnode-uuid, A uuid generator\n\n\nvalidator, A validation library\n\n\n\n\nThe Baqend JavaScript SDK and all its bundled dependencies are shipped under the\n\nMIT License\n.\n\n\nTo see that Baqend is working, paste the following after the Baqend script tag. It will replace the HTML body with 5 raw todo items from the \ntutorial application\n. Delete the snippet afterwards.\n\n\n<script>\n  DB.connect('toodle').then(function() {\n    return DB.Todo.find().limit(5).resultList();\n  }).then(function(result) {\n    document.querySelector('body').innerHTML = \"<pre>\" + JSON.stringify(result, null, \" \") + \"</pre>\";\n  });\n</script>\n\n\n\n\nBaqend + Node.js\n\n\nThe Baqend SDK is fully compatible with \nNode.js\n. This means you can use the SDK in a Node.js-based application for saving data, logging in users, etc. Additionally \nBaqend modules\n and \nhandlers\n are based on Node.js and run and scaled automatically by Baqend.\n\n\nTo install the SDK for a Node.js project do an \nnpm install --save baqend\n and use \nrequire('baqend')\n in your code.\n\n\nvar DB = require('baqend');\nDB.connect('example');\n\n\n\n\nThe Baqend SDK is compatible with Require.JS, Browserify, ES6 and TypeScript and all majors build tools (Gulp, Grunt, Webpack, NPM scripts, etc.).\n\n\nConnect your App to Baqend\n\n\nAfter including the Baqend SDK in your app, connect it with your Baqend. Simply call the connect\nmethod on the DB variable:\n\n\n//connect to the example app\nDB.connect('example');\n//Or use a TLS-encrypted (SSL) connection to Baqend\nDB.connect('example', true);\n\n\n\n\nNote:\n If you use a custom deployment, e.g. the Baqend community edition you must pass a hostname or a complete URL\nto the connect call: \nDB.connect('https://mybaqend.example.com/v1')\n\n\n\nYou can pass a callback as a second argument, which will be called when the connection is successfully established.\n\n\nDB.connect('example', function() {\n  //work with the DB\n  DB.Todo.load(...)\n});\n\n\n\n\nBehind the scenes Baqend is requested, the metadata of your app is loaded and the \nData Models\n are created and initialized.\nIf you want to register the handler afterwards, you can use the ready method to wait on the SDK initialization.\n\n\nDB.ready(function() { DB... //work with the DB });\n\n\n\n\nIf you are familiar with \nPromises\n you can alternatively use the returned promise instead of passing \na callback. This works for all places in the Baqend SDK that exhibit asynchronous behaviour.\n\n\nDB.ready().then(function() {\n  DB... //work with the DB\n});\n\n\n\n\nTip:\n Baqend not only gives you APIs for serverless development but also hosts and accelerates your assets, like HTML, CSS, images, etc. See \nHosting\n for more details.\n\n\n\nAccessing Data\n\n\nAfter the Baqend SDK has been successfully initialized, all defined classes can be accessed using the DB instance. \nJust use the name of the class to access the \nobject factory\n.\n\n\nDB.ready(function() {\n  DB.Todo //The Todo class factory\n});\n\n\n\n\nThe object factory can be called or can be used like a normal JavaScript constructor to create instances.\n\n\nvar todo = new DB.Todo({name: 'My first Todo'});\n\n\n\n\nThe constructor accepts one optional argument, which is a (JSON-)object containing the initial values of the object.\n\n\nThe object attributes can be accessed and changed by their names.\n\n\nvar todo = new DB.Todo({name: 'My first Todo'});\nconsole.log(todo.name); //'My first Todo'\ntodo.active = true;\n\n\n\n\nPromises\n\n\nPromise\ns are a programming paradigm to work with asynchronous code. Primarily used for communication and \nevent-scheduled tasks it makes code much more readable then the callback-based approach. A Promise represents the \npublic interface for\nan asynchronous operation and can be used to chain tasks that depend on each other.\n\n\nThe Baqend SDK supports both paradigms, therefore each asynchronous method accepts an optional success and an error\ncallback and returns a Promise for further tasks.\n\n\nBasically there are two common ways to initialize a Promise. You can create a new instance of a Promise with an executor\nfunction. With the given resolve and reject function it can decide if the promise should be fulfilled with a given\nvalue or should be rejected with an error.\n\n\nvar promise = new Promise(function(resolve, reject) {\n  var delay = Math.random() * 2000 + 1000;\n  window.setTimeout(function() {\n  //We fulfill the promise after the randomized delay\n  resolve(delay);\n  }, Math.random() * 2000 + 1000);\n});\n\n\n\n\nThe second way is to create an already resolved Promise with a given value.\n\n\nvar promise = Promise.resolve(200);\n\n\n\n\nIf you want to listen for the outcome of such a promise you can register a onFulfilled and a onRejection listener with\n the \nthen(onFulfilled, onRejected)\n method of the promise. When the promise gets resolved, the onFulfilled listener is\ncalled with the fulfilled value. In case of rejection the onRejected listener is called with the error.\n\n\npromise.then(function(value) {\n  console.log('We have waited ' + value + 'ms');\n}, function(e) {\n  console.log('An unexpected error with message: ' + e.message + ' occurred.');\n});\n\n\n\n\nThe \nPromise.then\n method returns a new promise which will be resolved with the result of the passed listener.\nThe listener itself can also perform asynchronous operations and return another promise which will then be used to \nresolve the outer Promise.\n\n\npromise.then(function(value) {\n  return anotherAsyncTask(value);\n}).then(function(anotherValue) {\n  //will only be called if the first promise \n  //and the anotherAsyncTask's Promise is fulfilled\n  //the anotherValue holds the fulfilled value of the anotherAsyncTask\n});\n\n\n\n\nFor additional examples and a more detailed explanation consult the \nMDN Promise Documentation\n.\n\n\nThe Baqend SDK uses the promise-based approach for the entire documentation since the code is more readable and is\n generally considered the best way to work with asynchronous code in JavaScript.",
            "title": "Setup"
        },
        {
            "location": "/topics/setup/#setup",
            "text": "",
            "title": "Setup"
        },
        {
            "location": "/topics/setup/#websites-apps-and-recommended-tooling",
            "text": "The Baqend JavaScript SDK works best for:   Dynamic and static  Websites  built with any tools of your choice. We recommend  single page applications  for the best user experience.  Hybrid apps  based on JavaScript. Baqend works very well with  Ionic  and  Cordova/PhoneGap .   Though Baqend does not make any assumptions on the tooling, here a the tools we most frequently see used with Baqend:   Frontend MVC Frameworks  for structuring your code:  Angular.js ,  Angular2 ,  React ,  Aurelia ,  Ember  and  Knockout  Templating Engines  to render data:  Handlebars ,  Lodash ,  Underscore  and  Mustache  Boilerplate projects  and  frontend generators  to get started easily:  Bootstrap  and  Intializr  give you nice boilerplate projects,  yeoman  generates many different frontend projects, Google has released a  web starter  that contains a cross-device boilerplate project and useful gulp tasks for live reloading, releasing, etc.  Hybrid app frameworks  for mobile applications with JavaScript:  Ionic ,  Framework7  and  Onsen UI  are based on web views,  React Native  is based on native UIs with JavaScript logic  Build tools  for bundling, deployment and development:  Webpack ,  Gulp  and  Grunt  all work well with Baqend  IDEs  and  Text Editors  for developing:  WebStorm  and  Netbeans  are full-fledged IDEs,  Sublime ,  Visual Studio Code  and  Atom  are powerful text and code editors  Baqend Starter Kits : Boilerplate projects connected to Baqend",
            "title": "Websites, Apps and Recommended Tooling"
        },
        {
            "location": "/topics/setup/#javascript-sdk",
            "text": "The JavaScript SDK is packaged as an UMD module, it can be used with RequireJS, browserify or without any module loader.\nTo get started please install the Baqend SDK with  npm  or  bower  or \ndownload the complete package from  GitHub .  Note:  If you are not using JavaScript you can use Baqend via its  REST API  from the programming language of your choice. Baqend's REST API is documented with  Swagger  and can be explored  here . In the  dashboard of you Baqend app  you can goto \"API Explorer\" to explore and use the REST API of your own instance.  To install Baqend, just add our CDN-hosted script in your website (available both over HTTPS and HTTP).  <script src=\"//www.baqend.com/js-sdk/latest/baqend.min.js\"></script>  \nFor additional setup information visit our  GitHub page .  Tip: \nIf you use our  Starter Kits  the Baqend SDK is already included and you can skip this setup.  Note: \nIt is generally a good idea to use the latest SDK version from  //www.baqend.com/js-sdk/latest/baqend.min.js  in development to always be up-to-date. In production, however, you should use the last exact version you tested with. Be aware that otherwise minor changes in a newly released version may break parts of your production application. See our  latest changes  to the SDK.  The Baqend SDK is written and tested for Chrome 24+, Firefox 18+, Internet Explorer 9+, Safari 7+, Node 4+, IOS 7+, Android 4+ and PhantomJS 1.9+  The Baqend SDK does not require any additional dependencies, however it is shipped with a few bundled dependencies:   core-js, a shim library  node-uuid, A uuid generator  validator, A validation library   The Baqend JavaScript SDK and all its bundled dependencies are shipped under the MIT License .  To see that Baqend is working, paste the following after the Baqend script tag. It will replace the HTML body with 5 raw todo items from the  tutorial application . Delete the snippet afterwards.  <script>\n  DB.connect('toodle').then(function() {\n    return DB.Todo.find().limit(5).resultList();\n  }).then(function(result) {\n    document.querySelector('body').innerHTML = \"<pre>\" + JSON.stringify(result, null, \" \") + \"</pre>\";\n  });\n</script>",
            "title": "Javascript SDK"
        },
        {
            "location": "/topics/setup/#baqend-nodejs",
            "text": "The Baqend SDK is fully compatible with  Node.js . This means you can use the SDK in a Node.js-based application for saving data, logging in users, etc. Additionally  Baqend modules  and  handlers  are based on Node.js and run and scaled automatically by Baqend.  To install the SDK for a Node.js project do an  npm install --save baqend  and use  require('baqend')  in your code.  var DB = require('baqend');\nDB.connect('example');  The Baqend SDK is compatible with Require.JS, Browserify, ES6 and TypeScript and all majors build tools (Gulp, Grunt, Webpack, NPM scripts, etc.).",
            "title": "Baqend + Node.js"
        },
        {
            "location": "/topics/setup/#connect-your-app-to-baqend",
            "text": "After including the Baqend SDK in your app, connect it with your Baqend. Simply call the connect\nmethod on the DB variable:  //connect to the example app\nDB.connect('example');\n//Or use a TLS-encrypted (SSL) connection to Baqend\nDB.connect('example', true);  Note:  If you use a custom deployment, e.g. the Baqend community edition you must pass a hostname or a complete URL\nto the connect call:  DB.connect('https://mybaqend.example.com/v1')  You can pass a callback as a second argument, which will be called when the connection is successfully established.  DB.connect('example', function() {\n  //work with the DB\n  DB.Todo.load(...)\n});  Behind the scenes Baqend is requested, the metadata of your app is loaded and the  Data Models  are created and initialized.\nIf you want to register the handler afterwards, you can use the ready method to wait on the SDK initialization.  DB.ready(function() { DB... //work with the DB });  If you are familiar with  Promises  you can alternatively use the returned promise instead of passing \na callback. This works for all places in the Baqend SDK that exhibit asynchronous behaviour.  DB.ready().then(function() {\n  DB... //work with the DB\n});  Tip:  Baqend not only gives you APIs for serverless development but also hosts and accelerates your assets, like HTML, CSS, images, etc. See  Hosting  for more details.",
            "title": "Connect your App to Baqend"
        },
        {
            "location": "/topics/setup/#accessing-data",
            "text": "After the Baqend SDK has been successfully initialized, all defined classes can be accessed using the DB instance. \nJust use the name of the class to access the  object factory .  DB.ready(function() {\n  DB.Todo //The Todo class factory\n});  The object factory can be called or can be used like a normal JavaScript constructor to create instances.  var todo = new DB.Todo({name: 'My first Todo'});  The constructor accepts one optional argument, which is a (JSON-)object containing the initial values of the object.  The object attributes can be accessed and changed by their names.  var todo = new DB.Todo({name: 'My first Todo'});\nconsole.log(todo.name); //'My first Todo'\ntodo.active = true;",
            "title": "Accessing Data"
        },
        {
            "location": "/topics/setup/#promises",
            "text": "Promise s are a programming paradigm to work with asynchronous code. Primarily used for communication and \nevent-scheduled tasks it makes code much more readable then the callback-based approach. A Promise represents the \npublic interface for\nan asynchronous operation and can be used to chain tasks that depend on each other.  The Baqend SDK supports both paradigms, therefore each asynchronous method accepts an optional success and an error\ncallback and returns a Promise for further tasks.  Basically there are two common ways to initialize a Promise. You can create a new instance of a Promise with an executor\nfunction. With the given resolve and reject function it can decide if the promise should be fulfilled with a given\nvalue or should be rejected with an error.  var promise = new Promise(function(resolve, reject) {\n  var delay = Math.random() * 2000 + 1000;\n  window.setTimeout(function() {\n  //We fulfill the promise after the randomized delay\n  resolve(delay);\n  }, Math.random() * 2000 + 1000);\n});  The second way is to create an already resolved Promise with a given value.  var promise = Promise.resolve(200);  If you want to listen for the outcome of such a promise you can register a onFulfilled and a onRejection listener with\n the  then(onFulfilled, onRejected)  method of the promise. When the promise gets resolved, the onFulfilled listener is\ncalled with the fulfilled value. In case of rejection the onRejected listener is called with the error.  promise.then(function(value) {\n  console.log('We have waited ' + value + 'ms');\n}, function(e) {\n  console.log('An unexpected error with message: ' + e.message + ' occurred.');\n});  The  Promise.then  method returns a new promise which will be resolved with the result of the passed listener.\nThe listener itself can also perform asynchronous operations and return another promise which will then be used to \nresolve the outer Promise.  promise.then(function(value) {\n  return anotherAsyncTask(value);\n}).then(function(anotherValue) {\n  //will only be called if the first promise \n  //and the anotherAsyncTask's Promise is fulfilled\n  //the anotherValue holds the fulfilled value of the anotherAsyncTask\n});  For additional examples and a more detailed explanation consult the  MDN Promise Documentation .  The Baqend SDK uses the promise-based approach for the entire documentation since the code is more readable and is\n generally considered the best way to work with asynchronous code in JavaScript.",
            "title": "Promises"
        },
        {
            "location": "/topics/crud/",
            "text": "CRUD\n\n\nEach entity has some basic methods for persisting and retrieving its data. This pattern is known as \ndata access \nobjects\n (DAO) or \nactive records\n and is common practice in persistence frameworks.\n\n\nCreate\n\n\nAfter creating a new object, the object can be persisted to Baqend with an \ninsert()\n call. The insert call ensures\nthat the object always get its own unique id by generating a new one if none was provided.\n\n\nvar todo = new DB.Todo({id: 'Todo1', name: 'My first Todo'});\n//we can use the object id right now\nconsole.log(todo.id) //'Todo1' \n\ntodo.insert().then(function() {\n  console.log(todo.version); //1\n});\n\n\n\n\nRead\n\n\nIf an object is persisted it can be loaded by its id (aka primary key). This method is very handy with custom (i.e. \nnon-generated) ids.\n\n\nDB.Todo.load('Todo1').then(function(todo) {\n  console.log(todo.name); //'My first Todo'  \n});\n\n\n\n\nIf an object is loaded from the Baqend all its attributes, collections and embedded objects will be loaded, too.\nReferences to other entities will not be loaded by default. You can, however, specify an optional \ndepth\n-parameter to indicate how deep referenced entities should be loaded:\n\n\nDB.Todo.load('Todo1', {depth: 1}).then(function(todo) {\n  // With 'depth: 1' all directly referenced objects will be loaded.\n});\n\n\n\n\nWhen you load the same object a second time, the object will be loaded from the local cache. This ensures that you\nalways get the same object instance for a given object id.\n\n\nDB.Todo.load('Todo1').then(function(todo1) {\n  DB.Todo.load('Todo1').then(function(todo2) {\n    console.log(todo1 === todo2); //true\n  });\n});\n\n\n\n\nUpdate\n\n\nAfter having loaded an instance and having done some modifications, you usually want to write the modifications back to\nBaqend.\n\n\ntodo.name = 'My first Todo of this day';\nreturn todo.update();\n\n\n\n\nThe \nupdate()\n method writes your changes back to Baqend, if no one else has already modified the object. To detect\nconcurrent object modifications, each entity has a version. Every time changes are written back to Baqend the \nversions will be matched. If the version in the Baqend differs form the provided version, the object was modified by \nsomeone else and the changes will be rejected, since the object is outdated, i.e. a concurrent modification occurred.\n This is called \noptimistic concurrency control\n: changes are performed locally and then sent to the server and only \n in the rare event of a consistency violation the change operation is rejected.\n\n\ntodo.name = 'My first Todo of this day';\nreturn todo.update().then(function() {\n  //the todo was successfully persisted\n}, function(e) {\n  //the update was rejected. Do we want to reapply our changes?\n});\n\n\n\n\n\n  \nNote:\n\n  When you try to update an already deleted object, it will also be treated as a concurrent modification and the update will be rejected.\n\n\n\n\nThere are also some situations where we would like to omit this behaviour and force a write of our changes. To do so the force option can be passed to the \nupdate\n method. Be aware that this \nlast-writer-wins\n-scheme may result in lost updates.\n\n\ntodo.name = 'My first Todo of this day';\n  //force the update and potentially overwrite all concurrent changes\nreturn todo.update({force: true}).then(function() {\n  //the todo was successfully persisted\n});\n\n\n\n\nEach object also automatically keeps track of its creation time and the last time it was updated in form of \nDateTime\n fields. Both of these fields are maintained automatically and are read only, i.e. you can not change them yourself.\n\n\ntodo.name = 'My first Todo of this day';\nreturn todo.update().then(function(updatedTodo) {\n  console.log(updatedTodo.createdAt);\n  console.log(updatedTodo.updatedAt);\n};\n\n\n\n\nDelete\n\n\nYou can delete an object by calling its \ndelete()\n method. It will delete the entity from Baqend and drop the entity\nfrom the local cache.\n\n\ntodo.delete().then(function() {\n  //the object was deleted\n}, function() {\n  //a concurrent modifications prevents removal\n});\n\n\n\n\nJust like the \nupdate()\n method, \ndelete()\n matches the local version with the version in the Baqend and \ndeletes the object only if the version is still up-to-date.\n\n\nAgain, you can pass the force option to bypass the version check.\n\n\ntodo.delete({force: true});\n\n\n\n\nSave\n\n\nAs you have seen in the previous examples you can \ninsert()\n new objects and \nupdate()\n existing objects. If it is\nirrelevant if the object is already persisted to the Baqend just use the \nsave()\n method. This either performs  an \nupdate or an insert, depending on the current state of the object.\n\n\nvar todo = new DB.Todo({id: 'Todo1', name: 'My first Todo'});\ntodo.save().then(function() { //inserts the object\n  todo.name = 'My first Todo of this day';\n  todo.save(); //updates the object\n});\n\n\n\n\nConcurrency with Optimistic Saving\n\n\nWithout the explicit \nforce\n flag, updates and saves can fail due to concurrent operations performed on the same object. With the \u00f2ptimisticSave` method you can conveniently specify the retry logic to apply, if the update fails. Even under high concurrency one writer will always succeed so that the system still makes progress.\n\n\nUnder the hood, this pattern of optimistic concurrency control relies on version numbers of the objects and conditional HTTP requests that only apply changes when the underlying object has not been changed.\n\n\nvar todo = new DB.Todo.load(\"myTodo\");\ntodo.optimisticSave(function(todo, abort) {\n  //this method may get called multiple times\n  if(todo.participants.length > 10) { \n    //you can specify when to stop reytring\n    abort();\n  }\n  todo.participants.push(\"Johnny\"); //apply a change --> will be saved automatically\n});\n\n\n\n\nTip:\n Optimistic saving is particularly useful for server-side code (\nmodules\n) that updates objects and may be invoked concurrently.\n\n\n\nLoad / Refresh\n\n\nSometimes you want to ensure, that you have the latest version of an previously loaded entity, for example before \nperforming an update. In that case you can use the \nload({refresh: true})\n method of the entity to get the latest \nversion from Baqend. \n\n\n//updates the local object with the most up-to-date version\ntodo.load({ refresh: true }).then(() => { \n  todo.name = 'My first Todo of this day';   \n  todo.save(); //updates the object\n});\n\n\n\n\nWhile performing an insert or update, you can also refresh the object after performing the operation. To do so you \ncan pass the \nrefresh\n flag to the \ninsert()\n, \nupdate()\n or \nsave()\n method.\n\n\ntodo.save({ refresh: true }).then(...); //refreshing the object after saving it\n\n\n\n\nThis option is very useful if you have a \nBaqend Code\n update handler which performs additional \nserver-side modifications on the entity being saved. By passing the \nrefresh\n flag you enforce that the modification will\n be loaded from the Baqend after the entity has been saved. \n\n\nRead-only Fields\n\n\nSome fields can't be manipulated by normal users, their update will be rejected.\nThose properties are:\n\n\n\n\n\u201ccreatedAt\u201d\n  contains the \nDate\n when the object was created.  \n\n\n\u201cupdatedAt\u201d\n  contains the \nDate\n of the last object update.\n\n\n\u201cusername\u201d\n  is the username of a user object.\n\n\n\u201cinactive\u201d\n  holds a boolean flag whether a user object is inactive.\n\n\n\n\nThe \nDB.getReference\n Method\n\n\nSometimes you don't need the fully loaded object, e.g. if you want to check if two users are part of the same role. \nIn that case, you don't need the loaded role to check the reference in both user objects.\nTherefore, the \nDB.getReference(id)\n method returns an unloaded object of the specific kind:\n\n\n//create a reference to the user with ID \u201c1\u201d\nconst userRef = DB.getReference('/db/User/1');\n\n//load the actual user object with all data\nlet user;\nuserRef.load(result => user = result);",
            "title": "CRUD"
        },
        {
            "location": "/topics/crud/#crud",
            "text": "Each entity has some basic methods for persisting and retrieving its data. This pattern is known as  data access \nobjects  (DAO) or  active records  and is common practice in persistence frameworks.",
            "title": "CRUD"
        },
        {
            "location": "/topics/crud/#create",
            "text": "After creating a new object, the object can be persisted to Baqend with an  insert()  call. The insert call ensures\nthat the object always get its own unique id by generating a new one if none was provided.  var todo = new DB.Todo({id: 'Todo1', name: 'My first Todo'});\n//we can use the object id right now\nconsole.log(todo.id) //'Todo1' \n\ntodo.insert().then(function() {\n  console.log(todo.version); //1\n});",
            "title": "Create"
        },
        {
            "location": "/topics/crud/#read",
            "text": "If an object is persisted it can be loaded by its id (aka primary key). This method is very handy with custom (i.e. \nnon-generated) ids.  DB.Todo.load('Todo1').then(function(todo) {\n  console.log(todo.name); //'My first Todo'  \n});  If an object is loaded from the Baqend all its attributes, collections and embedded objects will be loaded, too.\nReferences to other entities will not be loaded by default. You can, however, specify an optional  depth -parameter to indicate how deep referenced entities should be loaded:  DB.Todo.load('Todo1', {depth: 1}).then(function(todo) {\n  // With 'depth: 1' all directly referenced objects will be loaded.\n});  When you load the same object a second time, the object will be loaded from the local cache. This ensures that you\nalways get the same object instance for a given object id.  DB.Todo.load('Todo1').then(function(todo1) {\n  DB.Todo.load('Todo1').then(function(todo2) {\n    console.log(todo1 === todo2); //true\n  });\n});",
            "title": "Read"
        },
        {
            "location": "/topics/crud/#update",
            "text": "After having loaded an instance and having done some modifications, you usually want to write the modifications back to\nBaqend.  todo.name = 'My first Todo of this day';\nreturn todo.update();  The  update()  method writes your changes back to Baqend, if no one else has already modified the object. To detect\nconcurrent object modifications, each entity has a version. Every time changes are written back to Baqend the \nversions will be matched. If the version in the Baqend differs form the provided version, the object was modified by \nsomeone else and the changes will be rejected, since the object is outdated, i.e. a concurrent modification occurred.\n This is called  optimistic concurrency control : changes are performed locally and then sent to the server and only \n in the rare event of a consistency violation the change operation is rejected.  todo.name = 'My first Todo of this day';\nreturn todo.update().then(function() {\n  //the todo was successfully persisted\n}, function(e) {\n  //the update was rejected. Do we want to reapply our changes?\n});  \n   Note: \n  When you try to update an already deleted object, it will also be treated as a concurrent modification and the update will be rejected.  There are also some situations where we would like to omit this behaviour and force a write of our changes. To do so the force option can be passed to the  update  method. Be aware that this  last-writer-wins -scheme may result in lost updates.  todo.name = 'My first Todo of this day';\n  //force the update and potentially overwrite all concurrent changes\nreturn todo.update({force: true}).then(function() {\n  //the todo was successfully persisted\n});  Each object also automatically keeps track of its creation time and the last time it was updated in form of  DateTime  fields. Both of these fields are maintained automatically and are read only, i.e. you can not change them yourself.  todo.name = 'My first Todo of this day';\nreturn todo.update().then(function(updatedTodo) {\n  console.log(updatedTodo.createdAt);\n  console.log(updatedTodo.updatedAt);\n};",
            "title": "Update"
        },
        {
            "location": "/topics/crud/#delete",
            "text": "You can delete an object by calling its  delete()  method. It will delete the entity from Baqend and drop the entity\nfrom the local cache.  todo.delete().then(function() {\n  //the object was deleted\n}, function() {\n  //a concurrent modifications prevents removal\n});  Just like the  update()  method,  delete()  matches the local version with the version in the Baqend and \ndeletes the object only if the version is still up-to-date.  Again, you can pass the force option to bypass the version check.  todo.delete({force: true});",
            "title": "Delete"
        },
        {
            "location": "/topics/crud/#save",
            "text": "As you have seen in the previous examples you can  insert()  new objects and  update()  existing objects. If it is\nirrelevant if the object is already persisted to the Baqend just use the  save()  method. This either performs  an \nupdate or an insert, depending on the current state of the object.  var todo = new DB.Todo({id: 'Todo1', name: 'My first Todo'});\ntodo.save().then(function() { //inserts the object\n  todo.name = 'My first Todo of this day';\n  todo.save(); //updates the object\n});",
            "title": "Save"
        },
        {
            "location": "/topics/crud/#concurrency-with-optimistic-saving",
            "text": "Without the explicit  force  flag, updates and saves can fail due to concurrent operations performed on the same object. With the \u00f2ptimisticSave` method you can conveniently specify the retry logic to apply, if the update fails. Even under high concurrency one writer will always succeed so that the system still makes progress.  Under the hood, this pattern of optimistic concurrency control relies on version numbers of the objects and conditional HTTP requests that only apply changes when the underlying object has not been changed.  var todo = new DB.Todo.load(\"myTodo\");\ntodo.optimisticSave(function(todo, abort) {\n  //this method may get called multiple times\n  if(todo.participants.length > 10) { \n    //you can specify when to stop reytring\n    abort();\n  }\n  todo.participants.push(\"Johnny\"); //apply a change --> will be saved automatically\n});  Tip:  Optimistic saving is particularly useful for server-side code ( modules ) that updates objects and may be invoked concurrently.",
            "title": "Concurrency with Optimistic Saving"
        },
        {
            "location": "/topics/crud/#load-refresh",
            "text": "Sometimes you want to ensure, that you have the latest version of an previously loaded entity, for example before \nperforming an update. In that case you can use the  load({refresh: true})  method of the entity to get the latest \nversion from Baqend.   //updates the local object with the most up-to-date version\ntodo.load({ refresh: true }).then(() => { \n  todo.name = 'My first Todo of this day';   \n  todo.save(); //updates the object\n});  While performing an insert or update, you can also refresh the object after performing the operation. To do so you \ncan pass the  refresh  flag to the  insert() ,  update()  or  save()  method.  todo.save({ refresh: true }).then(...); //refreshing the object after saving it  This option is very useful if you have a  Baqend Code  update handler which performs additional \nserver-side modifications on the entity being saved. By passing the  refresh  flag you enforce that the modification will\n be loaded from the Baqend after the entity has been saved.",
            "title": "Load / Refresh"
        },
        {
            "location": "/topics/crud/#read-only-fields",
            "text": "Some fields can't be manipulated by normal users, their update will be rejected.\nThose properties are:   \u201ccreatedAt\u201d   contains the  Date  when the object was created.    \u201cupdatedAt\u201d   contains the  Date  of the last object update.  \u201cusername\u201d   is the username of a user object.  \u201cinactive\u201d   holds a boolean flag whether a user object is inactive.",
            "title": "Read-only Fields"
        },
        {
            "location": "/topics/crud/#the-dbgetreference-method",
            "text": "Sometimes you don't need the fully loaded object, e.g. if you want to check if two users are part of the same role. \nIn that case, you don't need the loaded role to check the reference in both user objects.\nTherefore, the  DB.getReference(id)  method returns an unloaded object of the specific kind:  //create a reference to the user with ID \u201c1\u201d\nconst userRef = DB.getReference('/db/User/1');\n\n//load the actual user object with all data\nlet user;\nuserRef.load(result => user = result);",
            "title": "The DB.getReference Method"
        },
        {
            "location": "/topics/schema/",
            "text": "Schema and Types\n\n\nBehind each object persisted to and loaded from Baqend there is a \nschema\n which describes the structure of its \ninstances. It specifies which attributes of an object will be tracked and saved (e.g. \nTodo.name\n, their types (e.g. \n\nString\n and optionally constraints (e.g. \nnot null\n).\n\n\nThe types that Baqend supports can be classified in five categories.\n\n\n\n\nEntities\n are the objects themselves, i.e. instances conforming to the schema\n\n\nReferences\n are references (i.e. links, foreign keys) to other entities.\n\n\nEmbeddables\n are objects that are embedded within other objects (i.e. value objects).\n\n\nPrimitives\n are native types like String, Numbers, Dates and JSON.\n\n\nCollections\n are lists, sets and maps containing any of the previous data types.\n\n\n\n\nData Modelling\n\n\nHere is an example for creating the data model of Todo objects in the dashboard:\n\n\n\n\nUnder the hood, Baqend stores data in MongoDB. However, in contrast to data modelling in MongoDB, Baqend supports a rich schema that is checked and validated whenever data ist stored. By using the JSON data types Baqend objects can have arbitrary schemaless parts.\n\n\nTip:\n Best practices for \nschemaless\n and \nschema-rich\n data modelling can both be applied in Baqend by mixing data types with JSON.\n\n\n\nEmbedding vs Referencing\n\n\nThe major decision when modelling data in Baqend is the choice between embedding and referencing.\n\n\nWith embedding, related content is stored together. This is also called \ndenormalization\n as the data might be duplicated in multiple places. Embedding is useful for:\n\n\n\n\nModelling \ncontains\n relationships. For example a shipping address is \"contained\" in an invoice object.\n\n\nModelling \none-to-many\n (1:n), aggregation and composition relationships. For example a Todo list is composed of multiple todo items.\n\n\n\n\nThe advantage of embedding is that data can be read in one chunk making retrieval more efficient. The downside is that whenever embedded objects are contained in multiple parent objects, more than one update has to be made in order to keep all instances of the embedded object consistent with each other.\n\n\n\n\nWith referencing, dependent data is not embedded, but instead references are followed to find related objects. In the world of relational database systems this is called \nnormalization\n and the references foreign keys. Referencing is a good choice if:\n\n\n\n\nData is used in multiple places.\n\n\nFor many-to-many (n:m) relationships. For example a \"friends with\" relationship would best be modelled by a list of references to friend profile objects.\n\n\nDeep hierarchies have to be modelled, e.g. the namespace of a file system.\n\n\n\n\nThe downside of referencing is that multiple reads and updates are required if connected data is changed. With the \ndepth\n-parameter you can, however, load and save entities with all its references. See \nreferences\n.\n\n\nEntity Objects\n\n\nIn general there are two types of objects. The first type - \nEntities\n - are those objects which have their own \nidentity, version and access rights. They can be directly saved, loaded and updated. Each entity has its own unique \nid. The id is immutable and set at object creation time.\n\n\nvar todo = new DB.Todo({name: 'My first Todo'});\nconsole.log(todo.id); //'84b9...'\n\n\n\n\nInstead of relying on automatic generation, objects can also have a \ncustom id\n. This allows to assign ids that are \nmemorable and meaningful.\n\n\nvar todo = new DB.Todo({id: 'Todo1', name: 'My first Todo'});\nconsole.log(todo.id); //'Todo1'\ntodo.save();\n\n\n\n\nNote:\n The save call will be rejected, if the id already exists!\n\n\n\nReferences\n\n\nEntity objects can reference other entities by reference, i.e. their id. Referenced objects will not be persisted \ninside another entity, instead only a reference to the other entity is be persisted.\n\n\nvar firstTodo = new DB.Todo({name: 'My first Todo'});\nvar secondTodo = new DB.Todo({name: 'My second Todo'});\n\nfirstTodo.doNext = secondTodo;\n\n\n\n\nTo save a reference, you just call the \nsave()\n method on the referencing entity.\n\n\n//the todo instance will automatically be serialized to a object reference\nfirstTodo.save();\n\n\n\n\nInternally, the reference is converted to a string like \n/db/Todo/84b9...\n and persisted inside the referencing entity. The referenced entity will not be saved by default. You can pass the \ndepth\n options flag to the save the complete object graph by \nreachability.\n\n\n//will also save secondTodo, since it is referenced by firstTodo\nfirstTodo.save({depth: true});\n\n\n\n\nWhen an entity is loaded from Baqend, referenced entities will not be loaded by default. Instead an unresolved entity\n(hollow object) is set for the referenced entity. If you try to access attributes of an unresolved entity, an \nobject is\n not available\n error will be thrown.\n\n\n//while loading the todo, the reference will be resolved to the referenced entity\nDB.Todo.load('7b2c...').then(function(firstTodo) {\n  console.log(firstTodo.name); //'My first Todo'\n  console.log(firstTodo.doNext.name); //will throw an object not available error\n});\n\n\n\n\nThe \nisReady\n field indicates if an entity is already resolved.\n\n\nDB.Todo.load('7b2c...').then(function(firstTodo) {\n  console.log(firstTodo.doNext.isReady); //false\n});\n\n\n\n\nCalling \nload()\n on an unresolved entity resolved it, i.e. the referenced object is loaded.\n\n\nfirstTodo.doNext.load(function() {\n  console.log(firstTodo.doNext.isReady); //true\n  console.log(firstTodo.doNext.name); //'My second Todo'\n});\n\n\n\n\nIf the object graph is not very deep, references can easily be resolved by reachability.\n\n\n//loading the todo will also load the referenced todo\nDB.Todo.load('7b2c...', {depth: true}).then(function(firstTodo) {\n  console.log(firstTodo.name); //'My first Todo'\n  console.log(firstTodo.doNext.name); //'My second Todo'\n});\n\n\n\n\nFor further information on persisting and loading strategies see the \nDeep Loading\n chapter.\n\n\nEmbedded Objects\n\n\nThe second type of objects are \nembedded objects\n. They can be used within an entity or a\ncollection like a list or map. They do not have an id and can only exist within an entity. Embedded objects are\nsaved, loaded and updated with their owning entity and will be persisted together with it. Embedded objects thus have\n the structure of a object but the behaviour of a primitive type (e.g. a String). This concept is also known as \nvalue\n  types\n, \nuser-defined types\n or \nsecond class objects\n.\n\n\nEmbedded objects can be created and used like entity objects.\n\n\nvar activity = new DB.Activity({start: new Date()});\nconsole.log(activity.start); //something like 'Tue Mar 24 2015 10:46:13 GMT'\nactivity.end = new Date();\n\n\n\n\nSince embeddables do not have an identity, they hold neither an id, version nor acl attribute.\n\n\nvar activity = new DB.Activity({start: new Date()});\nconsole.log(activity.id); //undefined\n\n\n\n\nTo actually persist an embedded object you have to assign the embedded object to an entity and save that outer entity.\n\n\nvar activity = new DB.Activity({start: new Date()});\nvar todo = new DB.Todo({name: 'My first Todo', activities: [activity]});\ntodo.save();\n\n\n\n\nPrimitives\n\n\nPrimitives types are the basic attribute types and known from programming languages. Whenever an entity is saved, all\nattribute values will be checked against the types described by the schema. This is one of the biggest advantages of \nhaving a schema: data cannot easily be corrupted as its correct structure is automatically enforced by the schema. \nPlease note that the JSON data type gives you full freedom on deciding which parts of a object should be structured \nand which parts are schema free. The following table shows all supported attribute types of Baqend \nand their corresponding JavaScript types.\n\n\n\n  \n\n    \nBaqend Primitive\n\n    \nJavaScript type\n\n    \nExample\n\n    \nNotes\n\n  \n\n  \n\n    \nString\n\n    \nString\n\n    \n\"My Sample String\"\n\n    \n\n  \n\n  \n\n    \nInteger\n\n    \nNumber\n\n    \n456\n\n    \n64bit integer. Fractions are deleted\n\n  \n\n  \n\n    \nDouble\n\n    \nNumber\n\n    \n456.456\n\n    \n64bit floating point numbers\n\n  \n\n  \n\n    \nBoolean\n\n    \nBoolean\n\n    \ntrue\n\n    \n\n  \n\n  \n\n    \nDateTime\n\n    \nDate(<datetime>)\n\n    \nnew Date()\n\n    \nThe date will be normalized to GMT.\n\n  \n\n  \n\n    \nDate\n\n    \nDate(<date>)\n\n    \nnew Date('2015-03-15')\n\n    \nThe time part of the date will be stripped out.\n\n  \n\n  \n\n    \nTime\n\n    \nDate(<datetime>)\n\n    \nnew Date('2015-01-15T13:30:00Z')\n\n    \nThe date part of the date will be stripped out and the time will be saved in GMT.\n\n  \n\n  \n\n    \nFile\n\n    \nFile(<fileId>)\n\n    \nnew File('/file/www/my.png')\n\n    \nThe file id points to an uploaded file.\n\n  \n\n  \n\n    \nGeoPoint\n\n    \nDB.GeoPoint(<lat>, <lng>)\n\n    \nnew DB.GeoPoint(53.5753, 10.0153)\n\n    \nYou can get the current GeoPoint of the User with \nGeoPoint.current()\n. This only works with an HTTPS connection.\n\n  \n\n  \n\n    \nJsonObject\n\n    \nObject\n\n    \n{\"name\": \"Test\"}\n\n    \nSemistructured JSON is embedded within the entity. Any valid JSON is allowed.\n\n  \n\n  \n\n    \nJsonArray\n\n    \nArray\n\n    \n[1,2,3]\n\n  \n\n\n\n\n\nCollections\n\n\nCollections are typed by a reference, embedded object class or a primitive type. The Baqend SDK \nsupports 3 type of collections, which are mapped to native JavaScript arrays, es6 sets and maps:\n\n\n\n  \n\n    \nBaqend Collection\n\n    \nExample\n\n    \nSupported element Types\n\n  \n\n  \n\n    \ncollection.List\n\n    \nnew DB.List([1,2,3])\n or \n \nnew Array(1,2,3)\n\n    \nAll non-collection types are supported as values\n\n  \n\n  \n\n    \ncollection.Set\n\n    \nnew DB.Set([1,2,3])\n or \n \nnew Set([1,2,3])\n\n    \nOnly String, Boolean, Integer, Double, Date, Time, DateTime and References are allowed as values. Only this\n    types can be compared by identity.\n\n  \n\n  \n\n    \ncollection.Map\n\n    \nnew DB.Map([[\"x\", 3], [\"y\", 5]])\n or \n \nnew Map([[\"x\", 3], [\"y\", 5]])\n\n    \nOnly String, Boolean, Integer, Double, Date, Time, DateTime and References are allowed as keys.\n\n    All non collection types are supported as values.\n\n  \n\n\n\n\nFor all collection methods see the MDN docs of \n\nArray\n,\n\nSet\n and \n\nMap",
            "title": "Schema and Types"
        },
        {
            "location": "/topics/schema/#schema-and-types",
            "text": "Behind each object persisted to and loaded from Baqend there is a  schema  which describes the structure of its \ninstances. It specifies which attributes of an object will be tracked and saved (e.g.  Todo.name , their types (e.g.  String  and optionally constraints (e.g.  not null ).  The types that Baqend supports can be classified in five categories.   Entities  are the objects themselves, i.e. instances conforming to the schema  References  are references (i.e. links, foreign keys) to other entities.  Embeddables  are objects that are embedded within other objects (i.e. value objects).  Primitives  are native types like String, Numbers, Dates and JSON.  Collections  are lists, sets and maps containing any of the previous data types.",
            "title": "Schema and Types"
        },
        {
            "location": "/topics/schema/#data-modelling",
            "text": "Here is an example for creating the data model of Todo objects in the dashboard:   Under the hood, Baqend stores data in MongoDB. However, in contrast to data modelling in MongoDB, Baqend supports a rich schema that is checked and validated whenever data ist stored. By using the JSON data types Baqend objects can have arbitrary schemaless parts.  Tip:  Best practices for  schemaless  and  schema-rich  data modelling can both be applied in Baqend by mixing data types with JSON.",
            "title": "Data Modelling"
        },
        {
            "location": "/topics/schema/#embedding-vs-referencing",
            "text": "The major decision when modelling data in Baqend is the choice between embedding and referencing.  With embedding, related content is stored together. This is also called  denormalization  as the data might be duplicated in multiple places. Embedding is useful for:   Modelling  contains  relationships. For example a shipping address is \"contained\" in an invoice object.  Modelling  one-to-many  (1:n), aggregation and composition relationships. For example a Todo list is composed of multiple todo items.   The advantage of embedding is that data can be read in one chunk making retrieval more efficient. The downside is that whenever embedded objects are contained in multiple parent objects, more than one update has to be made in order to keep all instances of the embedded object consistent with each other.   With referencing, dependent data is not embedded, but instead references are followed to find related objects. In the world of relational database systems this is called  normalization  and the references foreign keys. Referencing is a good choice if:   Data is used in multiple places.  For many-to-many (n:m) relationships. For example a \"friends with\" relationship would best be modelled by a list of references to friend profile objects.  Deep hierarchies have to be modelled, e.g. the namespace of a file system.   The downside of referencing is that multiple reads and updates are required if connected data is changed. With the  depth -parameter you can, however, load and save entities with all its references. See  references .",
            "title": "Embedding vs Referencing"
        },
        {
            "location": "/topics/schema/#entity-objects",
            "text": "In general there are two types of objects. The first type -  Entities  - are those objects which have their own \nidentity, version and access rights. They can be directly saved, loaded and updated. Each entity has its own unique \nid. The id is immutable and set at object creation time.  var todo = new DB.Todo({name: 'My first Todo'});\nconsole.log(todo.id); //'84b9...'  Instead of relying on automatic generation, objects can also have a  custom id . This allows to assign ids that are \nmemorable and meaningful.  var todo = new DB.Todo({id: 'Todo1', name: 'My first Todo'});\nconsole.log(todo.id); //'Todo1'\ntodo.save();  Note:  The save call will be rejected, if the id already exists!",
            "title": "Entity Objects"
        },
        {
            "location": "/topics/schema/#references",
            "text": "Entity objects can reference other entities by reference, i.e. their id. Referenced objects will not be persisted \ninside another entity, instead only a reference to the other entity is be persisted.  var firstTodo = new DB.Todo({name: 'My first Todo'});\nvar secondTodo = new DB.Todo({name: 'My second Todo'});\n\nfirstTodo.doNext = secondTodo;  To save a reference, you just call the  save()  method on the referencing entity.  //the todo instance will automatically be serialized to a object reference\nfirstTodo.save();  Internally, the reference is converted to a string like  /db/Todo/84b9...  and persisted inside the referencing entity. The referenced entity will not be saved by default. You can pass the  depth  options flag to the save the complete object graph by \nreachability.  //will also save secondTodo, since it is referenced by firstTodo\nfirstTodo.save({depth: true});  When an entity is loaded from Baqend, referenced entities will not be loaded by default. Instead an unresolved entity\n(hollow object) is set for the referenced entity. If you try to access attributes of an unresolved entity, an  object is\n not available  error will be thrown.  //while loading the todo, the reference will be resolved to the referenced entity\nDB.Todo.load('7b2c...').then(function(firstTodo) {\n  console.log(firstTodo.name); //'My first Todo'\n  console.log(firstTodo.doNext.name); //will throw an object not available error\n});  The  isReady  field indicates if an entity is already resolved.  DB.Todo.load('7b2c...').then(function(firstTodo) {\n  console.log(firstTodo.doNext.isReady); //false\n});  Calling  load()  on an unresolved entity resolved it, i.e. the referenced object is loaded.  firstTodo.doNext.load(function() {\n  console.log(firstTodo.doNext.isReady); //true\n  console.log(firstTodo.doNext.name); //'My second Todo'\n});  If the object graph is not very deep, references can easily be resolved by reachability.  //loading the todo will also load the referenced todo\nDB.Todo.load('7b2c...', {depth: true}).then(function(firstTodo) {\n  console.log(firstTodo.name); //'My first Todo'\n  console.log(firstTodo.doNext.name); //'My second Todo'\n});  For further information on persisting and loading strategies see the  Deep Loading  chapter.",
            "title": "References"
        },
        {
            "location": "/topics/schema/#embedded-objects",
            "text": "The second type of objects are  embedded objects . They can be used within an entity or a\ncollection like a list or map. They do not have an id and can only exist within an entity. Embedded objects are\nsaved, loaded and updated with their owning entity and will be persisted together with it. Embedded objects thus have\n the structure of a object but the behaviour of a primitive type (e.g. a String). This concept is also known as  value\n  types ,  user-defined types  or  second class objects .  Embedded objects can be created and used like entity objects.  var activity = new DB.Activity({start: new Date()});\nconsole.log(activity.start); //something like 'Tue Mar 24 2015 10:46:13 GMT'\nactivity.end = new Date();  Since embeddables do not have an identity, they hold neither an id, version nor acl attribute.  var activity = new DB.Activity({start: new Date()});\nconsole.log(activity.id); //undefined  To actually persist an embedded object you have to assign the embedded object to an entity and save that outer entity.  var activity = new DB.Activity({start: new Date()});\nvar todo = new DB.Todo({name: 'My first Todo', activities: [activity]});\ntodo.save();",
            "title": "Embedded Objects"
        },
        {
            "location": "/topics/schema/#primitives",
            "text": "Primitives types are the basic attribute types and known from programming languages. Whenever an entity is saved, all\nattribute values will be checked against the types described by the schema. This is one of the biggest advantages of \nhaving a schema: data cannot easily be corrupted as its correct structure is automatically enforced by the schema. \nPlease note that the JSON data type gives you full freedom on deciding which parts of a object should be structured \nand which parts are schema free. The following table shows all supported attribute types of Baqend \nand their corresponding JavaScript types.  \n   \n     Baqend Primitive \n     JavaScript type \n     Example \n     Notes \n   \n   \n     String \n     String \n     \"My Sample String\" \n     \n   \n   \n     Integer \n     Number \n     456 \n     64bit integer. Fractions are deleted \n   \n   \n     Double \n     Number \n     456.456 \n     64bit floating point numbers \n   \n   \n     Boolean \n     Boolean \n     true \n     \n   \n   \n     DateTime \n     Date(<datetime>) \n     new Date() \n     The date will be normalized to GMT. \n   \n   \n     Date \n     Date(<date>) \n     new Date('2015-03-15') \n     The time part of the date will be stripped out. \n   \n   \n     Time \n     Date(<datetime>) \n     new Date('2015-01-15T13:30:00Z') \n     The date part of the date will be stripped out and the time will be saved in GMT. \n   \n   \n     File \n     File(<fileId>) \n     new File('/file/www/my.png') \n     The file id points to an uploaded file. \n   \n   \n     GeoPoint \n     DB.GeoPoint(<lat>, <lng>) \n     new DB.GeoPoint(53.5753, 10.0153) \n     You can get the current GeoPoint of the User with  GeoPoint.current() . This only works with an HTTPS connection. \n   \n   \n     JsonObject \n     Object \n     {\"name\": \"Test\"} \n     Semistructured JSON is embedded within the entity. Any valid JSON is allowed. \n   \n   \n     JsonArray \n     Array \n     [1,2,3]",
            "title": "Primitives"
        },
        {
            "location": "/topics/schema/#collections",
            "text": "Collections are typed by a reference, embedded object class or a primitive type. The Baqend SDK \nsupports 3 type of collections, which are mapped to native JavaScript arrays, es6 sets and maps:  \n   \n     Baqend Collection \n     Example \n     Supported element Types \n   \n   \n     collection.List \n     new DB.List([1,2,3])  or    new Array(1,2,3) \n     All non-collection types are supported as values \n   \n   \n     collection.Set \n     new DB.Set([1,2,3])  or    new Set([1,2,3]) \n     Only String, Boolean, Integer, Double, Date, Time, DateTime and References are allowed as values. Only this\n    types can be compared by identity. \n   \n   \n     collection.Map \n     new DB.Map([[\"x\", 3], [\"y\", 5]])  or    new Map([[\"x\", 3], [\"y\", 5]]) \n     Only String, Boolean, Integer, Double, Date, Time, DateTime and References are allowed as keys. \n    All non collection types are supported as values. \n     For all collection methods see the MDN docs of  Array , Set  and  Map",
            "title": "Collections"
        },
        {
            "location": "/topics/queries/",
            "text": "Queries\n\n\nTo retrieve objects by more complex criteria than their id, queries can be used. They are executed on Baqend and \nreturn the matching objects.\nThe Baqend SDK features a \nquery builder\n that creates\n\nMongoDB queries\n under the hood. It is possible\n to formulate native MongoDB queries, but using the query builder is the recommend way: it is far more readable and \n does all the plumbing and abstraction from MongoDB obscurities.\n\n\nresultList, singleResult and count\n\n\nThe simplest query is one that has no filter criterion and thus returns all objects. \nThe actual result is retrieved via the \nresultList\n method.\n\n\nDB.Todo.find().resultList(function(result) {\n  result.forEach(function(todo) {\n    console.log(todo.name); //'My first Todo', 'My second Todo', ...\n  });\n});\n\n\n\n\nYou can also use the \ndepth\n-parameter to query the entities to a specified depth just like for normal \nreads\n.\n\n\nTo find just the first matching object use the \nsingleResult\n method.\n\n\nDB.Todo.find().singleResult(function(todo) {\n  console.log(todo.name); //'My first Todo'\n});\n\n\n\n\nBoth \nresultList\n and \nsingleResult\n \nsupport deep loading\n to also load references.\n\n\nIf you just need the number of matching objects, use the \ncount\n method.\n\n\nDB.Todo.find().count(function(count) {\n  console.log(count); //'17'\n});\n\n\n\n\nFilters\n\n\nUsually queries are employed to exert some kind of filter. The query builder supports lots of different \n\nfilters\n,\nthat can be applied on entity attributes. By default chained filters are \nand\n-combined.\n\n\nDB.Todo.find()\n  .matches('name', /^My Todo/)\n  .equal('active', true)\n  .lessThanOrEqualTo('activities.start', new Date())\n  .resultList(...)\n\n\n\n\nThe above query searches for all todos, whose name starts with \n'My Todo'\n, are currently active and contain an \nactivity in its activities list that has been started before the current date.\n\n\nNote that all valid MongoDB attribute expressions can be used as a field name in a filter, in particular \npath-expressions such as 'activities.start'.\n\n\nIf you are familiar with \nMongoDB queries\n, you can\nuse the \nwhere\n method to describe a query in MongoDB's JSON format. An equivalent query to the above one would look \nlike this:\n\n\nDB.Todo.find()\n  .where({\n    \"name\": { \"$regex\": \"^My Todo\" },\n    \"active\": true,\n    \"activities.start\": { \"$lte\": { \"$date\": new Date().toISOString() }}\n  })\n  .resultList(...)\n\n\n\n\nThe following table list all available query filters and the types on which they can be applied:\n\n\n\n  \n\n  \n\n    \nFilter method\n\n  \n\n  \n  \n    \n\n      MongoDB equivalent\n    \n\n    \nSupported types\n\n    \nNotes\n\n  \n\n  \n\n  \n\n  \n\n    \nequal('name', 'My Todo')\n\n  \n\n  \n\n    \n$eq\n\n    \nAll types\n\n    \nComplex types like embedded objects only match if their complete structure matches.\n\n  \n\n  \n\n    \nnotEqual('name', 'My Todo')\n\n  \n\n  \n  \n    \n$neq\n\n    \nAll types\n\n    \nComplex types like embedded objects only match if their complete structure matches.\n\n  \n\n  \n\n    \ngreaterThan('total', 3)\n\n  \n\n  \n  \n    \n$gt\n\n    \nNumbers, Dates, Strings\n\n    \ngt()\n is an alias\n\n  \n\n  \n\n    \ngreaterThanOrEqualTo('total', 3)\n\n  \n\n  \n  \n    \n$gte\n\n    \nNumbers, Dates, Strings\n\n    \nge()\n is an alias\n\n  \n\n  \n\n    \nlessThan('total', 3)\n\n  \n  \n  \n  \n    \n$lt\n\n    \nNumbers, Dates, Strings\n\n    \nlt()\n is an alias\n\n  \n\n  \n\n    \nlessThanOrEqualTo('total', 3)\n\n  \n\n  \n  \n    \n$lte\n\n    \nNumbers, Dates, Strings\n\n    \nle()\n is an alias\n\n  \n\n  \n\n    \nbetween('total', 3, 5)\n\n  \n\n  \n  \n    \n-\n\n    \nNumbers, Dates, Strings\n\n    \nIt is equivalent to \ngt('total', 3).lt('total', 5)\n\n  \n\n  \n\n    \nin('total', 3, 5[,...])\n\n  \n\n  \n  \n    \n$in\n\n    \nAll types\n\n    \n\n        For primitive fields \nany\n of the given values have to match the field value.\n        On set and list fields \nat least one\n value must be contained in the collection in order for the \n        filter to match. \n    \n\n  \n\n  \n\n    \nnotIn('total', 3, 5[,...])\n\n  \n\n  \n  \n    \n$nin\n\n    \nAll types\n\n    \n\n      On primitive fields \nnone\n of the given values must match the field value. \n      On set and list fields \nnone\n of the given values must to be contained in the collection in order \n      for the filter to match.\n    \n\n  \n\n  \n\n    \nisNull('name')\n\n  \n\n  \n  \n    \n-\n\n    \nAll types\n\n    \nChecks if the field has no value; equivalent to \nequal('name', null)\n\n  \n\n  \n\n    \nisNotNull('name')\n\n  \n\n  \n  \n    \n$exists\n\n    \nAll types\n\n    \n\n      Checks if the field has a value; equivalent to \nwhere({'name': {\"$exists\" true, \"$ne\", null})\n\n    \n\n  \n\n  \n\n    \ncontainsAny('activities', activity1, activity2 [,...])\n\n  \n\n  \n  \n    \n$in\n\n    \nList, Set, JsonArray\n\n    \nChecks if the collection contains any of the given elements\n\n  \n\n  \n\n    \ncontainsAll('activities', activity1, activity2 [,...])\n\n  \n\n  \n  \n    \n$all\n\n    \nList, Set, JsonArray\n\n    \nChecks if the collection contains all of the given elements\n\n  \n\n  \n\n    \nmod('total', 5, 3)\n\n  \n\n  \n\n    \n$mod\n\n    \nNumber\n\n    \nThe field value divided by divisor must be equal to the remainder\n\n  \n\n  \n\n    \nmatches('name', /^My [eman]{4}/)\n\n  \n\n  \n  \n    \n$regex\n\n    \nString\n\n    \n\n      The regular expression must be anchored (starting with \n^\n); ignore case and global flags are not\n      supported.\n    \n\n  \n\n  \n\n    \nsize('activities', 3)\n\n  \n\n  \n  \n    \n$size\n\n    \nList, Set, JsonArray\n\n    \nMatches if the collection has the specified size.\n\n  \n\n  \n\n    \nnear('location', <geo point>, 1000)\n\n  \n\n  \n  \n    \n$nearSphere\n\n    \nGeoPoint\n\n    \n\n      The geo point field has to be within the maximum distance in meters to the given GeoPoint.\n      Returns from nearest to furthest.\n\n      You need a Geospatial Index on this field, to use this kind of query. Read the query index section for more details.\n    \n\n  \n\n  \n\n    \nwithinPolygon('location', <geo point list>)\n\n  \n\n  \n  \n    \n$geoWithin\n\n    \nGeoPoint\n\n    \n\n      The geo point of the object has to be contained within the given polygon.\n      You need a Geospatial Index on this field, to use this kind of query. Read the [query indexes](../queries#query-indexes) section \n      for more details.\n    \n\n  \n\n  \n\n\n\n\n\nYou can get the current GeoPoint of the User with \nDB.GeoPoint.current()\n. This only works with an HTTPS connection.\n\n\nReferences can and should be used in filters. Internally references are converted to ids\n and used for filtering. To get all Todos owned by the currently logged-in user, we can simply use the User instance \n in the query builder:\n\n\nDB.Todo.find()\n  .equal('owner', DB.User.me) //any other User reference is also valid here\n  .resultList(...)\n\n\n\n\nNote:\n \nDB.user.me\n refers to the currently logged-in User instance. To learn more about users and the\nlogin process see the \nUser, Roles and Permission chapter\n.\n\n\n\nSorting\n\n\nIt is possible to sort the query result for one or more attributes. The query builder can be used to specify \nwhich attributes shall be used for sorting. Let's sort our query result by name:\n\n\nDB.Todo.find()\n  .matches('name', /^My Todo/)\n  .ascending('name')\n  .resultList(...)\n\n\n\n\nIf you use more than one sort criterion, the order of the result reflects the order in which the sort methods were \ncalled. The following query will list all active tasks before the inactive ones and sort the tasks by their name in \nascending order.\n\n\nDB.Todo.find()\n  .matches('name', /^My Todo/)\n  .ascending('name')\n  .descending('active')\n  .resultList(...)\n\n\n\n\nWhen calling \ndescending('active')\n before \nascending('name')\n the result is sorted by name and \nthen by active flag, which is only relevant for multiple todos having the same name. \n\n\nYou can also set the sort criteria with the MongoDB \norderby\n \nsyntax by using the \nsort()\n method. An equivalent expression to the above is this:\n\n\nDB.Todo.find()\n  .matches('name', /^My Todo/)\n  .sort({\"name\": 1, \"active\": -1})\n  .resultList(...)\n\n\n\n\nOffset and Limit\n\n\nOn larger data sets you usually don't want to load everything at once. Its often reasonable to instead page through the \nquery results. It is therefore possible to skip objects and limit the result size.\n\n\nvar page = 3;\nvar resultsPerPage = 30;\n\nDB.Todo.find()\n  .matches('name', /^My Todo/)\n  .ascending('name')\n  .offset((page - 1) * resultsPerPage)\n  .limit(resultsPerPage)\n  .resultList(...)\n\n\n\n\nNote:\n An offset query on large result sets yields [poor query performance](http://use-the-index-luke\n.com/sql/partial-results/fetch-next-page). Instead, consider using a filter and sort criteria to navigate through \nresults.\n\n\n\nFor instance if you implement a simple pagination, you can sort by id and can get the data of the next\npage by a simple greaterThen filter. As the id always has an index this results in good performance regardless of the\n query result size.\n\n\nvar pageId = '00000-...';\nvar resultsPerPage = 30;\n\nDB.Todo.find()\n  .matches('name', /^My Todo/)\n  .greaterThan('id', pageId)\n  .ascending('id', pageId)\n  .limit(resultsPerPage)\n  .resultList(function(result) {\n    pageId = result[result.length - 1];  \n  })\n\n\n\n\nBut often you want to sort your result by another attribute (e.g. \ncreatedAt\n). When you sort by an attribute which \nby itself is not unique you must combine it with a unique attribute (e.g. \nid\n). \n\n\n//initialize default values\nvar resultsPerPage = 30;\nvar lastObject = {id: '', createdAt: new Date(0)};\n\n//later page through the pages by the following query\nvar qb = DB.Todo.find(); \nqb.or(qb.equal('createdAt', lastObject.createdAt).greaterThan('id', lastObject.id), qb.greaterThan('createdAt', lastObject.createdAt))\n     .ascending('createdAt')\n     .ascending('id')\n     .limit(resultsPerPage)\n     .resultList(function(result) {\n        //track last seen object\n        lastObject = result[result.length - 1]; \n        console.log(result);\n      });\n\n\n\n\nExplanation:\n By combining the results of the query which fetches all remaining entities where the \ncreatedAt\n is equal to our last seen \ncreatedAt\n \nplus all ids which are greater than the last seen \nid\n we make our result unique when \ncreatedAt\n has the same value on \nmultiple entities. That guarantees a unique order for none unique attributes.\n\n\nComposing Filters by \nand\n, \nor\n and \nnor\n\n\nFilters are joined with \nand\n by default. In more complex cases you may want to formulate a query with one or more \n\nand\n, \n\nor\n or \n\nnor\n  expressions. \nFor such cases the initial \nfind()\n call returns a \n\nQuery.Builder\n instance. The builder provides\nadditional methods to compose filter expressions.\n\n\nThe following query finds all todos which the logged-in user is not currently working on and all todos which aren't \ndone yet:\n\n\nvar queryBuilder = DB.Todo.find();\nvar condition1 = queryBuilder\n  .matches('name', /^My Todo/)\n  .equal('active', false);\n\nvar condition2 = queryBuilder\n  .matches('name', /^Your Todo/)\n  .equal('done', false);\n\nqueryBuilder.or(condition1, condition2)\n  .ascending('name')\n  .resultList(...)\n\n\n\n\nQuery Indexes\n\n\nIndexes on fields that are frequently queried can massively impact the overall query performance. Therefore our Dashboard\nprovides a very comfortable way to create custom indexes on fields. It is always an tradeof on which fields you should \ncreate an index. A good index should be created on fields that contains many distinct values. But to many indexes on the \nsame class can also reduce the write throughput. If you like to read more about indexes we currently use, visit the mongo\n\nindexes docs\n.\n\n\nTo create an Index open the schema view of the class and use the \nIndex\n or \nUnique Index\n button to create an index. \nCurrently we support three types of indexes: \n\n\nIndex:\n A simple index which contains a single field used to improve querys which filters the specified field. \n\n\nUnique Index:\n A index that requires uniqueness of the field values. Inserting or updating objects that violates the \n unique constraint will be rejected with an ObjectExists error.\n\n\nGeospatial Index:\n This index can be created on GeoPoint fields and is required for \nnear\n and \nwithinPolygon\n query\nfilters. This Index is created on GeoPoint fields by using the \nIndex\n Button.",
            "title": "Queries"
        },
        {
            "location": "/topics/queries/#queries",
            "text": "To retrieve objects by more complex criteria than their id, queries can be used. They are executed on Baqend and \nreturn the matching objects.\nThe Baqend SDK features a  query builder  that creates MongoDB queries  under the hood. It is possible\n to formulate native MongoDB queries, but using the query builder is the recommend way: it is far more readable and \n does all the plumbing and abstraction from MongoDB obscurities.",
            "title": "Queries"
        },
        {
            "location": "/topics/queries/#resultlist-singleresult-and-count",
            "text": "The simplest query is one that has no filter criterion and thus returns all objects. \nThe actual result is retrieved via the  resultList  method.  DB.Todo.find().resultList(function(result) {\n  result.forEach(function(todo) {\n    console.log(todo.name); //'My first Todo', 'My second Todo', ...\n  });\n});  You can also use the  depth -parameter to query the entities to a specified depth just like for normal  reads .  To find just the first matching object use the  singleResult  method.  DB.Todo.find().singleResult(function(todo) {\n  console.log(todo.name); //'My first Todo'\n});  Both  resultList  and  singleResult   support deep loading  to also load references.  If you just need the number of matching objects, use the  count  method.  DB.Todo.find().count(function(count) {\n  console.log(count); //'17'\n});",
            "title": "resultList, singleResult and count"
        },
        {
            "location": "/topics/queries/#filters",
            "text": "Usually queries are employed to exert some kind of filter. The query builder supports lots of different  filters ,\nthat can be applied on entity attributes. By default chained filters are  and -combined.  DB.Todo.find()\n  .matches('name', /^My Todo/)\n  .equal('active', true)\n  .lessThanOrEqualTo('activities.start', new Date())\n  .resultList(...)  The above query searches for all todos, whose name starts with  'My Todo' , are currently active and contain an \nactivity in its activities list that has been started before the current date.  Note that all valid MongoDB attribute expressions can be used as a field name in a filter, in particular \npath-expressions such as 'activities.start'.  If you are familiar with  MongoDB queries , you can\nuse the  where  method to describe a query in MongoDB's JSON format. An equivalent query to the above one would look \nlike this:  DB.Todo.find()\n  .where({\n    \"name\": { \"$regex\": \"^My Todo\" },\n    \"active\": true,\n    \"activities.start\": { \"$lte\": { \"$date\": new Date().toISOString() }}\n  })\n  .resultList(...)  The following table list all available query filters and the types on which they can be applied:  \n   \n   \n     Filter method \n   \n     \n     \n      MongoDB equivalent\n     \n     Supported types \n     Notes \n   \n   \n   \n   \n     equal('name', 'My Todo') \n   \n   \n     $eq \n     All types \n     Complex types like embedded objects only match if their complete structure matches. \n   \n   \n     notEqual('name', 'My Todo') \n   \n     \n     $neq \n     All types \n     Complex types like embedded objects only match if their complete structure matches. \n   \n   \n     greaterThan('total', 3) \n   \n     \n     $gt \n     Numbers, Dates, Strings \n     gt()  is an alias \n   \n   \n     greaterThanOrEqualTo('total', 3) \n   \n     \n     $gte \n     Numbers, Dates, Strings \n     ge()  is an alias \n   \n   \n     lessThan('total', 3) \n     \n     \n     $lt \n     Numbers, Dates, Strings \n     lt()  is an alias \n   \n   \n     lessThanOrEqualTo('total', 3) \n   \n     \n     $lte \n     Numbers, Dates, Strings \n     le()  is an alias \n   \n   \n     between('total', 3, 5) \n   \n     \n     - \n     Numbers, Dates, Strings \n     It is equivalent to  gt('total', 3).lt('total', 5) \n   \n   \n     in('total', 3, 5[,...]) \n   \n     \n     $in \n     All types \n     \n        For primitive fields  any  of the given values have to match the field value.\n        On set and list fields  at least one  value must be contained in the collection in order for the \n        filter to match. \n     \n   \n   \n     notIn('total', 3, 5[,...]) \n   \n     \n     $nin \n     All types \n     \n      On primitive fields  none  of the given values must match the field value. \n      On set and list fields  none  of the given values must to be contained in the collection in order \n      for the filter to match.\n     \n   \n   \n     isNull('name') \n   \n     \n     - \n     All types \n     Checks if the field has no value; equivalent to  equal('name', null) \n   \n   \n     isNotNull('name') \n   \n     \n     $exists \n     All types \n     \n      Checks if the field has a value; equivalent to  where({'name': {\"$exists\" true, \"$ne\", null}) \n     \n   \n   \n     containsAny('activities', activity1, activity2 [,...]) \n   \n     \n     $in \n     List, Set, JsonArray \n     Checks if the collection contains any of the given elements \n   \n   \n     containsAll('activities', activity1, activity2 [,...]) \n   \n     \n     $all \n     List, Set, JsonArray \n     Checks if the collection contains all of the given elements \n   \n   \n     mod('total', 5, 3) \n   \n   \n     $mod \n     Number \n     The field value divided by divisor must be equal to the remainder \n   \n   \n     matches('name', /^My [eman]{4}/) \n   \n     \n     $regex \n     String \n     \n      The regular expression must be anchored (starting with  ^ ); ignore case and global flags are not\n      supported.\n     \n   \n   \n     size('activities', 3) \n   \n     \n     $size \n     List, Set, JsonArray \n     Matches if the collection has the specified size. \n   \n   \n     near('location', <geo point>, 1000) \n   \n     \n     $nearSphere \n     GeoPoint \n     \n      The geo point field has to be within the maximum distance in meters to the given GeoPoint.\n      Returns from nearest to furthest. \n      You need a Geospatial Index on this field, to use this kind of query. Read the query index section for more details.\n     \n   \n   \n     withinPolygon('location', <geo point list>) \n   \n     \n     $geoWithin \n     GeoPoint \n     \n      The geo point of the object has to be contained within the given polygon.\n      You need a Geospatial Index on this field, to use this kind of query. Read the [query indexes](../queries#query-indexes) section \n      for more details.\n     \n   \n     You can get the current GeoPoint of the User with  DB.GeoPoint.current() . This only works with an HTTPS connection.  References can and should be used in filters. Internally references are converted to ids\n and used for filtering. To get all Todos owned by the currently logged-in user, we can simply use the User instance \n in the query builder:  DB.Todo.find()\n  .equal('owner', DB.User.me) //any other User reference is also valid here\n  .resultList(...)  Note:   DB.user.me  refers to the currently logged-in User instance. To learn more about users and the\nlogin process see the  User, Roles and Permission chapter .",
            "title": "Filters"
        },
        {
            "location": "/topics/queries/#sorting",
            "text": "It is possible to sort the query result for one or more attributes. The query builder can be used to specify \nwhich attributes shall be used for sorting. Let's sort our query result by name:  DB.Todo.find()\n  .matches('name', /^My Todo/)\n  .ascending('name')\n  .resultList(...)  If you use more than one sort criterion, the order of the result reflects the order in which the sort methods were \ncalled. The following query will list all active tasks before the inactive ones and sort the tasks by their name in \nascending order.  DB.Todo.find()\n  .matches('name', /^My Todo/)\n  .ascending('name')\n  .descending('active')\n  .resultList(...)  When calling  descending('active')  before  ascending('name')  the result is sorted by name and \nthen by active flag, which is only relevant for multiple todos having the same name.   You can also set the sort criteria with the MongoDB  orderby  \nsyntax by using the  sort()  method. An equivalent expression to the above is this:  DB.Todo.find()\n  .matches('name', /^My Todo/)\n  .sort({\"name\": 1, \"active\": -1})\n  .resultList(...)",
            "title": "Sorting"
        },
        {
            "location": "/topics/queries/#offset-and-limit",
            "text": "On larger data sets you usually don't want to load everything at once. Its often reasonable to instead page through the \nquery results. It is therefore possible to skip objects and limit the result size.  var page = 3;\nvar resultsPerPage = 30;\n\nDB.Todo.find()\n  .matches('name', /^My Todo/)\n  .ascending('name')\n  .offset((page - 1) * resultsPerPage)\n  .limit(resultsPerPage)\n  .resultList(...)  Note:  An offset query on large result sets yields [poor query performance](http://use-the-index-luke\n.com/sql/partial-results/fetch-next-page). Instead, consider using a filter and sort criteria to navigate through \nresults.  For instance if you implement a simple pagination, you can sort by id and can get the data of the next\npage by a simple greaterThen filter. As the id always has an index this results in good performance regardless of the\n query result size.  var pageId = '00000-...';\nvar resultsPerPage = 30;\n\nDB.Todo.find()\n  .matches('name', /^My Todo/)\n  .greaterThan('id', pageId)\n  .ascending('id', pageId)\n  .limit(resultsPerPage)\n  .resultList(function(result) {\n    pageId = result[result.length - 1];  \n  })  But often you want to sort your result by another attribute (e.g.  createdAt ). When you sort by an attribute which \nby itself is not unique you must combine it with a unique attribute (e.g.  id ).   //initialize default values\nvar resultsPerPage = 30;\nvar lastObject = {id: '', createdAt: new Date(0)};\n\n//later page through the pages by the following query\nvar qb = DB.Todo.find(); \nqb.or(qb.equal('createdAt', lastObject.createdAt).greaterThan('id', lastObject.id), qb.greaterThan('createdAt', lastObject.createdAt))\n     .ascending('createdAt')\n     .ascending('id')\n     .limit(resultsPerPage)\n     .resultList(function(result) {\n        //track last seen object\n        lastObject = result[result.length - 1]; \n        console.log(result);\n      });  Explanation:  By combining the results of the query which fetches all remaining entities where the  createdAt  is equal to our last seen  createdAt  \nplus all ids which are greater than the last seen  id  we make our result unique when  createdAt  has the same value on \nmultiple entities. That guarantees a unique order for none unique attributes.",
            "title": "Offset and Limit"
        },
        {
            "location": "/topics/queries/#composing-filters-by-and-or-and-nor",
            "text": "Filters are joined with  and  by default. In more complex cases you may want to formulate a query with one or more  and ,  or  or  nor   expressions. \nFor such cases the initial  find()  call returns a  Query.Builder  instance. The builder provides\nadditional methods to compose filter expressions.  The following query finds all todos which the logged-in user is not currently working on and all todos which aren't \ndone yet:  var queryBuilder = DB.Todo.find();\nvar condition1 = queryBuilder\n  .matches('name', /^My Todo/)\n  .equal('active', false);\n\nvar condition2 = queryBuilder\n  .matches('name', /^Your Todo/)\n  .equal('done', false);\n\nqueryBuilder.or(condition1, condition2)\n  .ascending('name')\n  .resultList(...)",
            "title": "Composing Filters by and, or and nor"
        },
        {
            "location": "/topics/queries/#query-indexes",
            "text": "Indexes on fields that are frequently queried can massively impact the overall query performance. Therefore our Dashboard\nprovides a very comfortable way to create custom indexes on fields. It is always an tradeof on which fields you should \ncreate an index. A good index should be created on fields that contains many distinct values. But to many indexes on the \nsame class can also reduce the write throughput. If you like to read more about indexes we currently use, visit the mongo indexes docs .  To create an Index open the schema view of the class and use the  Index  or  Unique Index  button to create an index. \nCurrently we support three types of indexes:   Index:  A simple index which contains a single field used to improve querys which filters the specified field.   Unique Index:  A index that requires uniqueness of the field values. Inserting or updating objects that violates the \n unique constraint will be rejected with an ObjectExists error.  Geospatial Index:  This index can be created on GeoPoint fields and is required for  near  and  withinPolygon  query\nfilters. This Index is created on GeoPoint fields by using the  Index  Button.",
            "title": "Query Indexes"
        },
        {
            "location": "/topics/realtime/",
            "text": "Real-Time Queries\n\n\nPrivate Beta:\n \nBaqend Real-Time Queries are currently not public. If you want to try our real-time features, just \ndrop us a line and we will happily \nenable it for your app\n.\n\n\n\n\nBaqend does not only feature powerful queries, but also real-time mechanisms that \nkeep query results up-to-date\n while the underlying database is under constant change. Baqend Real-Time Queries come in two flavors:\n\n\n\n\nSelf-maintaining queries\n (\n.resultStream()\n): You'll get the complete (updated) result whenever it changes.\n\n\nEvent stream queries\n (\n.eventStream()\n): You'll receive an event message for every database write that affects your query.\n\n\n\n\nCalling \n.eventStream()\n or \n.resultStream()\n on a query object opens a \nwebsocket\n connection to Baqend, registers a real-time query and returns an \nRxJS observable\n. This observable provides you with an instant update to your query whenever a relevant change occurs.  \n\n\nThe following sections describe both real-time query types in detail.\n\n\nReal-Time SDK:\n \nTo use real-time features, you have to include the \nBaqend Real-Time SDK\n.\n\n\n\n\nSelf-Maintaining Queries\n\n\nBaqend Self-Maintaining Queries behave \nexactly like regular queries\n, but with one important distinction: They \nupdate themselves\n and thus never become stale. You will receive both the current result once upfront and the updated result whenever a regular query would return a different result than before.\n\n\nAll you have to do is use \nresult\nStream\n()\n instead of \nresult\nList\n()\n for your queries. \n\n\nGoing Real-Time: \nresult\nList\n()\n vs. \nresult\nStream\n()\n\n\nTo shed more light on the difference between regular and real-time queries, consider the following example: Imagine you and your colleagues are collaborating on a shared todo list that is frequently updated. And let's say you want to keep an eye on the 10 most urgent open tasks by the following query:\n\n\nvar query = DB.Todo.find()\n              .matches('name', /^My Todo/)\n              .ascending(status)\n              .ascending('deadline')\n              .limit(10);\n\n\n\n\nWith a regular query that does not update itself (\nresult\nList\n()\n), you would have to evaluate the query again and again to make sure you don't miss any updates:\n\n\n//Maintaining a result with purely pull-based queries is tedious:\nquery.resultList(result => console.log(result));\n//...\n//Did something change?\nquery.resultList(result => console.log(result));\n//...\n//Let's check again...\nquery.resultList(result => console.log(result));\n//...\n//Don't do this! Use real-time queries instead!\n\n\n\n\nThis pattern is obviously inefficient and introduces staleness to your critical data. Using a self-maintaining query, on the other hand, there is \nno need to actively refresh the result\n. You simply replace \nresult\nList\n()\n by \nresult\nStream\n()\n and \u2014 that's it: \n\n\n// will print the result once upfront and whenever it changes:\nquery.resultStream(result => console.log(result));\n\n\n\n\nWith the above code, the top-10 list is not only printed to console once (as it would be with a regular query), but every time \u2014 and \nimmediately\n \u2014 when a task enters the top-10, is updated within the top-10 or leaves the top-10. \n\n\nObservables and Subscriptions\n\n\nTo harness the expressiveness of real-time queries, the Baqend client SDK uses the \nobserver pattern\n. This section explains the basic concepts in the context of Baqend Real-Time Queries. For a more generic approach, have a look at other resources such as the \nRxJS manual\n.\n\n\nEvery real-time query produces a \nstream\n (i.e. a sequence of query updates) that is represented by an abstraction called \nobservable\n. An observable maintains a list of so-called \nobservers\n, each of which is a collection of callback functions. Whenever new data becomes available in the stream, the observable notifies each observer, so that they can apply their callback functions to the new data. To add a new observer to an observable, one has to create a \nsubscription\n. This subscription can be canceled (\nunsubscribed\n) to remove its respective observer from the observable. \n\n\nIn a nutshell, you have to subscribe to an observable and provide a few callback functions in order to define application behavior. In particular, you can define the following three callback functions for a real-time query:\n\n\n\n\nnext\n: \nWhat to do when an update arrives in the stream?\n\nFor self-maintaining queries, this callback function receives the complete updated query result. For \nevent stream queries\n, it receives individual change events.\n\n\nerror\n (optional): \nWhat to do when there is an error?\n\nThis callback receives a server-side error, for example when you issue a real-time query with insufficient access rights. \n\n\ncomplete\n (optional): \nWhat to do when the network connection is closed?\n\n\nSelf-maintaining queries\n will transparently reconnect by default (see \nreconnect\n option), so this handler can usually be ignored for them. \nEvent stream queries\n, on the other hand, do not support automatic reconnects: They will just silently stop working when disconnected, unless a \ncomplete\n function is provided.\n\n\n\n\nNote:\n \nOn an \nerror\n or \ncomplete\n event, the corresponding subscription will automatically be \ncanceled\n. \n\n\n\n\nThe simplest way to create a subscription is to just provide the \nnext\n handler as an argument to \n.resultStream()\n as illustrated in the last section. As a return value, you get the \nsubscription\n object that you can use to unsubscribe later:\n\n\n// start:\nvar subscription = query.resultStream(result => console.log(result)); \n// ...\n// stop:\nsubscription.unsubscribe(); \n\n\n\n\nBut you can, of course, provide all three handlers in the same fashion:\n\n\nvar onNext = result => console.log(result);\nvar onError = err => console.log(err); // optional\nvar onComplete = () => console.log('I am offline!'); // optional\n\nvar subscription = query.resultStream(onNext, onError, onComplete);\n\n\n\n\nThe above code is equivalent to first creating an observable and then subscribing to it:\n\n\nvar stream = query.resultStream(); // observable\nvar subscription = stream.subscribe(onNext, onError, onComplete); \n\n\n\n\nHowever, if you first create a \nstream\n observable, you can create multiple subscriptions on top of it:\n\n\n// one single observable:\nvar stream = query.resultStream(); \n\n// Multiple subscriptions on the same observable:\nvar subscription = stream.subscribe(onNext);\nvar otherSubscription = stream.subscribe(otherOnNext);\n\n\n\n\nError Handling\n\n\nOn error, your subscription will automatically be canceled, but you can provide a custom error handler function that is executed whenever something goes wrong:\n\n\nvar onNext = event => console.log(event);\nvar onError = error => console.log(error);\nvar subscription = stream.subscribe(onNext, onError);\n//...\n// A serverside error produces the following output:\n//\n// {\n//   \"id\":\"919ed4a1-9492-497c-af38-8c1aed29bb27\",\n//   \"reason\":\"Query Not Supported\",\n//   \"message\":\"Offset + limit may not exceed 500, but offset already was 500.\"\n// }\n\n\n\n\nEvery error event has the following attributes:\n\n\n\n\nid\n: the subscription ID\n\n\nreason\n: the name of the problem\n\n\nmessage:\n a more elaborate problem description that should point you towards the problem.\n\n\n\n\nOptions\n\n\nBy design, self-maintaining queries are straightforward to use and do not require you to configure anything. However, you can customize behavior by providing an \noptions\n argument as first parameter to the \nresultStream\n function.\n\nCurrently, there is only one parameter:\n\n\n\n\nreconnect\n (default: \n-1\n): determines how often the self-maintaining query is resubscribed after connection loss (negative values indicating infinite retries).\n\nBy default, a self-maintaining query will be resubscribed and the full initial result will be delivered again whenever the websocket connection drops. Since the full query result (and not just changed objects) is transmitted on subscription, \nreconnecting can impose significant communication overhead\n for large result sets. To shield against this kind of performance leak, you can specify a non-negative integer to override this behavior. In this case, you should also provide a \ncomplete\n handler which is going to be called after the number of reconnect tries has been exhausted.\n\n\n\n\nEvent Stream Queries\n\n\nCalling \n.eventStream()\n on a query object creates an observable that encapsulates all data modifications relevant to your query. But in contrast to a self-maintaining query, an event stream query will not give you a full-blown result on every change, but instead an event notification describing what exactly happened.  \n\n\nNote:\n \nIf you haven't already, you should read the guide section on \nobservables and subscriptions\n as an introduction on how to work with Baqend's real-time API.\n\n\n\n\nYou can create an event stream observable like this:\n\n\nvar query = DB.Todo.find().matches('name', /^My Todo/);\nvar stream = query.eventStream(); // observable\n\n\n\n\nTo make your code react to result changes, you can subscribe to the observable and provide a function that is called for every incoming change event:\n\n\nvar subscription = stream.subscribe(event => console.log(event));\n\n\n\n\nAs with self-maintaining queries, you can also provide functions to handle errors and connection problems:\n\n\nvar onNext = event => console.log(event);\nvar onError = err => console.log(err); // optional\nvar onComplete = () => console.log('I am offline!'); // optional\n\nvar subscription = stream.subscribe(onNext, onError, onComplete);\n\n\n\n\nAnd of course, you can also skip creating the observable and directly subscribe to an event streaming query:\n\n\nvar subscription = query.eventStream(onNext, onError, onComplete);\n\n\n\n\nTo cancel your subscription and thus stop receiving events from an event stream query, just unsubscribe:\n\n\nsubscription.unsubscribe();\n\n\n\n\nIn order to activate event stream updates for a query, all you have to do is register it as an event stream query and provide a function to execute for every received change event:\n\n\nvar query = DB.Todo.find()\n              .matches('name', /^My Todo/)\n              .ascending('deadline')\n              .limit(20);\nvar subscription = query.eventStream()\n              .subscribe(event => console.log(event));\n//...\nnew DB.Todo({name: 'My Todo XYZ'}).insert(); // insert data\n//...\n// The insert produces the following event:\n//{\n//  \"matchType\":\"add\",\n//  \"operation\":\"insert\",\n//  \"data\":{\"name\":\"do groceries\",...},\n//  \"date\":\"2016-11-09T12:42:31.322Z\"\n//  \"initial\":true,\n//  \"index\":1\n//}\n\n\n\n\nOnce subscribed to a stream, you will get an event for every database entity in the initial result set (i.e. every entity matching at subscription time) and for every entity that enters the result set, leaves the result set or is updated while in the result set.\n\n\nEvery event can carry the following information:\n\n\n\n\nid\n: the subscription ID\n\n\ndate\n: server-time from the instant at which the event was generated.\n\n\ninitial:\n a boolean value indicating whether this event reflects the matching status at query time (\ntrue\n) or a recent change data change (\nfalse\n).\n\n\nindex\n (for sorting queries only): the position of the matching entity in the ordered result (\nundefined\n for non-matching entities).\n\n\ndata:\n the database entity this event was generated for, e.g. an entity that just entered or left the result set. (For self-maintaining queries, this attribute carries the updated result.)\n\n\nmatchType:\n indicates how the transmitted entity relates to the query result.\nEvery event is delivered with one of the following match types:\n\n\n'add'\n: the entity entered the result set, i.e. it did not match before and is matching now.\n\n\n'change'\n: the entity was updated, but remains a match.\n\n\n'changeIndex'\n (for sorting queries only): the entity was updated and remains a match, but changed its position within the query result.\n\n\n'remove'\n: the entity was a match before, but is not matching any longer.\n\n\n'match'\n: the entity matches the query (subsumes \n'add'\n, \n'change'\n and \n'changeIndex'\n). You will only receive this match type, if you explicitly request it.\n\n\n\n\n\n\noperation:\n the operation by which the entity was altered (\n'insert'\n, \n'update'\n or \n'delete'\n; \n'none'\n if unknown or not applicable).\n\nFor an example where neither \n'insert'\n, \n'update'\n nor \n'delete'\n can reasonably be applied to an event, consider how the last one in a top-10 query result is pushed out when a new contender enters the top-10: While one event represents the insertion of the new contender itself, another event represents the entity leaving the result which was neither inserted, updated nor deleted. Consequently, Baqend would deliver this event with a \n'none'\n operation.\n\n\n\n\nOptions\n\n\nBy default, you receive the initial result set and all events that are required to maintain it. However, the optional argument for the \n.eventStream([options])\n function lets you restrict the kind of event notifications to receive by setting the appropriate attribute values:\n\n\n\n\ninitial\n (default: \ntrue\n): whether or not you want to receive the initial result set. If set to \ntrue\n, every entity matching the query at subscription time will be delivered with match type \nadd\n, irrespective of whether and which restrictions you impose on operations and match types (see the other options). If set to \nfalse\n, you will only receive an event when something changes.\n\n\nmatchTypes\n (default: \n['all']\n): The default gives you all events with the most specific match type (\n'add'\n, \n'change'\n, \n'changeIndex'\n or \n'remove'\n). If you are only interested in a specific subset of match types, you can specify any combination of them to listen for.\nIf you do not care about the difference between new and updated items, you can also use match type \n'match'\n. This will yield the same events as the combination of \n'add'\n, \n'change'\n and \n'changeIndex'\n, but the match type of the received events will always be \n'match'\n.\n\n\noperations\n (default: \n['any']\n): By default, events will not be sorted out based on their operation, but you can choose any combination of \n'insert'\n, \n'update'\n, \n'delete'\n and \n'none'\n to narrow down the kind of matches you receive. \n\n\n\n\nNote:\n \nYou can only restrict the event stream by \neither match type or operation\n, but not both.\n\n\n\n\nComplex semantics:\n \nFiltering events by \noperation\n does not work as straightforward as you might think at first glance. So before using this feature, be sure to read the parameter description above and the \nexample\n below.\n\n\n\n\nEvent Stream Simple Queries\n\n\nSimple queries\n are queries that just return all entities in a collection, no filtering involved. While event stream simple queries can be very useful (for example to monitor all operations on the collection), they can produce vast amounts of events for collections that have many members or are updated very often. Therefore, you should be \nparticularly\n careful to only subscribe to events you really want to be bothered with when using event stream simple queries.\n\n\nFor instance, if you are interested in all todo lists and only want to be notified as \nnew\n lists are created, you could subscribe to the following stream:\n\n\nvar stream = DB.Todo.find().eventStream({operations: 'insert'});// initial result is delivered by default\n\n\n\n\nIf, on the other hand, you only care for the creation of new todo lists and not for the ones that are already in the database, you should not request the initial result set:\n\n\nvar stream = DB.Todo.find().eventStream({initial: false, operations: 'insert'});\n\n\n\n\nEvent Stream Filter Queries\n\n\nLike regular filter queries, \nevent stream filter queries\n allow you to select entities based on their attribute values by applying \nfilters\n.\n\n\nYou can, for instance, have the database send you an event for every todo list that is \ncreated\n with a name that matches a particular pattern:\n\n\nvar stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .eventStream({initial: false, operations: 'insert'});\n\n\n\n\nIt is important to note, however, that the above query will only tell you when a new todo list matches your query \non insert\n; it will \nnot\n produce an event when an already-existing list is renamed to match your pattern, because that would happen by \nupdate\n (while the stream is targeting \ninsert\n operations only).\n\n\nIf you are really looking for an event stream query that gives you new matches irrespective of the triggering operation, you should work with \nmatchTypes\n and leave \noperations\n at the default:\n\n\nvar stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .eventStream({initial: false, matchTypes: 'add'});// operations: ['any'] by default\n\n\n\n\nTo get the full picture, you can also request the initial result upfront. Initial matches are always delivered with match type \nadd\n:\n\n\nvar stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .eventStream({matchTypes: 'add'});// initial: true by default\n\n\n\n\nOf course, you can combine several predicates using \nand\n, \nor\n and \nnor\n. The following query keeps you up-to-date on all todo lists that are active and match one pattern or have already been marked as done and match another pattern:\n\n\nvar queryBuilder = DB.Todo.find();\nvar condition1 = queryBuilder\n  .matches('name', /^My Todo/)\n  .equal('active', true);\n\nvar condition2 = queryBuilder\n  .matches('name', /^Your Todo/)\n  .equal('done', true);\n\nvar stream = queryBuilder\n               .or(condition1, condition2)\n               .eventStream();\n\n\n\n\nEvent Stream Sorting Queries\n\n\nAll features described so far are also available for \nevent stream sorting queries\n, i.e. queries that contain \nlimit\n, \noffset\n, \nascending\n, \ndescending\n or \nsort\n.\nEvents stream sorting queries are great to maintain ordered results such as high-score rankings or prioritized todo lists.\n\n\nThe following generates events for your top-20 todo lists, sorted by urgency, name and status:\n\n\nvar stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .ascending('name')\n               .descending('active')\n               .limit(20)\n               .eventStream();\n\n\n\n\nEntities that sort identically are \nimplicitly ordered by ID\n. Thus, a query without explicit ordering will result in more or less random order by default as IDs are generated randomly:\n\n\nvar stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .limit(20)// no order provided? Implicitly ordered by ID!\n               .eventStream();\n\n\n\n\nThe \nlimit\n clause is optional\n and a query without limit will be registered with the maximum permitted limit: \noffset + limit <= 500\n must always hold. In other words, \nlimit\n can never assume values greater than \n500 - offset\n. Correspondingly, queries with an \noffset\n of more than 499 are illegal.\n\nSince the maximum limit is implicitly enforced, the following three event stream queries are registered identical:\n\n\nvar implicitLimit = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .offset(5)\n               .eventStream(); // implicit limit: 495 (= 500 - offset)\n\nvar explicitLimit = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .offset(5)\n               .limit(495) // explicit limit\n               .eventStream();\n\nvar cappedLimit = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .offset(5)\n               .limit(500) // limit is capped to 495, so that offset + limit <= 500\n               .eventStream();\n\n\n\n\nAn event stream sorting query with \noffset\n maintains an ordered result, hiding the first few items from you. However, the first index in a sorted query result is always \n0\n, irrespective of whether it is specified with \noffset\n or not. Accordingly, events for the following subscription will carry \nindex\n values in the range between \n0\n and \n9\n:\n\n\nvar stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .ascending('name')\n               .descending('active')\n               .offset(5)// skip the first 5 items\n               .limit(10)// only return the first 10 items\n               .eventStream();\n\n\n\n\nWith respect to efficiency, the same rules apply to event stream and regular (i.e. non-streaming) queries: Enforcing order on huge results is expensive and sorting queries should therefore be avoided when filter queries would do as well.\n\n\nNote:\n Currently, event stream sorting queries are \nalways executed as anonymous queries\n, i.e. they will only give you data that is publicly visible. To retrieve data protected by object ACLs, you have to either forgo real-time (use a plain sorting query) or ordering (use a real-time query without \nlimit\n, \noffset\n, \nascending\n and \ndescending\n).\n\n\n\n\nExample: Subscription and Events\n\n\nFor an example of how an event stream query behaves, consider the following example where two users are working concurrently on the same database. \nUser 1\n subscribes to an event stream sorting query and listens for the result and updates, whereas \nUser 2\n is working on the data.\n\n\nTimestamp 0:\n \nUser 1\n and \nUser 2\n are connected to the same database.\n\n\nTimestamp 1:\n \nUser 2\n inserts \ntodo1\n:\n\n\nvar todo1 = new DB.Todo({name: 'My Todo 1'});\ntodo1.insert();\n\n//actual result: [ todo1 ]\n\n\n\n\nTimestamp 2:\n \nUser 1\n subscribes to an event stream query and immediately receives a match event for \ntodo1\n:\n\n\nvar stream = DB.Todo.find()\n    .matches('name', /^My Todo/)\n    .ascending('name')\n    .descending('active')\n    .limit(3)\n    .eventStream();\nsubscription = stream.subscribe((event) => {\n  console.log(event.matchType + '/'\n    + event.operation + ': '\n    + event.data.name + ' is now at index '\n    + event.index);\n});\n// ... one round-trip later\n//'add/none: My Todo 1 is now at index 0'\n\n\n\n\nTimestamp 3:\n \nUser 2\n inserts \ntodo2\n:\n\n\nvar todo2 = new DB.Todo({name: 'My Todo 2'});\ntodo2.insert();\n\n//actual result: [ todo1, todo2 ]\n\n\n\n\nTimestamp 4:\n \nUser 1\n receives a new event for \ntodo2\n:\n\n\n//'add/insert: My Todo 2 is now at index 1'\n\n\n\n\nTimestamp 5:\n \nUser 2\n: inserts \ntodo3\n:\n\n\nvar todo3 = new DB.Todo({name: 'My Todo 3'});\ntodo3.insert();\n\n//actual result: [ todo1, todo2, todo3 ]\n\n\n\n\nTimestamp 6:\n \nUser 1\n receives a new event for \ntodo3\n:\n\n\n//'add/insert: My Todo 3 is now at index 2'\n\n\n\n\nTimestamp 7:\n \nUser 2\n updates \ntodo3\n in such a way that its position in the ordered result changes:\n\n\ntodo3.name = 'My Todo 1b (former 3)';\ntodo3.update();\n\n//actual result: [ todo1, todo3, todo2 ]\n\n\n\n\nTimestamp 8:\n \nUser 1\n is notified of this update through an event that delivers the new version of \ntodo3\n. The fact that \ntodo3\n had already been a match and just changed its position in the result is encoded in the event's match type \nchangeIndex\n:\n\n\n//'changeIndex/update: My Todo 1b (former 3) is now at index 1'\n\n\n\n\nTimestamp 9:\n \nUser 2\n inserts \ntodo0\n which sorts before all other items in the result and therefore is assigned index \n0\n:\n\n\nvar todo0 = new DB.Todo({name: 'My Todo 0'});\ntodo0.insert();\n\n//entities in DB: [ todo0, todo1, todo3 ], todo2\n//                 <--- within limit --->\n\n\n\n\nBecause of the \n.limit(3)\n clause, only the first three of all four matching entities are valid matches and the last one \u2014 currently \ntodo2\n \u2014 is \npushed beyond limit\n and therefore leaves the result.\n\n\nTimestamp 10:\n \nUser 1\n receives two events that correspond to the two relevant changes to the result:\n\n\n//'remove/none: My Todo 2 is now at index undefined'\n//'add/insert: My Todo 0 is now at index 0'\n\n\n\n\nTimestamp 11:\n \nUser 2\n updates \ntodo3\n again, so that it assumes its original name:\n\n\ntodo3.name = 'My Todo 3';\ntodo3.update();\n\n//entities in DB: [ todo0, todo1, todo2 ], todo3\n//                 <--- within limit --->\n\n\n\n\nThrough this update, \ntodo2\n and \ntodo3\n swap places.\n\n\nTimestamp 12:\n \nUser 1\n receives the corresponding events:\n\n\n//'remove/update: My Todo 3 is now at index undefined'\n//'add/none: My Todo 2 is now at index 2'\n\n\n\n\nTimestamp 13:\n \nUser 2\n deletes \ntodo3\n:\n\n\ntodo3.delete();\n\n//entities in DB: [ todo0, todo1, todo2 ]\n\n\n\n\nNote that the deleted entity was not part of the result set.\n\n\nTimestamp 14:\n \nUser 1\n no match, because deleting \ntodo3\n had no effect on the query result.\n\n\n//nothing happened\n\n\n\n\nUser 1 starts receiving the initial result directly after subscription (Timestamp 2). From this point on, any write operation performed by User 2 is forwarded to User 1 \u2014 as long as it's affecting the subscribed query's result. Changes to non-matching items have no effect in the eyes of User 1 (Timestamps 13/14).\n\n\nBe aware that operation-related semantics are rather complex for sorting queries: For example, \ninsert\n and \nupdate\n operations may trigger an item to \nleave\n the result (Timestamps 9/10 and 11/12). Similarly (even though not shown in the example), an \nadd\n event can be triggered by a \ndelete\n when an item enters the result set from beyond limit. When triggered by an operation on a different entity, an event may even be delivered with no operation at all (Timestamps 10 and 12).\n\n\nTip:\n\nBottom line, be careful when filtering the event stream of a sorted query by operation!\n\n\n\n\nAdvanced Features: RxJS\n\n\nThe Baqend Real-Time SDK is shipped with \nbasic support for ES7 Observables\n, so that you can use it without requiring external dependencies.\nTo leverage the full potential of Baqend's real-time query engine, though, we recommend using it in combination with the feature-rich RxJS client library.\n\n\nIn the following, we give you some references and a few examples of what you can do with RxJS and Baqend Real-Time Queries.\n\n\nRxJS: The ReactiveX JavaScript Client Library\n\n\nSince the \nRxJS documentation is great and extensive\n, we do not go into detail on our client library, but rather provide a few references to get you started:\n\n\n\n\nWhat is ReactiveX?\n\n\nWhat is an observable?\n\n\nOperators: What can I do with an observable?\n\n\nWhich operator do I need for ...?\n\n\n\n\nReal-Time Aggregations\n\n\nAnother neat use case for event stream queries is to compute and maintain aggregates in real-time.\nSimilar to result set maintenance, the basic idea is to keep all relevant information in an \naccumulator\n and to recompute and output the updated aggregate value whenever an event is received.\n\n\nCount\n\n\nOne of the simpler aggregates over a collection of entities is the \ncardinality\n or \ncount\n, i.e. the number of entities in the collection. The following code will compute and maintain the cardinality of the query result:\n\n\nvar maintainCardinality = (counter, event) => {\n  if (event.matchType === 'add') {// entering item: count + 1\n    counter++;\n  } else if (event.matchType === 'remove') {// leaving item: count - 1\n    counter--;\n  }\n  return counter;\n};\n\nvar subscription = stream.scan(maintainCardinality, 0)// update counter\n                     .subscribe(value => console.log(value));// output counter\n\n\n\n\nThe current number of entities in the result set will be printed to the console whenever a change occurs.\n\n\nTip:\n\nCount maintenance is a good example where it makes sense to not subscribe to the default match types (\n['all']\n), because you are actually only interested in \nadd\n and \nremove\n events: To restrict the events you will receive to those that really matter, register the event stream query with \n.eventStream({matchTypes: ['add', 'remove']})\n.\n\n\n\n\nAverage\n\n\nNow to a more complex example: Let's say you are interested in the \naverage number of activities\n of each of the todo lists matching your query.\n\n\nvar initialAccumulator = {\n  contributors: {},// individual activity counts go here\n  count: 0,// result set cardinality\n  sum: 0,// overall number of activities in the result\n  average: 0// computed as: sum/count\n};\n\n\n\n\nThe accumulator is not just an integer, but an object with several values: For maximum precision, we maintain the overall number of activities (\nsum\n) and result cardinality (\ncount\n) separately and compute the \naverage\n fresh on every event. We remember the number of activities for every individual entity in a map (\ncontributors\n); this is necessary, because otherwise we would not have a clue by how much to decrement \nsum\n when an entity is updated or leaves the result set.\n\n\nvar maintainAverage = (accumulator, event) => {\n  var newValue = event.matchType === 'remove' ? 0 : event.data.activities.length;\n  var oldValue = accumulator.contributors[event.data.id] || 0;//default: 0\n\n  if (newValue !== 0) {// remember new value\n    accumulator.contributors[event.data.id] = newValue;\n  } else {// forget old value\n    delete accumulator.contributors[event.data.id];\n  }\n  accumulator.sum += newValue - oldValue;\n  accumulator.count += event.matchType === 'remove' ? -1 : event.matchType === 'add' ? 1 : 0;\n  accumulator.average = accumulator.count > 0 ? accumulator.sum / accumulator.count : 0;\n  return accumulator;\n};\n\n\n\n\nThe maintenance function extracts the current number of activities (\nnewValue\n) from the incoming event and the former value (\noldValue\n) from the \ncontributors\n map in the accumulator. Depending on whether the incoming entity contributes to the average or not, it either stores the new value in the map or removes the old value. Finally, \nsum\n and \ncount\n are updated and the average is computed and stored as \naccumulator.average\n.\n\n\nSince we are only interested in the average value, we add another step to extract it from the accumulator via the \nmap\n operator:\n\n\nvar subscription = stream.scan(maintainAverage, initialAccumulator)//update counter\n                           .map(accumulator => accumulator.average)//extract average\n                           .subscribe(value => console.log(value));//output counter\n\n\n\n\nLimitations\n\n\nThe real-time feature is available for all queries with the following limitations:\n\n\n\n\nCurrently, \nreal-time sorting queries only return public data\n, even when executed with admin privileges; to retrieve private data, use regular (i.e. non-streaming) sorting queries or real-time queries that do not contain \nlimit\n, \noffset\n, \nascending\n, \ndescending\n or \nsort\n.\n\n\nGeospatial queries (\nwithinSphere\n, \nwithinPolygon\n) are currently not available for real-time",
            "title": "Real-Time Queries"
        },
        {
            "location": "/topics/realtime/#real-time-queries",
            "text": "Private Beta:  \nBaqend Real-Time Queries are currently not public. If you want to try our real-time features, just  drop us a line and we will happily  enable it for your app .  Baqend does not only feature powerful queries, but also real-time mechanisms that  keep query results up-to-date  while the underlying database is under constant change. Baqend Real-Time Queries come in two flavors:   Self-maintaining queries  ( .resultStream() ): You'll get the complete (updated) result whenever it changes.  Event stream queries  ( .eventStream() ): You'll receive an event message for every database write that affects your query.   Calling  .eventStream()  or  .resultStream()  on a query object opens a  websocket  connection to Baqend, registers a real-time query and returns an  RxJS observable . This observable provides you with an instant update to your query whenever a relevant change occurs.    The following sections describe both real-time query types in detail.  Real-Time SDK:  \nTo use real-time features, you have to include the  Baqend Real-Time SDK .",
            "title": "Real-Time Queries"
        },
        {
            "location": "/topics/realtime/#self-maintaining-queries",
            "text": "Baqend Self-Maintaining Queries behave  exactly like regular queries , but with one important distinction: They  update themselves  and thus never become stale. You will receive both the current result once upfront and the updated result whenever a regular query would return a different result than before.  All you have to do is use  result Stream ()  instead of  result List ()  for your queries.",
            "title": "Self-Maintaining Queries"
        },
        {
            "location": "/topics/realtime/#going-real-time-resultlist-vs-resultstream",
            "text": "To shed more light on the difference between regular and real-time queries, consider the following example: Imagine you and your colleagues are collaborating on a shared todo list that is frequently updated. And let's say you want to keep an eye on the 10 most urgent open tasks by the following query:  var query = DB.Todo.find()\n              .matches('name', /^My Todo/)\n              .ascending(status)\n              .ascending('deadline')\n              .limit(10);  With a regular query that does not update itself ( result List () ), you would have to evaluate the query again and again to make sure you don't miss any updates:  //Maintaining a result with purely pull-based queries is tedious:\nquery.resultList(result => console.log(result));\n//...\n//Did something change?\nquery.resultList(result => console.log(result));\n//...\n//Let's check again...\nquery.resultList(result => console.log(result));\n//...\n//Don't do this! Use real-time queries instead!  This pattern is obviously inefficient and introduces staleness to your critical data. Using a self-maintaining query, on the other hand, there is  no need to actively refresh the result . You simply replace  result List ()  by  result Stream ()  and \u2014 that's it:   // will print the result once upfront and whenever it changes:\nquery.resultStream(result => console.log(result));  With the above code, the top-10 list is not only printed to console once (as it would be with a regular query), but every time \u2014 and  immediately  \u2014 when a task enters the top-10, is updated within the top-10 or leaves the top-10.",
            "title": "Going Real-Time: resultList() vs. resultStream()"
        },
        {
            "location": "/topics/realtime/#observables-and-subscriptions",
            "text": "To harness the expressiveness of real-time queries, the Baqend client SDK uses the  observer pattern . This section explains the basic concepts in the context of Baqend Real-Time Queries. For a more generic approach, have a look at other resources such as the  RxJS manual .  Every real-time query produces a  stream  (i.e. a sequence of query updates) that is represented by an abstraction called  observable . An observable maintains a list of so-called  observers , each of which is a collection of callback functions. Whenever new data becomes available in the stream, the observable notifies each observer, so that they can apply their callback functions to the new data. To add a new observer to an observable, one has to create a  subscription . This subscription can be canceled ( unsubscribed ) to remove its respective observer from the observable.   In a nutshell, you have to subscribe to an observable and provide a few callback functions in order to define application behavior. In particular, you can define the following three callback functions for a real-time query:   next :  What to do when an update arrives in the stream? \nFor self-maintaining queries, this callback function receives the complete updated query result. For  event stream queries , it receives individual change events.  error  (optional):  What to do when there is an error? \nThis callback receives a server-side error, for example when you issue a real-time query with insufficient access rights.   complete  (optional):  What to do when the network connection is closed?  Self-maintaining queries  will transparently reconnect by default (see  reconnect  option), so this handler can usually be ignored for them.  Event stream queries , on the other hand, do not support automatic reconnects: They will just silently stop working when disconnected, unless a  complete  function is provided.   Note:  \nOn an  error  or  complete  event, the corresponding subscription will automatically be  canceled .   The simplest way to create a subscription is to just provide the  next  handler as an argument to  .resultStream()  as illustrated in the last section. As a return value, you get the  subscription  object that you can use to unsubscribe later:  // start:\nvar subscription = query.resultStream(result => console.log(result)); \n// ...\n// stop:\nsubscription.unsubscribe();   But you can, of course, provide all three handlers in the same fashion:  var onNext = result => console.log(result);\nvar onError = err => console.log(err); // optional\nvar onComplete = () => console.log('I am offline!'); // optional\n\nvar subscription = query.resultStream(onNext, onError, onComplete);  The above code is equivalent to first creating an observable and then subscribing to it:  var stream = query.resultStream(); // observable\nvar subscription = stream.subscribe(onNext, onError, onComplete);   However, if you first create a  stream  observable, you can create multiple subscriptions on top of it:  // one single observable:\nvar stream = query.resultStream(); \n\n// Multiple subscriptions on the same observable:\nvar subscription = stream.subscribe(onNext);\nvar otherSubscription = stream.subscribe(otherOnNext);",
            "title": "Observables and Subscriptions"
        },
        {
            "location": "/topics/realtime/#error-handling",
            "text": "On error, your subscription will automatically be canceled, but you can provide a custom error handler function that is executed whenever something goes wrong:  var onNext = event => console.log(event);\nvar onError = error => console.log(error);\nvar subscription = stream.subscribe(onNext, onError);\n//...\n// A serverside error produces the following output:\n//\n// {\n//   \"id\":\"919ed4a1-9492-497c-af38-8c1aed29bb27\",\n//   \"reason\":\"Query Not Supported\",\n//   \"message\":\"Offset + limit may not exceed 500, but offset already was 500.\"\n// }  Every error event has the following attributes:   id : the subscription ID  reason : the name of the problem  message:  a more elaborate problem description that should point you towards the problem.",
            "title": "Error Handling"
        },
        {
            "location": "/topics/realtime/#options",
            "text": "By design, self-maintaining queries are straightforward to use and do not require you to configure anything. However, you can customize behavior by providing an  options  argument as first parameter to the  resultStream  function. \nCurrently, there is only one parameter:   reconnect  (default:  -1 ): determines how often the self-maintaining query is resubscribed after connection loss (negative values indicating infinite retries). \nBy default, a self-maintaining query will be resubscribed and the full initial result will be delivered again whenever the websocket connection drops. Since the full query result (and not just changed objects) is transmitted on subscription,  reconnecting can impose significant communication overhead  for large result sets. To shield against this kind of performance leak, you can specify a non-negative integer to override this behavior. In this case, you should also provide a  complete  handler which is going to be called after the number of reconnect tries has been exhausted.",
            "title": "Options"
        },
        {
            "location": "/topics/realtime/#event-stream-queries",
            "text": "Calling  .eventStream()  on a query object creates an observable that encapsulates all data modifications relevant to your query. But in contrast to a self-maintaining query, an event stream query will not give you a full-blown result on every change, but instead an event notification describing what exactly happened.    Note:  \nIf you haven't already, you should read the guide section on  observables and subscriptions  as an introduction on how to work with Baqend's real-time API.  You can create an event stream observable like this:  var query = DB.Todo.find().matches('name', /^My Todo/);\nvar stream = query.eventStream(); // observable  To make your code react to result changes, you can subscribe to the observable and provide a function that is called for every incoming change event:  var subscription = stream.subscribe(event => console.log(event));  As with self-maintaining queries, you can also provide functions to handle errors and connection problems:  var onNext = event => console.log(event);\nvar onError = err => console.log(err); // optional\nvar onComplete = () => console.log('I am offline!'); // optional\n\nvar subscription = stream.subscribe(onNext, onError, onComplete);  And of course, you can also skip creating the observable and directly subscribe to an event streaming query:  var subscription = query.eventStream(onNext, onError, onComplete);  To cancel your subscription and thus stop receiving events from an event stream query, just unsubscribe:  subscription.unsubscribe();  In order to activate event stream updates for a query, all you have to do is register it as an event stream query and provide a function to execute for every received change event:  var query = DB.Todo.find()\n              .matches('name', /^My Todo/)\n              .ascending('deadline')\n              .limit(20);\nvar subscription = query.eventStream()\n              .subscribe(event => console.log(event));\n//...\nnew DB.Todo({name: 'My Todo XYZ'}).insert(); // insert data\n//...\n// The insert produces the following event:\n//{\n//  \"matchType\":\"add\",\n//  \"operation\":\"insert\",\n//  \"data\":{\"name\":\"do groceries\",...},\n//  \"date\":\"2016-11-09T12:42:31.322Z\"\n//  \"initial\":true,\n//  \"index\":1\n//}  Once subscribed to a stream, you will get an event for every database entity in the initial result set (i.e. every entity matching at subscription time) and for every entity that enters the result set, leaves the result set or is updated while in the result set.  Every event can carry the following information:   id : the subscription ID  date : server-time from the instant at which the event was generated.  initial:  a boolean value indicating whether this event reflects the matching status at query time ( true ) or a recent change data change ( false ).  index  (for sorting queries only): the position of the matching entity in the ordered result ( undefined  for non-matching entities).  data:  the database entity this event was generated for, e.g. an entity that just entered or left the result set. (For self-maintaining queries, this attribute carries the updated result.)  matchType:  indicates how the transmitted entity relates to the query result.\nEvery event is delivered with one of the following match types:  'add' : the entity entered the result set, i.e. it did not match before and is matching now.  'change' : the entity was updated, but remains a match.  'changeIndex'  (for sorting queries only): the entity was updated and remains a match, but changed its position within the query result.  'remove' : the entity was a match before, but is not matching any longer.  'match' : the entity matches the query (subsumes  'add' ,  'change'  and  'changeIndex' ). You will only receive this match type, if you explicitly request it.    operation:  the operation by which the entity was altered ( 'insert' ,  'update'  or  'delete' ;  'none'  if unknown or not applicable). \nFor an example where neither  'insert' ,  'update'  nor  'delete'  can reasonably be applied to an event, consider how the last one in a top-10 query result is pushed out when a new contender enters the top-10: While one event represents the insertion of the new contender itself, another event represents the entity leaving the result which was neither inserted, updated nor deleted. Consequently, Baqend would deliver this event with a  'none'  operation.",
            "title": "Event Stream Queries"
        },
        {
            "location": "/topics/realtime/#options_1",
            "text": "By default, you receive the initial result set and all events that are required to maintain it. However, the optional argument for the  .eventStream([options])  function lets you restrict the kind of event notifications to receive by setting the appropriate attribute values:   initial  (default:  true ): whether or not you want to receive the initial result set. If set to  true , every entity matching the query at subscription time will be delivered with match type  add , irrespective of whether and which restrictions you impose on operations and match types (see the other options). If set to  false , you will only receive an event when something changes.  matchTypes  (default:  ['all'] ): The default gives you all events with the most specific match type ( 'add' ,  'change' ,  'changeIndex'  or  'remove' ). If you are only interested in a specific subset of match types, you can specify any combination of them to listen for.\nIf you do not care about the difference between new and updated items, you can also use match type  'match' . This will yield the same events as the combination of  'add' ,  'change'  and  'changeIndex' , but the match type of the received events will always be  'match' .  operations  (default:  ['any'] ): By default, events will not be sorted out based on their operation, but you can choose any combination of  'insert' ,  'update' ,  'delete'  and  'none'  to narrow down the kind of matches you receive.    Note:  \nYou can only restrict the event stream by  either match type or operation , but not both.  Complex semantics:  \nFiltering events by  operation  does not work as straightforward as you might think at first glance. So before using this feature, be sure to read the parameter description above and the  example  below.",
            "title": "Options"
        },
        {
            "location": "/topics/realtime/#event-stream-simple-queries",
            "text": "Simple queries  are queries that just return all entities in a collection, no filtering involved. While event stream simple queries can be very useful (for example to monitor all operations on the collection), they can produce vast amounts of events for collections that have many members or are updated very often. Therefore, you should be  particularly  careful to only subscribe to events you really want to be bothered with when using event stream simple queries.  For instance, if you are interested in all todo lists and only want to be notified as  new  lists are created, you could subscribe to the following stream:  var stream = DB.Todo.find().eventStream({operations: 'insert'});// initial result is delivered by default  If, on the other hand, you only care for the creation of new todo lists and not for the ones that are already in the database, you should not request the initial result set:  var stream = DB.Todo.find().eventStream({initial: false, operations: 'insert'});",
            "title": "Event Stream Simple Queries"
        },
        {
            "location": "/topics/realtime/#event-stream-filter-queries",
            "text": "Like regular filter queries,  event stream filter queries  allow you to select entities based on their attribute values by applying  filters .  You can, for instance, have the database send you an event for every todo list that is  created  with a name that matches a particular pattern:  var stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .eventStream({initial: false, operations: 'insert'});  It is important to note, however, that the above query will only tell you when a new todo list matches your query  on insert ; it will  not  produce an event when an already-existing list is renamed to match your pattern, because that would happen by  update  (while the stream is targeting  insert  operations only).  If you are really looking for an event stream query that gives you new matches irrespective of the triggering operation, you should work with  matchTypes  and leave  operations  at the default:  var stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .eventStream({initial: false, matchTypes: 'add'});// operations: ['any'] by default  To get the full picture, you can also request the initial result upfront. Initial matches are always delivered with match type  add :  var stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .eventStream({matchTypes: 'add'});// initial: true by default  Of course, you can combine several predicates using  and ,  or  and  nor . The following query keeps you up-to-date on all todo lists that are active and match one pattern or have already been marked as done and match another pattern:  var queryBuilder = DB.Todo.find();\nvar condition1 = queryBuilder\n  .matches('name', /^My Todo/)\n  .equal('active', true);\n\nvar condition2 = queryBuilder\n  .matches('name', /^Your Todo/)\n  .equal('done', true);\n\nvar stream = queryBuilder\n               .or(condition1, condition2)\n               .eventStream();",
            "title": "Event Stream Filter Queries"
        },
        {
            "location": "/topics/realtime/#event-stream-sorting-queries",
            "text": "All features described so far are also available for  event stream sorting queries , i.e. queries that contain  limit ,  offset ,  ascending ,  descending  or  sort .\nEvents stream sorting queries are great to maintain ordered results such as high-score rankings or prioritized todo lists.  The following generates events for your top-20 todo lists, sorted by urgency, name and status:  var stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .ascending('name')\n               .descending('active')\n               .limit(20)\n               .eventStream();  Entities that sort identically are  implicitly ordered by ID . Thus, a query without explicit ordering will result in more or less random order by default as IDs are generated randomly:  var stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .limit(20)// no order provided? Implicitly ordered by ID!\n               .eventStream();  The  limit  clause is optional  and a query without limit will be registered with the maximum permitted limit:  offset + limit <= 500  must always hold. In other words,  limit  can never assume values greater than  500 - offset . Correspondingly, queries with an  offset  of more than 499 are illegal. \nSince the maximum limit is implicitly enforced, the following three event stream queries are registered identical:  var implicitLimit = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .offset(5)\n               .eventStream(); // implicit limit: 495 (= 500 - offset)\n\nvar explicitLimit = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .offset(5)\n               .limit(495) // explicit limit\n               .eventStream();\n\nvar cappedLimit = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .offset(5)\n               .limit(500) // limit is capped to 495, so that offset + limit <= 500\n               .eventStream();  An event stream sorting query with  offset  maintains an ordered result, hiding the first few items from you. However, the first index in a sorted query result is always  0 , irrespective of whether it is specified with  offset  or not. Accordingly, events for the following subscription will carry  index  values in the range between  0  and  9 :  var stream = DB.Todo.find()\n               .matches('name', /^My Todo/)\n               .ascending('deadline')\n               .ascending('name')\n               .descending('active')\n               .offset(5)// skip the first 5 items\n               .limit(10)// only return the first 10 items\n               .eventStream();  With respect to efficiency, the same rules apply to event stream and regular (i.e. non-streaming) queries: Enforcing order on huge results is expensive and sorting queries should therefore be avoided when filter queries would do as well.  Note:  Currently, event stream sorting queries are  always executed as anonymous queries , i.e. they will only give you data that is publicly visible. To retrieve data protected by object ACLs, you have to either forgo real-time (use a plain sorting query) or ordering (use a real-time query without  limit ,  offset ,  ascending  and  descending ).",
            "title": "Event Stream Sorting Queries"
        },
        {
            "location": "/topics/realtime/#example-subscription-and-events",
            "text": "For an example of how an event stream query behaves, consider the following example where two users are working concurrently on the same database.  User 1  subscribes to an event stream sorting query and listens for the result and updates, whereas  User 2  is working on the data.  Timestamp 0:   User 1  and  User 2  are connected to the same database.  Timestamp 1:   User 2  inserts  todo1 :  var todo1 = new DB.Todo({name: 'My Todo 1'});\ntodo1.insert();\n\n//actual result: [ todo1 ]  Timestamp 2:   User 1  subscribes to an event stream query and immediately receives a match event for  todo1 :  var stream = DB.Todo.find()\n    .matches('name', /^My Todo/)\n    .ascending('name')\n    .descending('active')\n    .limit(3)\n    .eventStream();\nsubscription = stream.subscribe((event) => {\n  console.log(event.matchType + '/'\n    + event.operation + ': '\n    + event.data.name + ' is now at index '\n    + event.index);\n});\n// ... one round-trip later\n//'add/none: My Todo 1 is now at index 0'  Timestamp 3:   User 2  inserts  todo2 :  var todo2 = new DB.Todo({name: 'My Todo 2'});\ntodo2.insert();\n\n//actual result: [ todo1, todo2 ]  Timestamp 4:   User 1  receives a new event for  todo2 :  //'add/insert: My Todo 2 is now at index 1'  Timestamp 5:   User 2 : inserts  todo3 :  var todo3 = new DB.Todo({name: 'My Todo 3'});\ntodo3.insert();\n\n//actual result: [ todo1, todo2, todo3 ]  Timestamp 6:   User 1  receives a new event for  todo3 :  //'add/insert: My Todo 3 is now at index 2'  Timestamp 7:   User 2  updates  todo3  in such a way that its position in the ordered result changes:  todo3.name = 'My Todo 1b (former 3)';\ntodo3.update();\n\n//actual result: [ todo1, todo3, todo2 ]  Timestamp 8:   User 1  is notified of this update through an event that delivers the new version of  todo3 . The fact that  todo3  had already been a match and just changed its position in the result is encoded in the event's match type  changeIndex :  //'changeIndex/update: My Todo 1b (former 3) is now at index 1'  Timestamp 9:   User 2  inserts  todo0  which sorts before all other items in the result and therefore is assigned index  0 :  var todo0 = new DB.Todo({name: 'My Todo 0'});\ntodo0.insert();\n\n//entities in DB: [ todo0, todo1, todo3 ], todo2\n//                 <--- within limit --->  Because of the  .limit(3)  clause, only the first three of all four matching entities are valid matches and the last one \u2014 currently  todo2  \u2014 is  pushed beyond limit  and therefore leaves the result.  Timestamp 10:   User 1  receives two events that correspond to the two relevant changes to the result:  //'remove/none: My Todo 2 is now at index undefined'\n//'add/insert: My Todo 0 is now at index 0'  Timestamp 11:   User 2  updates  todo3  again, so that it assumes its original name:  todo3.name = 'My Todo 3';\ntodo3.update();\n\n//entities in DB: [ todo0, todo1, todo2 ], todo3\n//                 <--- within limit --->  Through this update,  todo2  and  todo3  swap places.  Timestamp 12:   User 1  receives the corresponding events:  //'remove/update: My Todo 3 is now at index undefined'\n//'add/none: My Todo 2 is now at index 2'  Timestamp 13:   User 2  deletes  todo3 :  todo3.delete();\n\n//entities in DB: [ todo0, todo1, todo2 ]  Note that the deleted entity was not part of the result set.  Timestamp 14:   User 1  no match, because deleting  todo3  had no effect on the query result.  //nothing happened  User 1 starts receiving the initial result directly after subscription (Timestamp 2). From this point on, any write operation performed by User 2 is forwarded to User 1 \u2014 as long as it's affecting the subscribed query's result. Changes to non-matching items have no effect in the eyes of User 1 (Timestamps 13/14).  Be aware that operation-related semantics are rather complex for sorting queries: For example,  insert  and  update  operations may trigger an item to  leave  the result (Timestamps 9/10 and 11/12). Similarly (even though not shown in the example), an  add  event can be triggered by a  delete  when an item enters the result set from beyond limit. When triggered by an operation on a different entity, an event may even be delivered with no operation at all (Timestamps 10 and 12).  Tip: \nBottom line, be careful when filtering the event stream of a sorted query by operation!",
            "title": "Example: Subscription and Events"
        },
        {
            "location": "/topics/realtime/#advanced-features-rxjs",
            "text": "The Baqend Real-Time SDK is shipped with  basic support for ES7 Observables , so that you can use it without requiring external dependencies.\nTo leverage the full potential of Baqend's real-time query engine, though, we recommend using it in combination with the feature-rich RxJS client library.  In the following, we give you some references and a few examples of what you can do with RxJS and Baqend Real-Time Queries.",
            "title": "Advanced Features: RxJS"
        },
        {
            "location": "/topics/realtime/#rxjs-the-reactivex-javascript-client-library",
            "text": "Since the  RxJS documentation is great and extensive , we do not go into detail on our client library, but rather provide a few references to get you started:   What is ReactiveX?  What is an observable?  Operators: What can I do with an observable?  Which operator do I need for ...?",
            "title": "RxJS: The ReactiveX JavaScript Client Library"
        },
        {
            "location": "/topics/realtime/#real-time-aggregations",
            "text": "Another neat use case for event stream queries is to compute and maintain aggregates in real-time.\nSimilar to result set maintenance, the basic idea is to keep all relevant information in an  accumulator  and to recompute and output the updated aggregate value whenever an event is received.",
            "title": "Real-Time Aggregations"
        },
        {
            "location": "/topics/realtime/#count",
            "text": "One of the simpler aggregates over a collection of entities is the  cardinality  or  count , i.e. the number of entities in the collection. The following code will compute and maintain the cardinality of the query result:  var maintainCardinality = (counter, event) => {\n  if (event.matchType === 'add') {// entering item: count + 1\n    counter++;\n  } else if (event.matchType === 'remove') {// leaving item: count - 1\n    counter--;\n  }\n  return counter;\n};\n\nvar subscription = stream.scan(maintainCardinality, 0)// update counter\n                     .subscribe(value => console.log(value));// output counter  The current number of entities in the result set will be printed to the console whenever a change occurs.  Tip: \nCount maintenance is a good example where it makes sense to not subscribe to the default match types ( ['all'] ), because you are actually only interested in  add  and  remove  events: To restrict the events you will receive to those that really matter, register the event stream query with  .eventStream({matchTypes: ['add', 'remove']}) .",
            "title": "Count"
        },
        {
            "location": "/topics/realtime/#average",
            "text": "Now to a more complex example: Let's say you are interested in the  average number of activities  of each of the todo lists matching your query.  var initialAccumulator = {\n  contributors: {},// individual activity counts go here\n  count: 0,// result set cardinality\n  sum: 0,// overall number of activities in the result\n  average: 0// computed as: sum/count\n};  The accumulator is not just an integer, but an object with several values: For maximum precision, we maintain the overall number of activities ( sum ) and result cardinality ( count ) separately and compute the  average  fresh on every event. We remember the number of activities for every individual entity in a map ( contributors ); this is necessary, because otherwise we would not have a clue by how much to decrement  sum  when an entity is updated or leaves the result set.  var maintainAverage = (accumulator, event) => {\n  var newValue = event.matchType === 'remove' ? 0 : event.data.activities.length;\n  var oldValue = accumulator.contributors[event.data.id] || 0;//default: 0\n\n  if (newValue !== 0) {// remember new value\n    accumulator.contributors[event.data.id] = newValue;\n  } else {// forget old value\n    delete accumulator.contributors[event.data.id];\n  }\n  accumulator.sum += newValue - oldValue;\n  accumulator.count += event.matchType === 'remove' ? -1 : event.matchType === 'add' ? 1 : 0;\n  accumulator.average = accumulator.count > 0 ? accumulator.sum / accumulator.count : 0;\n  return accumulator;\n};  The maintenance function extracts the current number of activities ( newValue ) from the incoming event and the former value ( oldValue ) from the  contributors  map in the accumulator. Depending on whether the incoming entity contributes to the average or not, it either stores the new value in the map or removes the old value. Finally,  sum  and  count  are updated and the average is computed and stored as  accumulator.average .  Since we are only interested in the average value, we add another step to extract it from the accumulator via the  map  operator:  var subscription = stream.scan(maintainAverage, initialAccumulator)//update counter\n                           .map(accumulator => accumulator.average)//extract average\n                           .subscribe(value => console.log(value));//output counter",
            "title": "Average"
        },
        {
            "location": "/topics/realtime/#limitations",
            "text": "The real-time feature is available for all queries with the following limitations:   Currently,  real-time sorting queries only return public data , even when executed with admin privileges; to retrieve private data, use regular (i.e. non-streaming) sorting queries or real-time queries that do not contain  limit ,  offset ,  ascending ,  descending  or  sort .  Geospatial queries ( withinSphere ,  withinPolygon ) are currently not available for real-time",
            "title": "Limitations"
        },
        {
            "location": "/topics/user-management/",
            "text": "Users, Roles, and Permissions\n\n\nBaqend comes with a powerful user, role, and permission management. This includes a generic registration and login \nmechanism and allows restricting access to insert, load, update, delete, and query operations through per-class and \nper-objects rules. These access control lists (ACLs) are expressed through allow and deny rules on users and roles.\n\n\nRegistration\n\n\nTo restrict access to a specific role or user, the user needs a user account. Baqend supports a simple registration \nprocess to create a new user account. The user class is a predefined class which will be instantiated during the registration \nprocess. A user object has a predefined \nusername\n which uniquely identifies the user (usually an email address) and a \npassword\n. The password\nwill be hashed and salted by Baqend before being saved.   \n\n\nDB.User.register('john.doe@example.com', 'MySecretPassword').then(function() {\n  //Hey we are logged in\n  console.log(DB.User.me.username); //'john.doe@example.com'\n});\n\n\n\n\nIf you like to set additional user attributes for the registration, you can alternatively create a new user instance and register\nthe newly created instance with a password.\n\n\nvar user = new DB.User({\n  'username': 'john.doe@example.com',\n  'firstName': 'John',   \n  'lastName': 'Doe',   \n  'age': 33\n});\n\nDB.User.register(user, 'MySecretPassword').then(function() {\n  //Hey we are logged in\n  console.log(DB.User.me === user); //true\n});\n\n\n\n\nLoginOption\n\n\nIf you don't want your user to be logged in or his login only to be valid for the current session after his registration, you can also pass a login option as third parameter:\n\n\nDB.User.register('john.doe@example.com', 'MySecretPassword', DB.User.LoginOption.NO_LOGIN).then(function() {\n  //Hey we are not logged in\n  console.log(DB.User.me); //null\n});\n\n\n\n\nThe following login options exist:\n\n\n\n\nLoginOption.NO_LOGIN\n - Users are not logged in after registration.\n\n\nLoginOption.SESSION_LOGIN\n - User is only logged in for the active session \u2013 after he closes the browser, he will be logged out.\n\n\nLoginOption.PERSIST_LOGIN\n - User is fully logged in (default behavior). \n\n\n\n\n\n  \nTip:\n\n  You can also use the \nLoginOption\n when logging a user in: \nDB.User.login('username', 'password', DB.User.LoginOption.SESSION_LOGIN)\n, for example.\n\n\n\n\nEmail Verification\n\n\nBy default a newly registered user is automatically logged in and does not need to verify his email address.\nTo enable email verification open the \nsettings\n in the Baqend dashboard and go to the email section.\nThere you can enable the email verification and setup a template for the verification email, which is then automatically send to every newly registered user.\n\n\nUntil the newly registered user has verified his email address by clicking on the verification link in the verification email, he is considered inactive and cannot log in.\nThis state is indicated by a read only \ninactive\n field of type \nBoolean\n in the user object. After verification this field is automatically set to \nfalse\n.\nOnly the admin is able to set the \ninactive\n field manually, e.g. to activate or ban users.\n\n\nEmail Hooks\n\n\nEvery time Baqend sends an email to a user, you can hook to that event by \nproviding a module\n.\nThere are two emails sent out:\n\n\n\n\nthe \nuser.register\n hook is called before a registration email is sent,\n\n\nthe \nuser.resetPassword\n hook is called before a reset-password email is sent.\n\n\n\n\nYou can manipulate the contents of the email via the following fields:\n\n\n\n\ntemplate\n - the email template you can configure in the settings. \n\n\nbody\n - the compiled template containing the variable values.\n\n\nlink\n - the link which can be configured in the settings.\n\n\nsubject\n - the email subject.\n\n\nto\n - email of the receiver.\n\n\nfromName\n - name of the sender of the email.\n\n\n\n\nMake sure to \nreturn the email object\n in the end; if not, no email will be sent!\n\n\nHere is an example:\n\n\nexports.call = function call(db, email, req) {\n  var recipient = db.User.me; //Get the recipient's unloaded user object\n\n  email.to = 'Jane Doe <jane.doe@example.com>';\n  email.fromName = 'John Doe';\n  email.template = 'Hey Jane! Follow the link to reset your password: {{link}} \u2013 Yours, John';\n  email.subject = 'Forgotten Password';\n\n  return email;\n}\n\n\n\n\nLogin and Logout\n\n\nWhen a user is already registered, he can login with the \nDB.User.login()\n method. \n\n\nDB.User.login('john.doe@example.com', 'MySecretPassword').then(function() {\n  //Hey we are logged in again\n  console.log(DB.User.me.username); //'john.doe@example.com'  \n});\n\n\n\n\nAfter the successful login a session will be established and all further requests to Baqend are authenticated \nwith the currently logged-in user.\nYou can also pass \nlogin options\n as a third parameter if you want the user to be logged in during the current session.\n\n\nSessions in Baqend are stateless, that means there is no state attached to a session on the server side.\nWhen a session is started a session token with a specified lifetime is created to identify the user.\nThis session is refreshed as long a the user is active. If this lifetime is exceeded, the session\nis closed automatically. A logout simply locally deletes the session token and removes the current\n\nDB.User.me\n object.\n\n\nDB.User.logout().then(function() {\n  //We are logged out again\n  console.log(DB.User.me); //null\n});\n\n\n\n\nNote:\n There is no need to close the session on the server side or handle any session state like in a PHP application for example.\n\n\n\nTip:\n  The \nmaximum session lifetime\n is determined by the so called session \nlonglife\n (default: 30 days). After this time the session expired and the user has to explicitly log in again.\nYou can set the \nlonglife\n in the settings of your Baqend dashboard.\n\n\n\nForgot Password\n\n\nIf your user forgot his password, you will want him to reset it.\nTherefore, you can let Baqend send him an email which includes a \u201creset password\u201d link, by calling:\n\n\n// Send a \u201creset password\u201d email\nDB.User.resetPassword('Username').then(() => {\n  //User received an email\n});\n\n\n\n\nIn your app settings, you can configure the email template and the reset-password URL the user is navigated to when he clicks the link in that email. \n\n\n\n\nOn your reset-password site, you can then set the new password in Baqend by calling:\n\n\nconst paramName = 'bq-token='; //Default token parameter \nconst search = location.search;\nconst token = search.substring(search.indexOf(paramName) + paramName.length);\nDB.User.newPassword(token, 'NewPassword').then(() => {\n //User is now logged in\n});\n\n\n\n\nYou can also pass \nlogin options\n as a third parameter if you don't want the user to be logged in after setting his password.\n\n\nNew Passwords\n\n\nPassword can be changed by giving the old password and specifying the new one. Admin users can change the passwords of all users without giving the previous one:\n\n\n//Using the user name\nDB.User.newPassword('Username', 'oldPassword', 'newPassword').then(() => {\n    //New Password is set\n});\n\n//Using a user object\nDB.User.me.newPassword('oldPassword', 'newPassword').then(...);\n\n//When logged in as an admin\nDB.User.newPassword('Username', null, 'newPassword').then(...);\n\n\n\n\nAutomatic Login\n\n\nDuring initialization the Baqend SDK checks, if the user is already registered and has been logged in before in this session and has not logged out explicitly.\nAs a consequence, returning users are automatically logged in and the \nDB.User.me\n object is set.\nNew user are anonymous by default and no user object is associated with the DB.\n\n\nDB.ready(function() {\n  if (DB.User.me) {\n    //do additional things if user is logged in\n    console.log('Hello ' + DB.User.me.username); //the username of the user\n  } else {\n    //do additional things if user is not logged in\n    console.log('Hello Anonymous');\n  }\n});\n\n\n\n\nLoading Users\n\n\nUser objects are private by default, i.e. only admins and the user itself can load or update the object. This behaviour is intended to protect sensitive user information. There are two ways to grant access to user objects:\n\n\n\n\nThe first (\nnot\n recommended) way is to grant access to specific users or groups or even to make the user objects publicly accessible. Because user objects are protected by object-level ACLs you need to have a look at Baqend's \npermission system\n to change the permissions.\n\n\nThe second (recommended) way is to divide your user information into two categories \npublic\n and \nprivate\n. Then store the private information in the private \nuser\n object and the public information in a separate \nprofile\n object that is publicly accessible and linked to the \nuser\n object.\n\n\n\n\nRoles\n\n\nThe Role class is also a predefined class which has a \nname\n and  a \nusers\n collection. The users collection \ncontains all the members of a role. A user has a specified role if he is included in the roles \nusers\n list. \n\n\n//create a new role\nvar role = new DB.Role({name: 'My First Group'});\n//add current user as a member of the role\nrole.addUser(DB.User.me);\n//allow the user to modify the role memberships\n//this overwrites the default where everyone has write access\nrole.acl.allowWriteAccess(DB.User.me);\nrole.save().then(...);\n\n\n\n\nA role can be read and written by everyone by default. To protect the role so that no one else can add himself to the \nrole we restrict write access to the current user. For more information about setting permissions see the \nsetting \nobject permissions\n chapter. \n\n\nPredefined Roles\n\n\nThere are three predefined roles:\n\n\n\n\nadmin\n - Users belonging to this role (e.g. the root) have full access to everything\n\n\nloggedin\n - Every user who is logged in, automatically has this role. The role can be used to require a user to have a logged-in account to perform certain actions.\n\n\nnode\n - When an operation is triggered by a handler or module, the roles of the user who triggered that request are enhanced by the node role. \n\n\n\n\nPredefined roles can be used just like normal roles. Typical use-case are that you define schema-level permissions to elevate rights of operations triggered by handlers and modules, allow certain things to logged-in users or restrict access to admins.\n\n\nNote:\n The node role does not have any special privileges by default, but you can use it in ACLs to give it special rights.\n\n\n\nPermissions\n\n\nThere are two types of permissions: \nclass-based\n and \nobject-based\n. The class-based permissions can be set\n by privileged users on the Baqend dashboard or by manipulating the class metadata. The object-based permissions can \n be set by users which have write-access to an object. As shown in the image below the class-level permissions are checked first. If the requesting user has the right permission on class level, the object-level permissions are checked. Only if the requesting user also has the right permissions on object level, he is granted acces to the entity.\n\n\n\n\nEach permission consists of one allow and one deny list. In the allow list user and roles can be white listed and in \nthe deny list they can be black listed. \n\n\nThe access will be granted based on the following rules:\n\n\n\n\nIf the user has the admin role, access is always granted and the following rules will be skipped\n\n\nOtherwise:\n\n\nIf the user or one of its roles are listed in the deny list, access is always denied\n\n\nIf no rules are defined in the allow list, public access is granted\n\n\nIf rules \nare\n defined the user or one of its roles has to be listed in the allow list in order to get access\n\n\n\n\nThe following table shows the SDK methods and the related permissions the user has to have, to perform the specific \noperation.\n\n\n\n  \n\n    \nMethod\n\n    \nClass-based permission\n\n    \nObject-based permission\n\n  \n\n  \n\n    \n.load()\n\n    \ntype.loadPermission\n\n    \nobject.acl.read\n\n  \n\n  \n\n    \n.find()\n\n    \ntype.queryPermission\n\n    \nobject.acl.read\n\n  \n\n  \n\n    \n.insert()\n\n    \ntype.insertPermission\n\n    \n-\n\n  \n\n  \n\n    \n.update()\n\n    \ntype.updatePermission\n\n    \nobject.acl.write\n\n  \n\n  \n\n    \n.delete()\n\n    \ntype.deletePermission\n\n    \nobject.acl.write\n\n  \n\n  \n\n    \n.save()\n\n    \ntype.insertPermission if the object is inserted\n\n      type.updatePermission if the object is updated\n    \n\n    \nobject.acl.write\n\n  \n\n  \n\n    \n.save({force: true})\n\n    \nboth type.insertPermission and type.updatePermission will be checked\n\n    \nobject.acl.write\n\n  \n\n\n\n\n\nNote:\n There is currently no way to check if a user has permissions to perform an operation without actually \nperforming the operation. \n\n\n\nAnonymous Users & Public Access\n\n\nAnonymous users only have permissions to serve public resources. A resource is publicly accessible, if\nno class or object permission restricts the access to specific users or roles. To check if the object's\npermissions allow public access you can check the \nacl.isPublicReadAllowed()\n and the \ntodo.acl.isPublicWriteAllowed()\n \nmethods.\n\n\ntodo.acl.isPublicReadAllowed() //will return true by default\ntodo.acl.isPublicWriteAllowed() //will return true by default\n\n\n\n\nNote:\n The access can still be restricted to specific roles or users by class-based permissions even if \n  \nacl.isPublicReadAllowed()\n or \ntodo.acl.isPublicWriteAllowed()\n returns \ntrue\n.\n\n\nSetting Object Permissions\n\n\nThe object permissions are split up in read and write permissions. When inserting a new object, by default read and \nwrite access is granted to everyone. You can manipulate object permissions only if you have write permissions on the object. If you want to restrict write access to the current user but want to share an object within a group, you \ncan add the role to the read permissions and the current user to the write permissions.\n\n\nDB.Role.find().equal('name', 'My First Role').singleResult(function(role) {\n  var todo = new DB.Todo({name: 'My first Todo'});\n  todo.acl.allowReadAccess(role)\n    .allowWriteAccess(DB.User.me);\n\n  return todo.save();\n}).then(...);\n\n\n\n\nOAuth login\n\n\nAnother way to login or register is via a 'Sign in with' - 'Google' or 'Facebook' button. \nIn general any OAuth provider can be used to authenticate and authorise a user. \nAs of now, Baqend supports the main five providers.\n\n\nSetup\n\n\nTo set them up, follow these steps:\n \n\n    \nRegister your applications on the provider's website. The table below links to the provider websites and documentation.\n\n    \nKeep the \nclient ID\n and a \nclient secret\n generated by the provider for later.\n\n    \nTake the link from the table below (according to your provider) and set it as the redirect URL on the provider's website.\n\n    \nLastly go to the settings in your Baqend dashboard and paste in the \nclient ID\n and \nclient secret\n for the provider in the OAuth section.\n\n \n\n\nSupported Providers\n\n\n\n    \n\n        \nProvider Setup\n\n        \nNotes\n\n    \n\n    \n\n        \ngoogle\n\n        \ndocs\n\n        \nAdd as redirect URL: \n \nhttps://<appName>.app.baqend.com/v1/db/User/OAuth/google\n\n    \n\n    \n\n        \nfacebook\n\n        \ndocs\n\n        \n\n            To set up Facebook-OAuth open the settings page of your \n            \nFacebook app\n, switch to \nAdvanced\n, activate \nWeb OAuth Login\n and \n            add \n \nhttps://<appName>.app.baqend.com/v1/db/User/OAuth/facebook\n \n as \nValid OAuth redirect URI\n. \n        \n\n    \n\n    \n\n        \ngithub\n\n        \ndocs\n\n        \nAdd as redirect URL: \n \nhttps://<appName>.app.baqend.com/v1/db/User/OAuth/github\n\n    \n\n    \n\n        \ntwitter\n\n        \ndocs\n\n        \nAdd as redirect URL: \nhttps://<appName>.app.baqend.com/v1/db/User/OAuth/twitter\n\n            Twitter does not support E-Mail scope. In default case a uuid is set as username.\n        \n\n    \n\n    \n\n        \nlinkedin\n\n        \ndocs\n\n        \nAdd as redirect URL: \n \nhttps://<appName>.app.baqend.com/v1/db/User/OAuth/linkedin\n\n    \n\n\n\n\nLogin & Registration\n\n\nIn order to use an OAuth provider to register or login users, you call one of the following SDK methods, depending on the provider:\n\n\nDB.User.loginWithGoogle(clientID, options).then((user) => {\n    //logged in successfully\n    db.User.me == user;\n});\n// Same for\nDB.User.loginWithFacebook(...)\nDB.User.loginWithGitHub(...)\nDB.User.loginWithTwitter(...)\nDB.User.loginWithLinkedIn(...)\n\n\n\n\nThe login call returns a promise and opens a new window showing the provider-specific login page.\nThe promise is resolved with the logged in user, once the login in the new window is completed.\nThe OAuth login does not distinguish between registration and login, so you don't have to worry about whether a user is already registered or not.\n\n\nIn the \noptions\n passed to the login you can configure the OAuth scope \namong others\n.\nThe scope defines what data is shared by the OAuth provider.\nOn registration the username is set to the email address if it's in the allowed scope. Otherwise a \nuuid\n is used.\n\n\nNote:\n For the login to work despite popup blockers the call needs to be made on response to a user interaction,\ne.g. after a click on the sign-in button. Also, an OAuth login will be aborted after 5 minutes of inactivity. The timeout can be changed with the timeout option.\n\n\n\nCustomize Login & Registration\n\n\nTo customize the login and registration behavior you can simply create a Baqend module named \noauth.[PROVIDER]\n, which is called after the user is logged in (or registered).\nIn this module you can access the logged in user and a data object containing the OAuth token as well as the user information shared by the OAuth provider.\nThe token can be used to directly do further API calls or save the token for later use.\n\n\nAs an example, if you like to edit the OAuth login for google, create the Baqend module \noauth.google\n. The module will be called after the user is successfully authorized:\n\n\nexports.call = function(db, data, req) {\n    db.User.me // the unresolved user object of the created or logged in user\n\n    // data contains the profile data send by the OAuth provider\n    data.id // The OAuth unique user id\n    data.access_token // The OAuth users API token\n    data.email // The users email if the required scope was requested by the client\n};\n\n\n\n\nThe following table lists more information on what data can be shared by the OAuth providers:\n \n\n  \n\n    \nProvider\n\n    \nProfile documentation\n\n  \n\n  \n\n    \ngoogle\n\n    \n\n      Just returns the email per default. \n      Visit \nOAuth 2.0 Scopes for Google APIs\n for a \n      complete list of supported scopes.\n    \n\n  \n\n  \n\n    \nfacebook\n\n    \nReturns the content of the \n    \nhttps://graph.facebook.com/v2.4/me\n resource\n\n  \n\n  \n\n    \ngithub\n\n    \nReturns the \nauthenticated user profile\n\n  \n\n  \n\n    \ntwitter\n\n    \nJust returns the \naccess_token\n. An Email address can't be queried with the twitter API.\n\n  \n\n  \n\n    \nlinkedin\n\n    \n\n      Returns the content of the \n      \nhttps://api.linkedin.com/v1/people/~?format=json\n resource.\n    \n\n  \n\n\n    \n\n\nNote:\n The returned properties depend on the requested scope.\n\n\n\nOAuth Login via Redirect\n\n\nIn some cases, it may be desirable to use the OAuth authorization without opening a new window,\ne.g. when cross-window communication is unavailable because of a missing \nlocalStorage\n object.\n\n\nTo use the login via redirect, you need to set a redirect parameter when calling the particular login method.\nIn this case, the SDK does not return the user object, but creates a unique token and redirects to the specified redirect URL.\nYour site will be closed and the provider login will open instead.\n\n\n//Set redirect parameter in loginOption\nloginOption = {'redirect': 'http://.../yourRedirectPage'};\n\n//call SDK method with loginOption\nDB.User.loginWithGoogle(clientID, loginOption).then(function(user) {\n    ...\n});\n\n\n\n\nAfter communicating with the OAuth provider, the unique token is sent as a query parameter to the specified redirect page.\nIn case of a failure, the particular error message is sent instead.\nThe following table lists more information of all possible query parameters:\n\n\n\n  \n\n    \nParameter\n\n    \nMeaning\n\n  \n\n  \n\n    \ntoken\n\n    \n\n      A unique token to identify the user object (in case of success)\n    \n\n  \n\n  \n\n    \nloginOption\n\n    \nThe specified login options (in case of success)\n\n  \n\n  \n\n    \nerrorMessage\n\n    \n\n        A url-encoded error message (in case of failure)\n    \n\n  \n\n\n\n\nIn case of success, you can call the following SDK method with the unique token and the specified login options\nas parameters to login the user.\n\n\nDB.User.loginWithToken(token, options).then(function(user) {\n    //logged in successfully\n    db.User.me == user;\n});\n\n\n\n\nThe login call returns a promise which is resolved with the logged in user. The OAuth login does not distinguish between\nregistration and login, so you don't have to worry about whether a user is already registered or not.\n\n\nNote:\n For the login via redirect to work, ensure to register all valid redirect URLs\n(e.g. 'http://.../yourRedirectPage') in the \"Authorized Domains\" section of your dashboard settings.",
            "title": "User Management"
        },
        {
            "location": "/topics/user-management/#users-roles-and-permissions",
            "text": "Baqend comes with a powerful user, role, and permission management. This includes a generic registration and login \nmechanism and allows restricting access to insert, load, update, delete, and query operations through per-class and \nper-objects rules. These access control lists (ACLs) are expressed through allow and deny rules on users and roles.",
            "title": "Users, Roles, and Permissions"
        },
        {
            "location": "/topics/user-management/#registration",
            "text": "To restrict access to a specific role or user, the user needs a user account. Baqend supports a simple registration \nprocess to create a new user account. The user class is a predefined class which will be instantiated during the registration \nprocess. A user object has a predefined  username  which uniquely identifies the user (usually an email address) and a  password . The password\nwill be hashed and salted by Baqend before being saved.     DB.User.register('john.doe@example.com', 'MySecretPassword').then(function() {\n  //Hey we are logged in\n  console.log(DB.User.me.username); //'john.doe@example.com'\n});  If you like to set additional user attributes for the registration, you can alternatively create a new user instance and register\nthe newly created instance with a password.  var user = new DB.User({\n  'username': 'john.doe@example.com',\n  'firstName': 'John',   \n  'lastName': 'Doe',   \n  'age': 33\n});\n\nDB.User.register(user, 'MySecretPassword').then(function() {\n  //Hey we are logged in\n  console.log(DB.User.me === user); //true\n});",
            "title": "Registration"
        },
        {
            "location": "/topics/user-management/#loginoption",
            "text": "If you don't want your user to be logged in or his login only to be valid for the current session after his registration, you can also pass a login option as third parameter:  DB.User.register('john.doe@example.com', 'MySecretPassword', DB.User.LoginOption.NO_LOGIN).then(function() {\n  //Hey we are not logged in\n  console.log(DB.User.me); //null\n});  The following login options exist:   LoginOption.NO_LOGIN  - Users are not logged in after registration.  LoginOption.SESSION_LOGIN  - User is only logged in for the active session \u2013 after he closes the browser, he will be logged out.  LoginOption.PERSIST_LOGIN  - User is fully logged in (default behavior).    \n   Tip: \n  You can also use the  LoginOption  when logging a user in:  DB.User.login('username', 'password', DB.User.LoginOption.SESSION_LOGIN) , for example.",
            "title": "LoginOption"
        },
        {
            "location": "/topics/user-management/#email-verification",
            "text": "By default a newly registered user is automatically logged in and does not need to verify his email address.\nTo enable email verification open the  settings  in the Baqend dashboard and go to the email section.\nThere you can enable the email verification and setup a template for the verification email, which is then automatically send to every newly registered user.  Until the newly registered user has verified his email address by clicking on the verification link in the verification email, he is considered inactive and cannot log in.\nThis state is indicated by a read only  inactive  field of type  Boolean  in the user object. After verification this field is automatically set to  false .\nOnly the admin is able to set the  inactive  field manually, e.g. to activate or ban users.",
            "title": "Email Verification"
        },
        {
            "location": "/topics/user-management/#email-hooks",
            "text": "Every time Baqend sends an email to a user, you can hook to that event by  providing a module .\nThere are two emails sent out:   the  user.register  hook is called before a registration email is sent,  the  user.resetPassword  hook is called before a reset-password email is sent.   You can manipulate the contents of the email via the following fields:   template  - the email template you can configure in the settings.   body  - the compiled template containing the variable values.  link  - the link which can be configured in the settings.  subject  - the email subject.  to  - email of the receiver.  fromName  - name of the sender of the email.   Make sure to  return the email object  in the end; if not, no email will be sent!  Here is an example:  exports.call = function call(db, email, req) {\n  var recipient = db.User.me; //Get the recipient's unloaded user object\n\n  email.to = 'Jane Doe <jane.doe@example.com>';\n  email.fromName = 'John Doe';\n  email.template = 'Hey Jane! Follow the link to reset your password: {{link}} \u2013 Yours, John';\n  email.subject = 'Forgotten Password';\n\n  return email;\n}",
            "title": "Email Hooks"
        },
        {
            "location": "/topics/user-management/#login-and-logout",
            "text": "When a user is already registered, he can login with the  DB.User.login()  method.   DB.User.login('john.doe@example.com', 'MySecretPassword').then(function() {\n  //Hey we are logged in again\n  console.log(DB.User.me.username); //'john.doe@example.com'  \n});  After the successful login a session will be established and all further requests to Baqend are authenticated \nwith the currently logged-in user.\nYou can also pass  login options  as a third parameter if you want the user to be logged in during the current session.  Sessions in Baqend are stateless, that means there is no state attached to a session on the server side.\nWhen a session is started a session token with a specified lifetime is created to identify the user.\nThis session is refreshed as long a the user is active. If this lifetime is exceeded, the session\nis closed automatically. A logout simply locally deletes the session token and removes the current DB.User.me  object.  DB.User.logout().then(function() {\n  //We are logged out again\n  console.log(DB.User.me); //null\n});  Note:  There is no need to close the session on the server side or handle any session state like in a PHP application for example.  Tip:   The  maximum session lifetime  is determined by the so called session  longlife  (default: 30 days). After this time the session expired and the user has to explicitly log in again.\nYou can set the  longlife  in the settings of your Baqend dashboard.",
            "title": "Login and Logout"
        },
        {
            "location": "/topics/user-management/#forgot-password",
            "text": "If your user forgot his password, you will want him to reset it.\nTherefore, you can let Baqend send him an email which includes a \u201creset password\u201d link, by calling:  // Send a \u201creset password\u201d email\nDB.User.resetPassword('Username').then(() => {\n  //User received an email\n});  In your app settings, you can configure the email template and the reset-password URL the user is navigated to when he clicks the link in that email.    On your reset-password site, you can then set the new password in Baqend by calling:  const paramName = 'bq-token='; //Default token parameter \nconst search = location.search;\nconst token = search.substring(search.indexOf(paramName) + paramName.length);\nDB.User.newPassword(token, 'NewPassword').then(() => {\n //User is now logged in\n});  You can also pass  login options  as a third parameter if you don't want the user to be logged in after setting his password.",
            "title": "Forgot Password"
        },
        {
            "location": "/topics/user-management/#new-passwords",
            "text": "Password can be changed by giving the old password and specifying the new one. Admin users can change the passwords of all users without giving the previous one:  //Using the user name\nDB.User.newPassword('Username', 'oldPassword', 'newPassword').then(() => {\n    //New Password is set\n});\n\n//Using a user object\nDB.User.me.newPassword('oldPassword', 'newPassword').then(...);\n\n//When logged in as an admin\nDB.User.newPassword('Username', null, 'newPassword').then(...);",
            "title": "New Passwords"
        },
        {
            "location": "/topics/user-management/#automatic-login",
            "text": "During initialization the Baqend SDK checks, if the user is already registered and has been logged in before in this session and has not logged out explicitly.\nAs a consequence, returning users are automatically logged in and the  DB.User.me  object is set.\nNew user are anonymous by default and no user object is associated with the DB.  DB.ready(function() {\n  if (DB.User.me) {\n    //do additional things if user is logged in\n    console.log('Hello ' + DB.User.me.username); //the username of the user\n  } else {\n    //do additional things if user is not logged in\n    console.log('Hello Anonymous');\n  }\n});",
            "title": "Automatic Login"
        },
        {
            "location": "/topics/user-management/#loading-users",
            "text": "User objects are private by default, i.e. only admins and the user itself can load or update the object. This behaviour is intended to protect sensitive user information. There are two ways to grant access to user objects:   The first ( not  recommended) way is to grant access to specific users or groups or even to make the user objects publicly accessible. Because user objects are protected by object-level ACLs you need to have a look at Baqend's  permission system  to change the permissions.  The second (recommended) way is to divide your user information into two categories  public  and  private . Then store the private information in the private  user  object and the public information in a separate  profile  object that is publicly accessible and linked to the  user  object.",
            "title": "Loading Users"
        },
        {
            "location": "/topics/user-management/#roles",
            "text": "The Role class is also a predefined class which has a  name  and  a  users  collection. The users collection \ncontains all the members of a role. A user has a specified role if he is included in the roles  users  list.   //create a new role\nvar role = new DB.Role({name: 'My First Group'});\n//add current user as a member of the role\nrole.addUser(DB.User.me);\n//allow the user to modify the role memberships\n//this overwrites the default where everyone has write access\nrole.acl.allowWriteAccess(DB.User.me);\nrole.save().then(...);  A role can be read and written by everyone by default. To protect the role so that no one else can add himself to the \nrole we restrict write access to the current user. For more information about setting permissions see the  setting \nobject permissions  chapter.",
            "title": "Roles"
        },
        {
            "location": "/topics/user-management/#predefined-roles",
            "text": "There are three predefined roles:   admin  - Users belonging to this role (e.g. the root) have full access to everything  loggedin  - Every user who is logged in, automatically has this role. The role can be used to require a user to have a logged-in account to perform certain actions.  node  - When an operation is triggered by a handler or module, the roles of the user who triggered that request are enhanced by the node role.    Predefined roles can be used just like normal roles. Typical use-case are that you define schema-level permissions to elevate rights of operations triggered by handlers and modules, allow certain things to logged-in users or restrict access to admins.  Note:  The node role does not have any special privileges by default, but you can use it in ACLs to give it special rights.",
            "title": "Predefined Roles"
        },
        {
            "location": "/topics/user-management/#permissions",
            "text": "There are two types of permissions:  class-based  and  object-based . The class-based permissions can be set\n by privileged users on the Baqend dashboard or by manipulating the class metadata. The object-based permissions can \n be set by users which have write-access to an object. As shown in the image below the class-level permissions are checked first. If the requesting user has the right permission on class level, the object-level permissions are checked. Only if the requesting user also has the right permissions on object level, he is granted acces to the entity.   Each permission consists of one allow and one deny list. In the allow list user and roles can be white listed and in \nthe deny list they can be black listed.   The access will be granted based on the following rules:   If the user has the admin role, access is always granted and the following rules will be skipped  Otherwise:  If the user or one of its roles are listed in the deny list, access is always denied  If no rules are defined in the allow list, public access is granted  If rules  are  defined the user or one of its roles has to be listed in the allow list in order to get access   The following table shows the SDK methods and the related permissions the user has to have, to perform the specific \noperation.  \n   \n     Method \n     Class-based permission \n     Object-based permission \n   \n   \n     .load() \n     type.loadPermission \n     object.acl.read \n   \n   \n     .find() \n     type.queryPermission \n     object.acl.read \n   \n   \n     .insert() \n     type.insertPermission \n     - \n   \n   \n     .update() \n     type.updatePermission \n     object.acl.write \n   \n   \n     .delete() \n     type.deletePermission \n     object.acl.write \n   \n   \n     .save() \n     type.insertPermission if the object is inserted \n      type.updatePermission if the object is updated\n     \n     object.acl.write \n   \n   \n     .save({force: true}) \n     both type.insertPermission and type.updatePermission will be checked \n     object.acl.write \n     Note:  There is currently no way to check if a user has permissions to perform an operation without actually \nperforming the operation.",
            "title": "Permissions"
        },
        {
            "location": "/topics/user-management/#anonymous-users-public-access",
            "text": "Anonymous users only have permissions to serve public resources. A resource is publicly accessible, if\nno class or object permission restricts the access to specific users or roles. To check if the object's\npermissions allow public access you can check the  acl.isPublicReadAllowed()  and the  todo.acl.isPublicWriteAllowed()  \nmethods.  todo.acl.isPublicReadAllowed() //will return true by default\ntodo.acl.isPublicWriteAllowed() //will return true by default  Note:  The access can still be restricted to specific roles or users by class-based permissions even if \n   acl.isPublicReadAllowed()  or  todo.acl.isPublicWriteAllowed()  returns  true .",
            "title": "Anonymous Users &amp; Public Access"
        },
        {
            "location": "/topics/user-management/#setting-object-permissions",
            "text": "The object permissions are split up in read and write permissions. When inserting a new object, by default read and \nwrite access is granted to everyone. You can manipulate object permissions only if you have write permissions on the object. If you want to restrict write access to the current user but want to share an object within a group, you \ncan add the role to the read permissions and the current user to the write permissions.  DB.Role.find().equal('name', 'My First Role').singleResult(function(role) {\n  var todo = new DB.Todo({name: 'My first Todo'});\n  todo.acl.allowReadAccess(role)\n    .allowWriteAccess(DB.User.me);\n\n  return todo.save();\n}).then(...);",
            "title": "Setting Object Permissions"
        },
        {
            "location": "/topics/user-management/#oauth-login",
            "text": "Another way to login or register is via a 'Sign in with' - 'Google' or 'Facebook' button. \nIn general any OAuth provider can be used to authenticate and authorise a user. \nAs of now, Baqend supports the main five providers.",
            "title": "OAuth login"
        },
        {
            "location": "/topics/user-management/#setup",
            "text": "To set them up, follow these steps:\n  \n     Register your applications on the provider's website. The table below links to the provider websites and documentation. \n     Keep the  client ID  and a  client secret  generated by the provider for later. \n     Take the link from the table below (according to your provider) and set it as the redirect URL on the provider's website. \n     Lastly go to the settings in your Baqend dashboard and paste in the  client ID  and  client secret  for the provider in the OAuth section.",
            "title": "Setup"
        },
        {
            "location": "/topics/user-management/#supported-providers",
            "text": "Provider Setup \n         Notes \n     \n     \n         google \n         docs \n         Add as redirect URL:    https://<appName>.app.baqend.com/v1/db/User/OAuth/google \n     \n     \n         facebook \n         docs \n         \n            To set up Facebook-OAuth open the settings page of your \n             Facebook app , switch to  Advanced , activate  Web OAuth Login  and \n            add    https://<appName>.app.baqend.com/v1/db/User/OAuth/facebook    as  Valid OAuth redirect URI . \n         \n     \n     \n         github \n         docs \n         Add as redirect URL:    https://<appName>.app.baqend.com/v1/db/User/OAuth/github \n     \n     \n         twitter \n         docs \n         Add as redirect URL:  https://<appName>.app.baqend.com/v1/db/User/OAuth/twitter \n            Twitter does not support E-Mail scope. In default case a uuid is set as username.\n         \n     \n     \n         linkedin \n         docs \n         Add as redirect URL:    https://<appName>.app.baqend.com/v1/db/User/OAuth/linkedin",
            "title": "Supported Providers"
        },
        {
            "location": "/topics/user-management/#login-registration",
            "text": "In order to use an OAuth provider to register or login users, you call one of the following SDK methods, depending on the provider:  DB.User.loginWithGoogle(clientID, options).then((user) => {\n    //logged in successfully\n    db.User.me == user;\n});\n// Same for\nDB.User.loginWithFacebook(...)\nDB.User.loginWithGitHub(...)\nDB.User.loginWithTwitter(...)\nDB.User.loginWithLinkedIn(...)  The login call returns a promise and opens a new window showing the provider-specific login page.\nThe promise is resolved with the logged in user, once the login in the new window is completed.\nThe OAuth login does not distinguish between registration and login, so you don't have to worry about whether a user is already registered or not.  In the  options  passed to the login you can configure the OAuth scope  among others .\nThe scope defines what data is shared by the OAuth provider.\nOn registration the username is set to the email address if it's in the allowed scope. Otherwise a  uuid  is used.  Note:  For the login to work despite popup blockers the call needs to be made on response to a user interaction,\ne.g. after a click on the sign-in button. Also, an OAuth login will be aborted after 5 minutes of inactivity. The timeout can be changed with the timeout option.",
            "title": "Login &amp; Registration"
        },
        {
            "location": "/topics/user-management/#customize-login-registration",
            "text": "To customize the login and registration behavior you can simply create a Baqend module named  oauth.[PROVIDER] , which is called after the user is logged in (or registered).\nIn this module you can access the logged in user and a data object containing the OAuth token as well as the user information shared by the OAuth provider.\nThe token can be used to directly do further API calls or save the token for later use.  As an example, if you like to edit the OAuth login for google, create the Baqend module  oauth.google . The module will be called after the user is successfully authorized:  exports.call = function(db, data, req) {\n    db.User.me // the unresolved user object of the created or logged in user\n\n    // data contains the profile data send by the OAuth provider\n    data.id // The OAuth unique user id\n    data.access_token // The OAuth users API token\n    data.email // The users email if the required scope was requested by the client\n};  The following table lists more information on what data can be shared by the OAuth providers:\n  \n   \n     Provider \n     Profile documentation \n   \n   \n     google \n     \n      Just returns the email per default. \n      Visit  OAuth 2.0 Scopes for Google APIs  for a \n      complete list of supported scopes.\n     \n   \n   \n     facebook \n     Returns the content of the \n     https://graph.facebook.com/v2.4/me  resource \n   \n   \n     github \n     Returns the  authenticated user profile \n   \n   \n     twitter \n     Just returns the  access_token . An Email address can't be queried with the twitter API. \n   \n   \n     linkedin \n     \n      Returns the content of the \n       https://api.linkedin.com/v1/people/~?format=json  resource.\n     \n          Note:  The returned properties depend on the requested scope.",
            "title": "Customize Login &amp; Registration"
        },
        {
            "location": "/topics/user-management/#oauth-login-via-redirect",
            "text": "In some cases, it may be desirable to use the OAuth authorization without opening a new window,\ne.g. when cross-window communication is unavailable because of a missing  localStorage  object.  To use the login via redirect, you need to set a redirect parameter when calling the particular login method.\nIn this case, the SDK does not return the user object, but creates a unique token and redirects to the specified redirect URL.\nYour site will be closed and the provider login will open instead.  //Set redirect parameter in loginOption\nloginOption = {'redirect': 'http://.../yourRedirectPage'};\n\n//call SDK method with loginOption\nDB.User.loginWithGoogle(clientID, loginOption).then(function(user) {\n    ...\n});  After communicating with the OAuth provider, the unique token is sent as a query parameter to the specified redirect page.\nIn case of a failure, the particular error message is sent instead.\nThe following table lists more information of all possible query parameters:  \n   \n     Parameter \n     Meaning \n   \n   \n     token \n     \n      A unique token to identify the user object (in case of success)\n     \n   \n   \n     loginOption \n     The specified login options (in case of success) \n   \n   \n     errorMessage \n     \n        A url-encoded error message (in case of failure)\n     \n     In case of success, you can call the following SDK method with the unique token and the specified login options\nas parameters to login the user.  DB.User.loginWithToken(token, options).then(function(user) {\n    //logged in successfully\n    db.User.me == user;\n});  The login call returns a promise which is resolved with the logged in user. The OAuth login does not distinguish between\nregistration and login, so you don't have to worry about whether a user is already registered or not.  Note:  For the login via redirect to work, ensure to register all valid redirect URLs\n(e.g. 'http://.../yourRedirectPage') in the \"Authorized Domains\" section of your dashboard settings.",
            "title": "OAuth Login via Redirect"
        },
        {
            "location": "/topics/baqend-code/",
            "text": "Baqend Code\n\n\nBaqend Code Handlers and Modules are JavaScript (Node.js) functions that can be defined in the dashboard and get \nevaluated on the server side. They come in handy when you need to enforce rules and cannot trust clients.\n\n\nHandlers\n\n\nWith handlers you are able to intercept and modify CRUD operations sent by clients. To register a handler, open the\nhandler page of a class on the dashboard. There are four tabs, one for each of the three basic data manipulation \noperations and onValidate for easily validation. Each tab has an empty function template that will be called before \nexecuting the operation. Here you can perform secure validations or execute additional business logic.\n\n\nonValidate\n\n\nonValidate gets called before an insert or update operation. It is a lightweight method to validate field values.\nThe function is propagated into the client-side Baqend SDK and can be called on the client to validate inputs without\nrewriting the validation logic. The validation library \nvalidatorJs\n helps \nkeeping validation simple and readable. The onValidate method gets a validator object for each field of the entity, \nwhich keeps all available validation methods.\n\n\nfunction onValidate(username, email) {\n username.isLength(3, 15);\n //An error messages can be passed as first argument\n email.isEmail('The email is not valid') \n}\n\n\n\n\nTo validate objects on the client device call \nobject.validate()\n in your application. It returns a result object \ncontaining the validation information.\n\n\nuser.username = \"john.doe@example.com\";\nvar result = user.validate();\nif (result.isValid) {\n  //true if all fields are valid\n} \n\nvar emailResult = result.fields.email;\nif (!emailResult.isValid) {\n  //if the email is not valid, the errors can be retrieved from the error array\n  console.log(emailResult.errors[0]) //'The email is not valid'\n}\n\n\n\n\nIt is also possible to write custom validators. You can use the \nis\n validator the write custom validators:\n\n\nfunction onValidate(password, passwordRepeat) {\n password.is('The passwords does not match', function(value) {\n   return value != passwordRepeat.value; \n }); \n}\n\n\n\n\nuser.password = \"mySecretPassword\";\nuser.passwordRepeat = \"mySecretPasswort\"\nvar result = user.validate();\n\nvar passwordResult = result.fields.password;\nif (!passwordResult.isValid) {\n  //if the email is not valid, the errors can be retrieved from the error array\n  console.log(passwordResult.errors[0]) //'The passwords does not match'\n}\n\n\n\n\nonInsert and onUpdate\n\n\nIf you need complex logic or your validation depends on other objects use the onUpdate and/or onInsert handler. The \nhandler's this object as well as the second argument are the object which is inserted or updated. All attributes can be \nread and manipulated through normal property access. The requesting user can be retrieved through \ndb.User.me\n. \nInside Baqend Code the user is an unresolved object just like all other \nreferenced objects. If you need to read or manipulate attributes, \n.load()\n the user first. Consider for example the \ncase of maintaining the total time spent on a todo in a dedicated field (e.g. for sorting):\n\n\nexports.onUpdate = function(db, obj) {\n  if (obj.done) {\n    //ensure that you always return promises of asynchronous calls, \n    //otherwise errors will not abort the update operation\n    return db.User.me.load().then(function(user) {\n      obj.activities.forEach(function(activity) {\n        user.workingTime += activity.end.getTime() - activity.start.getTime();\n      });\n      return user.save();\n    });\n  }\n}\n\n\n\n\nSince its possible to reactivate finished tasks, we might want to check if we need to decrease the counter. This is only\nnecessary if the last status of the Todo object was done. To get the state of the object before the current update \n(before image) use \ndb.load(objectID)\n. \nobj.load()\n on the other hand would refresh the state of object currently \nunder update to the previous state.\n\n\nexports.onUpdate = function(db, obj) {\n  return db.Todo.load(obj.id).then(function(oldTodo) {\n    if (oldTodo.done != obj.done) {\n      return db.User.me.load().then(function(user) {\n        var totalTime = obj.activities.reduce(function(totalTime, activity) {\n          return totalTime += activity.end.getTime() - activity.start.getTime();\n        }, 0);\n\n        if (obj.done) {\n          user.workingTime += totalTime;\n        } else {\n          user.workingTime -= totalTime;\n        }\n\n        return user.save();\n      }\n    }\n  }\n}\n\n\n\n\nIt is also possible to change the actual object in the \nonInsert\n and \nonUpdate\n handler before it is saved. While \nissuing the insert/update from the SDK you will not get this changes back by default. To get the changed data back, use \nthe refresh flag of the \nsave()\n, \ninsert()\n or \nupdate()\n method.\n\n\n//the Baqend handler\nexports.onUpdate = function(db, obj) {\n  obj.counter++;\n}\n\n\n\n\n//on client side without refresh\nDB.Test.load('546c6-a...').then(function(obj) {\n  return obj.save();\n}).then(function(obj) {\n  //obj.counter == 0\n});\n\n//on client side with refresh\nDB.Test.load('546c6-a...').then(function(obj) {\n  return obj.save({refresh: true});\n}).then(function(obj) {\n  //obj.counter == 1\n});\n\n\n\n\nNote:\n Inside Baqend Code data operations (e.g. \nuser.save()\n) have the access rights of the user starting the \nrequest enhanced by an additional \nnode\n role. Calls to Baqend originating from handlers will not trigger another \n\nonUpdate(db)\n call. See \nPredefined Roles\n for more details.\n\n\n\nonDelete\n\n\nThe onDelete handler is called with an empty object only containing the id of the deleted object. The method can\nfor instance be used to log information or delete related objects. \n\n\nexports.onDelete = function(db, obj) {\n  obj.id //the id of the object which will be deleted\n  obj.name //null\n}\n\n\n\n\nAll four handlers are \nbefore\n-operation handlers. Be aware that they are called after the class level permissions are \nchecked, but before object level permissions were validated. Thus, making changes to other objects inside handlers \nshould be treated with care: these operations could succeed while the original operation might fail due to missing \nobject access rights. An elegant way to simplify such cases is the use of \nafter\n-handlers, one of our \nUpcoming Features\n.\n\n\nModules\n\n\nBaqend Modules are JavaScript modules stored in Baqend. They can be called by \nclients and be imported by other modules and handlers. Only modules that export a \ncall\n method can be called by \nclients directly. The Baqend module will get the DB object as the first, data sent by the client as \nthe second and the \nrequest\n object as the third parameter.\n\n\nLet's create a simple invite system. To invite a user to an event, the invitation is added to this/her invite list. \nThis process needs to be encapsulated in a Baqend modules as it requires write permissions on other users.\n\n\n//invite\nexports.call = function(db, data, req) {\n  return db.User.find()\n    .equal('username', data.username)\n    .singleResult(function(user) {\n      user.invites.add(data.invite);\n      return user.save();\n    });\n};\n\n\n\n\nThe \nbody\n parameter passed into the function contains the request payload, i.e. the decoded query parameters of a GET request or the parsed body of a \nPOST\n request.\n\n\nOn the client side, we can now invite a user by its username to our event by invoking the Baqend invite method. Baqend \nmodules can be invoked using \nget\n for reading data and with \npost\n to modify data. \n\n\n\n\nwith \nget\n data is sent with url query parameters of an HTTP GET request (URL size limit: 2KB)\n\n\nwith \npost\n data is sent in the body of an HTTP POST request\n\n\n\n\nDB.modules.post('invite', {email: 'peter@example.com', invite: 'My new event'})\n  .then(function() {\n    //invite was send successfully\n  });\n\n\n\n\nBaqend modules are also useful for sending messages like E-mails, Push notifications and SMS.\n\n\nAborting requests\n\n\nTo abort an insert, update, delete or Baqend module invocation, handlers as well as modules may throw an \n\nAbort\n exception.\n\n\nexports.onDelete = function(db, obj) {\n  throw new Abort('Delete not allowed.', {id: obj.id});\n}\n\n\n\n\nThe Abort exception aborts the request. The optional \ndata parameter transfers additional JSON data back to the client. The data can be retrieved from the error \nobject passed to the reject handler of the promise.\n\n\nobj.delete().then(function() {\n  //object was deleted successfully  \n}, function(e) {\n  e.message //The error message\n  e.data.id //The data sent backed to the client\n});\n\n\n\n\nAdvanced request handling\n\n\nIn addition to the simplified \ncall(db, obj, req)\n method we provide an advanced way to handle requests within Baqend modules.\nYou can implement GET and POST request handling separately by implementing a equivalent \nget(db, req, res)\n and \n\npost(db, req, res)\n. \n\n\nNote:\n that the second parameter is the request object and the third parameter is an express \n\nresponse\n object.\n\n\n\nWith the request object, you can handle form submissions via get or post\n\n\n//Handle get submissions\nexports.get = function(db, req, res) {\n  //access url get parameters\n  var myParam = req.query.myParam;\n\n  res.json(req.query);\n};\n\n//Handle post submissions\nexports.post = function(db, req, res) {\n  //access form post parameters\n  var myParam = req.body.myParam;\n\n  res.json(req.body);\n};\n\n\n\n\nWith the response object, you can send additional response headers and have a better control over the content which will \nbe send back. You can use the complete express API to handle the actual request.\n\n\nexports.get = function(db, req, res) {\n  var myParam = req.query.myParam;\n\n  if(db.User.me) {\n    //we are logged in\n    return db.User.me.load().then(function() {\n      //use the powerful express helpers\n      res.status(200);\n      res.json({\n        myParam: myParam, \n        token: sig(myParam, db.User.me),\n        userId: db.User.me.id\n      });\n    });\n  } else {\n    //we are anonymous, lets redirect the user to a login page\n    res.redirect('http://myApp.baqend.com/login');\n    res.send();\n  }\n};\n\n\n\n\nIt is important that you send the content back with one of the express \nres.send()\n helpers. Otherwise the response will \nnot be send back to the client. In addition ensure that you return a \npromise\n when you make asynchronous calls within \nyour Baqend module, otherwise the request will be aborted with an error!\n\n\nHandling binary data\n\n\nAs a part of the advanced request handling, it is also possible to upload and download binary files in Baqend modules.\n\n\nTo send binary data to your Baqend module, you can specify the 'requestType' option.\nWith the 'responseType' option you can receive binary data in the specified type from your Baqend module.\nThis works similar to the file API and you can use all the listed \nfile types\n as 'requestType' and 'responseType' too.\n\n\nvar svgBase64 = 'PHN2ZyB4bWxucz0...';\nvar mimeType = 'image/svg+xml';\n\nreturn db.modules.post(bucket, svgBase64, {\n  requestType: 'base64',    //Sending the file as a base64 string \n  mimeType: mimeType,       //Setting the mimeType as Content-Type\n  responseType: 'data-url'  //Receiving the data as a data-url\n}).then(function(result) {\n  result // 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0...'\n});\n\n\n\n\nTo handle the binary files in a Baqend module, you must process the incoming raw stream directly. The incoming request\nobject is a node.js \nReadable Stream\n and you will receive \nthe incoming raw data as \nBuffer\n chunks.\n\n\nTo send binary data back to the client, you should set the Content-Type of the response data with the express \n\nres.type()\n method and send the data afterwards.\n\n\nIf you have completed the request handling you need to resolve the previously returned promise to signal the completion \nof the request handling.\n\n\n//this simple Baqend handler just sends the uploaded file back to the client\nexports.post = function(db, req, res) {\n  return new Promise(function(success) {\n    //node gives the file stream as chunks of Buffer \n    var chunks = []; \n    req.on('data', function(chunk) {\n      chunks.push(chunk);\n    });\n    req.on('end', function() {\n      var requestData = Buffer.concat(chunks);\n      // do something with the requestData\n      res.status(200)\n          .type(req.get('Content-Type'))\n          .send(requestData); //sending some data back\n      success();\n    });\n  });\n};\n\n\n\n\nHandling Files\n\n\nIn the Baqend Code you can use the same \nFile API\n as from your client. For Baqend Code we, however, support two additional file content formats, namely \nstream\n and \nbuffer\n.\n\n\nWith the \nstream\n format you can for example stream data through your Baqend Code into the database without buffering it, as the following example shows:\n\n\nvar http = require('https');\n\nexports.call = function(db, data, req) {\n  return new Promise((success, error) => {\n    var httpReq = http.request({\n      method: 'GET',\n      hostname: data.host,\n      path: data.path\n    }, success);\n\n    httpReq.on('error', error);\n    httpReq.end();\n  }).then((stream) => {\n    var file = new db.File({parent: '/www', name: data.name});\n    var type = stream.headers['content-type'];\n    var size = stream.headers['content-length'];\n    return file.upload({data: stream, type: 'stream', mimeType: type, size: size});\n  });\n};\n\n\n\n\nThis example shows a Baqend Module that sends an HTTP request (\nhttpReq\n) to download whatever is referenced\nby the URL (\ndata.host\n and \ndata.path\n). We take the \nstream\n from this download and\nupload a file with this content into the \n/www\n root folder. This happens without buffering the downloaded\ndata as it is streamed right through to the database.\n\n\nNote:\n If you stream the file content to the server you always need to specify the file size as shown in the example.\n\n\n\nImporting code and libraries\n\n\nBaqend code constitutes CommonJS modules and can require other modules and external libraries. \n\n\nBaqend modules not exposing a call method can't be called by the client but may be required by \nother modules and handlers.\n\n\n//myModule\nexports.updateMe = function(db) {\n  return db.User.me.load().then(function(user) {\n    user.visits++;\n    return user.save();\n  });\n}; \n\n\n\n\nBaqend modules are imported through relative require calls and external libraries through absolute \nrequire calls.\n\n\n//require another Baqend module\nvar myModule = require('./myModule');\n//require an update (or insert, delete, validate) handler from 'MyClass'\nvar updateHandler = require('./MyClass/update');\n//require the http core module for external http requests\nvar http = require('http');\nexports.call = function(db, data, req) {\n  return myModule.updateMe(db);\n}; \n\n\n\n\nIn Baqend Handlers modules are required from the parent folder. \n\n\n//onUpdate              \n//Require the module form the parent folder\nvar myModule = require('../myModule');       \nexports.onUpdate = function(db, obj) {\n  return myModule.updateMe(db);\n}; \n\n\n\n\nThe following additional libraries can always be required in Baqend code:\n\n\n\n\nhttp\n - Node.js http core library\n\n\nhttps\n - Node.js https core library \n\n\nquerystring\n - Node.js core querystring parsing and serialization library\n\n\ncrypto\n - Node.js core crypto api offers a way of encapsulating secure credentials \n\n\nbaqend\n - The Baqend SDK\n\n\nexpress\n - HTTP server\n\n\ntwilio\n - APIs for Text Messaging, VoIP & Voice in the Cloud \n\n\nlwip\n - a Light Weight Image Processor for NodeJS\n\n\nnode-mailjet\n \nAPI v3\n Official Mailjet API v3 NodeJS wrapper \n\n\n\n\nNote:\n If you need custom Node.js modules from npm, please contact us via \nsupport@baqend.com\n and we will add them.\n\n\n\nPermissions\n\n\nBaqend Code is always executed with the permissions of the requesting client. If the requesting user is not logged in, \nall requests made from Baqend code are anonymous. Both anonymous and authenticated invocations are enhanced by the node \nrole. This predefined role can be used in class and object ACLs to grant Baqend code additional access rights. \nIn addition there are some Baqend API resources which can only be accessed by the admin or the node role.",
            "title": "Baqend Code"
        },
        {
            "location": "/topics/baqend-code/#baqend-code",
            "text": "Baqend Code Handlers and Modules are JavaScript (Node.js) functions that can be defined in the dashboard and get \nevaluated on the server side. They come in handy when you need to enforce rules and cannot trust clients.",
            "title": "Baqend Code"
        },
        {
            "location": "/topics/baqend-code/#handlers",
            "text": "With handlers you are able to intercept and modify CRUD operations sent by clients. To register a handler, open the\nhandler page of a class on the dashboard. There are four tabs, one for each of the three basic data manipulation \noperations and onValidate for easily validation. Each tab has an empty function template that will be called before \nexecuting the operation. Here you can perform secure validations or execute additional business logic.",
            "title": "Handlers"
        },
        {
            "location": "/topics/baqend-code/#onvalidate",
            "text": "onValidate gets called before an insert or update operation. It is a lightweight method to validate field values.\nThe function is propagated into the client-side Baqend SDK and can be called on the client to validate inputs without\nrewriting the validation logic. The validation library  validatorJs  helps \nkeeping validation simple and readable. The onValidate method gets a validator object for each field of the entity, \nwhich keeps all available validation methods.  function onValidate(username, email) {\n username.isLength(3, 15);\n //An error messages can be passed as first argument\n email.isEmail('The email is not valid') \n}  To validate objects on the client device call  object.validate()  in your application. It returns a result object \ncontaining the validation information.  user.username = \"john.doe@example.com\";\nvar result = user.validate();\nif (result.isValid) {\n  //true if all fields are valid\n} \n\nvar emailResult = result.fields.email;\nif (!emailResult.isValid) {\n  //if the email is not valid, the errors can be retrieved from the error array\n  console.log(emailResult.errors[0]) //'The email is not valid'\n}  It is also possible to write custom validators. You can use the  is  validator the write custom validators:  function onValidate(password, passwordRepeat) {\n password.is('The passwords does not match', function(value) {\n   return value != passwordRepeat.value; \n }); \n}  user.password = \"mySecretPassword\";\nuser.passwordRepeat = \"mySecretPasswort\"\nvar result = user.validate();\n\nvar passwordResult = result.fields.password;\nif (!passwordResult.isValid) {\n  //if the email is not valid, the errors can be retrieved from the error array\n  console.log(passwordResult.errors[0]) //'The passwords does not match'\n}",
            "title": "onValidate"
        },
        {
            "location": "/topics/baqend-code/#oninsert-and-onupdate",
            "text": "If you need complex logic or your validation depends on other objects use the onUpdate and/or onInsert handler. The \nhandler's this object as well as the second argument are the object which is inserted or updated. All attributes can be \nread and manipulated through normal property access. The requesting user can be retrieved through  db.User.me . \nInside Baqend Code the user is an unresolved object just like all other \nreferenced objects. If you need to read or manipulate attributes,  .load()  the user first. Consider for example the \ncase of maintaining the total time spent on a todo in a dedicated field (e.g. for sorting):  exports.onUpdate = function(db, obj) {\n  if (obj.done) {\n    //ensure that you always return promises of asynchronous calls, \n    //otherwise errors will not abort the update operation\n    return db.User.me.load().then(function(user) {\n      obj.activities.forEach(function(activity) {\n        user.workingTime += activity.end.getTime() - activity.start.getTime();\n      });\n      return user.save();\n    });\n  }\n}  Since its possible to reactivate finished tasks, we might want to check if we need to decrease the counter. This is only\nnecessary if the last status of the Todo object was done. To get the state of the object before the current update \n(before image) use  db.load(objectID) .  obj.load()  on the other hand would refresh the state of object currently \nunder update to the previous state.  exports.onUpdate = function(db, obj) {\n  return db.Todo.load(obj.id).then(function(oldTodo) {\n    if (oldTodo.done != obj.done) {\n      return db.User.me.load().then(function(user) {\n        var totalTime = obj.activities.reduce(function(totalTime, activity) {\n          return totalTime += activity.end.getTime() - activity.start.getTime();\n        }, 0);\n\n        if (obj.done) {\n          user.workingTime += totalTime;\n        } else {\n          user.workingTime -= totalTime;\n        }\n\n        return user.save();\n      }\n    }\n  }\n}  It is also possible to change the actual object in the  onInsert  and  onUpdate  handler before it is saved. While \nissuing the insert/update from the SDK you will not get this changes back by default. To get the changed data back, use \nthe refresh flag of the  save() ,  insert()  or  update()  method.  //the Baqend handler\nexports.onUpdate = function(db, obj) {\n  obj.counter++;\n}  //on client side without refresh\nDB.Test.load('546c6-a...').then(function(obj) {\n  return obj.save();\n}).then(function(obj) {\n  //obj.counter == 0\n});\n\n//on client side with refresh\nDB.Test.load('546c6-a...').then(function(obj) {\n  return obj.save({refresh: true});\n}).then(function(obj) {\n  //obj.counter == 1\n});  Note:  Inside Baqend Code data operations (e.g.  user.save() ) have the access rights of the user starting the \nrequest enhanced by an additional  node  role. Calls to Baqend originating from handlers will not trigger another  onUpdate(db)  call. See  Predefined Roles  for more details.",
            "title": "onInsert and onUpdate"
        },
        {
            "location": "/topics/baqend-code/#ondelete",
            "text": "The onDelete handler is called with an empty object only containing the id of the deleted object. The method can\nfor instance be used to log information or delete related objects.   exports.onDelete = function(db, obj) {\n  obj.id //the id of the object which will be deleted\n  obj.name //null\n}  All four handlers are  before -operation handlers. Be aware that they are called after the class level permissions are \nchecked, but before object level permissions were validated. Thus, making changes to other objects inside handlers \nshould be treated with care: these operations could succeed while the original operation might fail due to missing \nobject access rights. An elegant way to simplify such cases is the use of  after -handlers, one of our  Upcoming Features .",
            "title": "onDelete"
        },
        {
            "location": "/topics/baqend-code/#modules",
            "text": "Baqend Modules are JavaScript modules stored in Baqend. They can be called by \nclients and be imported by other modules and handlers. Only modules that export a  call  method can be called by \nclients directly. The Baqend module will get the DB object as the first, data sent by the client as \nthe second and the  request  object as the third parameter.  Let's create a simple invite system. To invite a user to an event, the invitation is added to this/her invite list. \nThis process needs to be encapsulated in a Baqend modules as it requires write permissions on other users.  //invite\nexports.call = function(db, data, req) {\n  return db.User.find()\n    .equal('username', data.username)\n    .singleResult(function(user) {\n      user.invites.add(data.invite);\n      return user.save();\n    });\n};  The  body  parameter passed into the function contains the request payload, i.e. the decoded query parameters of a GET request or the parsed body of a  POST  request.  On the client side, we can now invite a user by its username to our event by invoking the Baqend invite method. Baqend \nmodules can be invoked using  get  for reading data and with  post  to modify data.    with  get  data is sent with url query parameters of an HTTP GET request (URL size limit: 2KB)  with  post  data is sent in the body of an HTTP POST request   DB.modules.post('invite', {email: 'peter@example.com', invite: 'My new event'})\n  .then(function() {\n    //invite was send successfully\n  });  Baqend modules are also useful for sending messages like E-mails, Push notifications and SMS.",
            "title": "Modules"
        },
        {
            "location": "/topics/baqend-code/#aborting-requests",
            "text": "To abort an insert, update, delete or Baqend module invocation, handlers as well as modules may throw an  Abort  exception.  exports.onDelete = function(db, obj) {\n  throw new Abort('Delete not allowed.', {id: obj.id});\n}  The Abort exception aborts the request. The optional \ndata parameter transfers additional JSON data back to the client. The data can be retrieved from the error \nobject passed to the reject handler of the promise.  obj.delete().then(function() {\n  //object was deleted successfully  \n}, function(e) {\n  e.message //The error message\n  e.data.id //The data sent backed to the client\n});",
            "title": "Aborting requests"
        },
        {
            "location": "/topics/baqend-code/#advanced-request-handling",
            "text": "In addition to the simplified  call(db, obj, req)  method we provide an advanced way to handle requests within Baqend modules.\nYou can implement GET and POST request handling separately by implementing a equivalent  get(db, req, res)  and  post(db, req, res) .   Note:  that the second parameter is the request object and the third parameter is an express  response  object.  With the request object, you can handle form submissions via get or post  //Handle get submissions\nexports.get = function(db, req, res) {\n  //access url get parameters\n  var myParam = req.query.myParam;\n\n  res.json(req.query);\n};\n\n//Handle post submissions\nexports.post = function(db, req, res) {\n  //access form post parameters\n  var myParam = req.body.myParam;\n\n  res.json(req.body);\n};  With the response object, you can send additional response headers and have a better control over the content which will \nbe send back. You can use the complete express API to handle the actual request.  exports.get = function(db, req, res) {\n  var myParam = req.query.myParam;\n\n  if(db.User.me) {\n    //we are logged in\n    return db.User.me.load().then(function() {\n      //use the powerful express helpers\n      res.status(200);\n      res.json({\n        myParam: myParam, \n        token: sig(myParam, db.User.me),\n        userId: db.User.me.id\n      });\n    });\n  } else {\n    //we are anonymous, lets redirect the user to a login page\n    res.redirect('http://myApp.baqend.com/login');\n    res.send();\n  }\n};  It is important that you send the content back with one of the express  res.send()  helpers. Otherwise the response will \nnot be send back to the client. In addition ensure that you return a  promise  when you make asynchronous calls within \nyour Baqend module, otherwise the request will be aborted with an error!",
            "title": "Advanced request handling"
        },
        {
            "location": "/topics/baqend-code/#handling-binary-data",
            "text": "As a part of the advanced request handling, it is also possible to upload and download binary files in Baqend modules.  To send binary data to your Baqend module, you can specify the 'requestType' option.\nWith the 'responseType' option you can receive binary data in the specified type from your Baqend module.\nThis works similar to the file API and you can use all the listed  file types  as 'requestType' and 'responseType' too.  var svgBase64 = 'PHN2ZyB4bWxucz0...';\nvar mimeType = 'image/svg+xml';\n\nreturn db.modules.post(bucket, svgBase64, {\n  requestType: 'base64',    //Sending the file as a base64 string \n  mimeType: mimeType,       //Setting the mimeType as Content-Type\n  responseType: 'data-url'  //Receiving the data as a data-url\n}).then(function(result) {\n  result // 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0...'\n});  To handle the binary files in a Baqend module, you must process the incoming raw stream directly. The incoming request\nobject is a node.js  Readable Stream  and you will receive \nthe incoming raw data as  Buffer  chunks.  To send binary data back to the client, you should set the Content-Type of the response data with the express  res.type()  method and send the data afterwards.  If you have completed the request handling you need to resolve the previously returned promise to signal the completion \nof the request handling.  //this simple Baqend handler just sends the uploaded file back to the client\nexports.post = function(db, req, res) {\n  return new Promise(function(success) {\n    //node gives the file stream as chunks of Buffer \n    var chunks = []; \n    req.on('data', function(chunk) {\n      chunks.push(chunk);\n    });\n    req.on('end', function() {\n      var requestData = Buffer.concat(chunks);\n      // do something with the requestData\n      res.status(200)\n          .type(req.get('Content-Type'))\n          .send(requestData); //sending some data back\n      success();\n    });\n  });\n};",
            "title": "Handling binary data"
        },
        {
            "location": "/topics/baqend-code/#handling-files",
            "text": "In the Baqend Code you can use the same  File API  as from your client. For Baqend Code we, however, support two additional file content formats, namely  stream  and  buffer .  With the  stream  format you can for example stream data through your Baqend Code into the database without buffering it, as the following example shows:  var http = require('https');\n\nexports.call = function(db, data, req) {\n  return new Promise((success, error) => {\n    var httpReq = http.request({\n      method: 'GET',\n      hostname: data.host,\n      path: data.path\n    }, success);\n\n    httpReq.on('error', error);\n    httpReq.end();\n  }).then((stream) => {\n    var file = new db.File({parent: '/www', name: data.name});\n    var type = stream.headers['content-type'];\n    var size = stream.headers['content-length'];\n    return file.upload({data: stream, type: 'stream', mimeType: type, size: size});\n  });\n};  This example shows a Baqend Module that sends an HTTP request ( httpReq ) to download whatever is referenced\nby the URL ( data.host  and  data.path ). We take the  stream  from this download and\nupload a file with this content into the  /www  root folder. This happens without buffering the downloaded\ndata as it is streamed right through to the database.  Note:  If you stream the file content to the server you always need to specify the file size as shown in the example.",
            "title": "Handling Files"
        },
        {
            "location": "/topics/baqend-code/#importing-code-and-libraries",
            "text": "Baqend code constitutes CommonJS modules and can require other modules and external libraries.   Baqend modules not exposing a call method can't be called by the client but may be required by \nother modules and handlers.  //myModule\nexports.updateMe = function(db) {\n  return db.User.me.load().then(function(user) {\n    user.visits++;\n    return user.save();\n  });\n};   Baqend modules are imported through relative require calls and external libraries through absolute \nrequire calls.  //require another Baqend module\nvar myModule = require('./myModule');\n//require an update (or insert, delete, validate) handler from 'MyClass'\nvar updateHandler = require('./MyClass/update');\n//require the http core module for external http requests\nvar http = require('http');\nexports.call = function(db, data, req) {\n  return myModule.updateMe(db);\n};   In Baqend Handlers modules are required from the parent folder.   //onUpdate              \n//Require the module form the parent folder\nvar myModule = require('../myModule');       \nexports.onUpdate = function(db, obj) {\n  return myModule.updateMe(db);\n};   The following additional libraries can always be required in Baqend code:   http  - Node.js http core library  https  - Node.js https core library   querystring  - Node.js core querystring parsing and serialization library  crypto  - Node.js core crypto api offers a way of encapsulating secure credentials   baqend  - The Baqend SDK  express  - HTTP server  twilio  - APIs for Text Messaging, VoIP & Voice in the Cloud   lwip  - a Light Weight Image Processor for NodeJS  node-mailjet   API v3  Official Mailjet API v3 NodeJS wrapper    Note:  If you need custom Node.js modules from npm, please contact us via  support@baqend.com  and we will add them.",
            "title": "Importing code and libraries"
        },
        {
            "location": "/topics/baqend-code/#permissions",
            "text": "Baqend Code is always executed with the permissions of the requesting client. If the requesting user is not logged in, \nall requests made from Baqend code are anonymous. Both anonymous and authenticated invocations are enhanced by the node \nrole. This predefined role can be used in class and object ACLs to grant Baqend code additional access rights. \nIn addition there are some Baqend API resources which can only be accessed by the admin or the node role.",
            "title": "Permissions"
        },
        {
            "location": "/topics/push/",
            "text": "Push Notifications\n\n\nBaqend provides the ability to send push notifications to end users devices. Before you can send a push notification you \nmust first register the Device of the User. Registered devices can then later be used in Baqend Code to send push\nnotifications to. \n\n\nNote:\n Currently Baqend supports IOS and Android devices, support for more platforms are planed. \n\n\n\nSetup Push\n\n\nApple Push Notifcation Service (APNS)\n\n\nTo enable push notifications for iOS devices you have to upload your production or sandbox certificate in the\nBaqend settings view of your app. Please upload your certificate as a \np12\n-file without any password protection. Otherwise it's\nnot possible for Baqend to use it.\n\n\nThe sandbox certificate is needed, when testing the app directly from Xcode. If the app has been published to the app\nstore or should be tested in \nTestFlight\n, you must upload your production certificate. It's currently not possible\nto use both certificate types at the same time.\n\n\nThis tutorial\n\nshow hows to enabled push notification in your app and how to export your certificate as a \np12\n-file.\n\n\nGoogle Cloud Messaging (GCM)\n\n\nTo enabled push notifications for Android devices Baqend needs your GCM API key. The key can be saved in the Baqend settings\nview of your app.\n\n\nTo get your API key browse to the \nGoogle Developers Console\n, open\n\nEnable and manage APIs\n, create or chose your app, click on \nCredentials\n on the left side. If you already created\nan server key, copy it from the list and save it at the Baqend settings view of your app, otherwise click on\n\nCreate credentials\n -> \nAPI key\n -> \nServer key\n to create a new api key. It's important, that the field\n\nAccept requests from these server IP addresses\n is empty.\n\n\nIn your app itself you have to use the \nsender ID\n and not the server API key. The \nsender ID\n is called \nproject number\n\nin the Google Developers Console.\n\n\nDevice Registration\n\n\nA registered device is represented in Baqend by the Device class. The Device class contains the \ndeviceOs\n field which\ncontains the platform name of the registered device, currently \nAndroid\n or \nIOS\n. To register a new device you must \nfirst obtain a device token with your used mobile framework. With the token you can register the device on Baqend.\n\n\nIt is not required to register a Device every time your App initialize. The SDK provides you a flag, that indicates if \nthe Device is already registered. Therefore you must only request a device token if the device is currently not \nregistered:\n\n\nDB.ready().then(function() {\n    if (!DB.Device.isRegistered) {\n        //helper method which fetch a new device token, using your favor framework \n        var deviceToken = requestDeviceToken();\n\n        DB.Device.register('IOS', deviceToken);\n    }\n});\n\n\n\n\nThe device class can be extended with custom fields like any other class in Baqend. This allows you to save additional\ndata with your device, which you can later use to query the devices that should receive a push notification. To persist \nadditional data with your device while registering it, you can pass a Device object to the registration method.\n\n\nA common use case is to save the user with a device, that allows you to send a push notification to the users device \nlater on.\n\n\nvar device = new DB.Device({\n    \"user\": DB.User.me\n});\n\nDB.Device.register('IOS', deviceToken, device);\n\n\n\n\nPushMessage\n Class\n\n\nTo send a push notification, the SDK provides a \nPushMessage\n class which can be used to send a message to one or more \ndevices. In addition to the message itself a \nPushMessage\n can transport additional information to the end users device.\n\n\n\n  \n\n    \nName\n\n    \nType\n\n    \nNotes\n\n  \n\n  \n\n    \nmessage\n\n    \nString\n\n    \nThe optional message to display\n\n  \n\n  \n\n    \nsubject\n\n    \nString\n\n    \nThe headline of the push message\n\n  \n\n  \n\n    \nsound\n\n    \nString\n\n    \nsound The filename of the sound file. The device uses this file as the notification sound.\n\n  \n\n  \n\n    \nbadge\n\n    \nNumber\n\n    \nThe badge count, displayed on the apps icon, only supported by IOS\n\n  \n\n  \n\n    \ndata\n\n    \nObject\n\n    \nAdditional json data send directly to your app\n\n  \n\n\n    \n\n\nSending Push\n\n\nPush notifications can only be sent within \nBaqend code\n. To send a push notification to one or more devices, you must\nfirst obtain the desired device ids. Therefore you can use the additional data stored in the device object to query those, \nor can save the device reference in another object.\n\n\n/**\n * The Baqend code sends a push notification to the given list of users.\n * Therefore the extended device class contains a user field.\n * @param {Array<String>} data.users A list of user ids\n * @param {String} data.message The message to push\n */\nexports.call = function(db, data) {\n  var users = data.users;\n  var message = data.message;\n  var subject = data.subject;\n\n  return db.Device.find()\n    .in('user', users)\n    .resultList()\n    .then(function(devices) {\n      var pushMessage = db.Device.PushMessage(devices, message, subject);\n      return db.Device.push(pushMessage);\n    });\n}",
            "title": "Push Notifications"
        },
        {
            "location": "/topics/push/#push-notifications",
            "text": "Baqend provides the ability to send push notifications to end users devices. Before you can send a push notification you \nmust first register the Device of the User. Registered devices can then later be used in Baqend Code to send push\nnotifications to.   Note:  Currently Baqend supports IOS and Android devices, support for more platforms are planed.",
            "title": "Push Notifications"
        },
        {
            "location": "/topics/push/#setup-push",
            "text": "",
            "title": "Setup Push"
        },
        {
            "location": "/topics/push/#apple-push-notifcation-service-apns",
            "text": "To enable push notifications for iOS devices you have to upload your production or sandbox certificate in the\nBaqend settings view of your app. Please upload your certificate as a  p12 -file without any password protection. Otherwise it's\nnot possible for Baqend to use it.  The sandbox certificate is needed, when testing the app directly from Xcode. If the app has been published to the app\nstore or should be tested in  TestFlight , you must upload your production certificate. It's currently not possible\nto use both certificate types at the same time.  This tutorial \nshow hows to enabled push notification in your app and how to export your certificate as a  p12 -file.",
            "title": "Apple Push Notifcation Service (APNS)"
        },
        {
            "location": "/topics/push/#google-cloud-messaging-gcm",
            "text": "To enabled push notifications for Android devices Baqend needs your GCM API key. The key can be saved in the Baqend settings\nview of your app.  To get your API key browse to the  Google Developers Console , open Enable and manage APIs , create or chose your app, click on  Credentials  on the left side. If you already created\nan server key, copy it from the list and save it at the Baqend settings view of your app, otherwise click on Create credentials  ->  API key  ->  Server key  to create a new api key. It's important, that the field Accept requests from these server IP addresses  is empty.  In your app itself you have to use the  sender ID  and not the server API key. The  sender ID  is called  project number \nin the Google Developers Console.",
            "title": "Google Cloud Messaging (GCM)"
        },
        {
            "location": "/topics/push/#device-registration",
            "text": "A registered device is represented in Baqend by the Device class. The Device class contains the  deviceOs  field which\ncontains the platform name of the registered device, currently  Android  or  IOS . To register a new device you must \nfirst obtain a device token with your used mobile framework. With the token you can register the device on Baqend.  It is not required to register a Device every time your App initialize. The SDK provides you a flag, that indicates if \nthe Device is already registered. Therefore you must only request a device token if the device is currently not \nregistered:  DB.ready().then(function() {\n    if (!DB.Device.isRegistered) {\n        //helper method which fetch a new device token, using your favor framework \n        var deviceToken = requestDeviceToken();\n\n        DB.Device.register('IOS', deviceToken);\n    }\n});  The device class can be extended with custom fields like any other class in Baqend. This allows you to save additional\ndata with your device, which you can later use to query the devices that should receive a push notification. To persist \nadditional data with your device while registering it, you can pass a Device object to the registration method.  A common use case is to save the user with a device, that allows you to send a push notification to the users device \nlater on.  var device = new DB.Device({\n    \"user\": DB.User.me\n});\n\nDB.Device.register('IOS', deviceToken, device);",
            "title": "Device Registration"
        },
        {
            "location": "/topics/push/#pushmessage-class",
            "text": "To send a push notification, the SDK provides a  PushMessage  class which can be used to send a message to one or more \ndevices. In addition to the message itself a  PushMessage  can transport additional information to the end users device.  \n   \n     Name \n     Type \n     Notes \n   \n   \n     message \n     String \n     The optional message to display \n   \n   \n     subject \n     String \n     The headline of the push message \n   \n   \n     sound \n     String \n     sound The filename of the sound file. The device uses this file as the notification sound. \n   \n   \n     badge \n     Number \n     The badge count, displayed on the apps icon, only supported by IOS \n   \n   \n     data \n     Object \n     Additional json data send directly to your app",
            "title": "PushMessage Class"
        },
        {
            "location": "/topics/push/#sending-push",
            "text": "Push notifications can only be sent within  Baqend code . To send a push notification to one or more devices, you must\nfirst obtain the desired device ids. Therefore you can use the additional data stored in the device object to query those, \nor can save the device reference in another object.  /**\n * The Baqend code sends a push notification to the given list of users.\n * Therefore the extended device class contains a user field.\n * @param {Array<String>} data.users A list of user ids\n * @param {String} data.message The message to push\n */\nexports.call = function(db, data) {\n  var users = data.users;\n  var message = data.message;\n  var subject = data.subject;\n\n  return db.Device.find()\n    .in('user', users)\n    .resultList()\n    .then(function(devices) {\n      var pushMessage = db.Device.PushMessage(devices, message, subject);\n      return db.Device.push(pushMessage);\n    });\n}",
            "title": "Sending Push"
        },
        {
            "location": "/topics/deep-loading/",
            "text": "Persistence and Deep Loading\n\n\nThe Baqend SDK internally tracks the state of all living entity instances and their attributes. If an attribute of an \nentity is changed, the entity will be marked as dirty. Only dirty entities will be send back to the Baqend while calling\n\nsave()\n or \nupdate()\n. Also the collections and embedded objects of an entity will be tracked the same way and mark the \nowning entity as dirty on modifications. The big advantage of this dirty tracking is that when you apply deep saving \nto persist object graphs, only those objects that were actually changed are transferred. This saves performance and \nbandwidth.\n\n\nDB.Todo.load('Todo1').then(function(todo) {\n  todo.save(); //will not perform a Baqend request since the object is not dirty   \n});\n\n\n\n\nDeep Loading\n\n\nAs described in the \nReferences\n chapter, references between entities will be handled differently \nfrom embedded objects or collections. The referenced objects will not be loaded with the referencing entity by default.\n\n\n//while loading the todo, the reference will be resolved to the referenced entity\nDB.Todo.load('7b2c...').then(function(firstTodo) {\n  console.log(firstTodo.name); //'My first Todo'\n  console.log(firstTodo.doNext.name); //will throw an object not available error\n});\n\n\n\n\nIn a more complex scenario you may have references in a collection. These references won't be be loaded by default \nneither.\n\n\nDB.Todo.load('7b2c...').then(function(firstTodo) {  \n  //will throw an object not available error\n  console.log(firstTodo.upComingTodos[0].name); \n});\n\n\n\n\nTo load dependant objects, you can pass the \ndepth\n option while loading the entity. The depth option allows to \nset a reference-depth which will automatically be loaded. A depth value of \n0\n (the default) just loads the entity. \n\n\nDB.Todo.load('7b2c...', {depth: 0}).then(function(firstTodo) {   \n  //will throw an object not available error\n  console.log(firstTodo.doNext.name); \n  //will still throw an object not available error\n  console.log(firstTodo.upComingTodos[0].name); \n});\n\n\n\n\nA depth value of \n1\n loads the entity and one additional level of references. This also includes references in \ncollections and embedded objects.\n\n\nDB.Todo.load('7b2c...', {depth: 1}).then(function(firstTodo) {\n  console.log(firstTodo.doNext.name); //'My second Todo'\n  console.log(firstTodo.upComingTodos[0].name); //'My second Todo'  \n  //will throw an object not available error\n  console.log(firstTodo.doNext.doNext.name); \n  //will still throw an object not available error\n  console.log(firstTodo.upComingTodos[0].upComingTodos[0].name); \n});\n\n\n\n\nSetting the depth value to \n2\n resolves the next level of references and so on. You can set the depth option to \ntrue\n to\nload all references by reachability. But be aware of that is dangerous for large object graphs. \n\n\nDeep Loading with Queries\n\n\nDeep loading also works for query results obtained via \nresultList\n and \nsingleResult\n:\n\n\nDB.Todo.find().resultList({depth: 1}, function(result) {\n  result.forEach(function(todo) {\n    console.log(todo.doNext.name);\n  });\n});\n\n\n\n\nIn that case all referenced objects in all objects loaded by the query are fetched, too.\n\n\nCached Loads\n\n\nEach EntityManager instance has an instance cache. This instance cache is used while loading objects and resolving \nreferences. When an entity is loaded it is stored into this instance cache and will always be returned when the same \ninstance is requested. This ensures that you will always get the same instance for a given object id. That means \nobject equality is always guaranteed for objects having the same ids. \n\n\nDB.Todo.load('MyFirstTodo', {depth: 1}).then(function(firstTodo) {\n  DB.Todo.load('MySecondTodo').then(function(secondTodo) {\n    //true, object equality is guaranteed by the DB instance cache\n    console.log(firstTodo.doNext == secondTodo); \n  });  \n});\n\n\n\n\nDeep Saving\n\n\nAs with deep loading, you can also save referenced entities with the referencing entity by passing the depth option.\n If you call \nsave()\n without any options, only the entity itself will be saved, but not any referenced entity. This is the \nsame behaviour as passing \ndepth\n with the value \n0\n.\n\n\nvar firstTodo = new DB.Todo({name: 'My first Todo'});\nvar secondTodo = new DB.Todo({name: 'My second Todo'});\n\nfirstTodo.doNext = secondTodo;\nfirstTodo.save(); //will save firstTodo, but not the secondTodo\n\n\n\n\nBy passing the depth option with a value of \n1\n the entity and all its direct referenced entities will be saved.\n\n\nvar thirdTodo = new DB.Todo({name: 'My third Todo'});\n\nfirstTodo.doNext = secondTodo;\nsecondTodo.doNext = thirdTodo;\n//will save firstTodo and secondTodo, but not the thirdTodo\nfirstTodo.save({depth: 1});\n\n\n\n\nAnd again increasing the \ndepth\n value to \n2\n will save all direct referenced entities and all entities which are \nreferenced by those referenced entities. You can also pass \ndepth\n with \ntrue\n to save all dirty entities by \nreachability.",
            "title": "Deep Loading"
        },
        {
            "location": "/topics/deep-loading/#persistence-and-deep-loading",
            "text": "The Baqend SDK internally tracks the state of all living entity instances and their attributes. If an attribute of an \nentity is changed, the entity will be marked as dirty. Only dirty entities will be send back to the Baqend while calling save()  or  update() . Also the collections and embedded objects of an entity will be tracked the same way and mark the \nowning entity as dirty on modifications. The big advantage of this dirty tracking is that when you apply deep saving \nto persist object graphs, only those objects that were actually changed are transferred. This saves performance and \nbandwidth.  DB.Todo.load('Todo1').then(function(todo) {\n  todo.save(); //will not perform a Baqend request since the object is not dirty   \n});",
            "title": "Persistence and Deep Loading"
        },
        {
            "location": "/topics/deep-loading/#deep-loading",
            "text": "As described in the  References  chapter, references between entities will be handled differently \nfrom embedded objects or collections. The referenced objects will not be loaded with the referencing entity by default.  //while loading the todo, the reference will be resolved to the referenced entity\nDB.Todo.load('7b2c...').then(function(firstTodo) {\n  console.log(firstTodo.name); //'My first Todo'\n  console.log(firstTodo.doNext.name); //will throw an object not available error\n});  In a more complex scenario you may have references in a collection. These references won't be be loaded by default \nneither.  DB.Todo.load('7b2c...').then(function(firstTodo) {  \n  //will throw an object not available error\n  console.log(firstTodo.upComingTodos[0].name); \n});  To load dependant objects, you can pass the  depth  option while loading the entity. The depth option allows to \nset a reference-depth which will automatically be loaded. A depth value of  0  (the default) just loads the entity.   DB.Todo.load('7b2c...', {depth: 0}).then(function(firstTodo) {   \n  //will throw an object not available error\n  console.log(firstTodo.doNext.name); \n  //will still throw an object not available error\n  console.log(firstTodo.upComingTodos[0].name); \n});  A depth value of  1  loads the entity and one additional level of references. This also includes references in \ncollections and embedded objects.  DB.Todo.load('7b2c...', {depth: 1}).then(function(firstTodo) {\n  console.log(firstTodo.doNext.name); //'My second Todo'\n  console.log(firstTodo.upComingTodos[0].name); //'My second Todo'  \n  //will throw an object not available error\n  console.log(firstTodo.doNext.doNext.name); \n  //will still throw an object not available error\n  console.log(firstTodo.upComingTodos[0].upComingTodos[0].name); \n});  Setting the depth value to  2  resolves the next level of references and so on. You can set the depth option to  true  to\nload all references by reachability. But be aware of that is dangerous for large object graphs.",
            "title": "Deep Loading"
        },
        {
            "location": "/topics/deep-loading/#deep-loading-with-queries",
            "text": "Deep loading also works for query results obtained via  resultList  and  singleResult :  DB.Todo.find().resultList({depth: 1}, function(result) {\n  result.forEach(function(todo) {\n    console.log(todo.doNext.name);\n  });\n});  In that case all referenced objects in all objects loaded by the query are fetched, too.",
            "title": "Deep Loading with Queries"
        },
        {
            "location": "/topics/deep-loading/#cached-loads",
            "text": "Each EntityManager instance has an instance cache. This instance cache is used while loading objects and resolving \nreferences. When an entity is loaded it is stored into this instance cache and will always be returned when the same \ninstance is requested. This ensures that you will always get the same instance for a given object id. That means \nobject equality is always guaranteed for objects having the same ids.   DB.Todo.load('MyFirstTodo', {depth: 1}).then(function(firstTodo) {\n  DB.Todo.load('MySecondTodo').then(function(secondTodo) {\n    //true, object equality is guaranteed by the DB instance cache\n    console.log(firstTodo.doNext == secondTodo); \n  });  \n});",
            "title": "Cached Loads"
        },
        {
            "location": "/topics/deep-loading/#deep-saving",
            "text": "As with deep loading, you can also save referenced entities with the referencing entity by passing the depth option.\n If you call  save()  without any options, only the entity itself will be saved, but not any referenced entity. This is the \nsame behaviour as passing  depth  with the value  0 .  var firstTodo = new DB.Todo({name: 'My first Todo'});\nvar secondTodo = new DB.Todo({name: 'My second Todo'});\n\nfirstTodo.doNext = secondTodo;\nfirstTodo.save(); //will save firstTodo, but not the secondTodo  By passing the depth option with a value of  1  the entity and all its direct referenced entities will be saved.  var thirdTodo = new DB.Todo({name: 'My third Todo'});\n\nfirstTodo.doNext = secondTodo;\nsecondTodo.doNext = thirdTodo;\n//will save firstTodo and secondTodo, but not the thirdTodo\nfirstTodo.save({depth: 1});  And again increasing the  depth  value to  2  will save all direct referenced entities and all entities which are \nreferenced by those referenced entities. You can also pass  depth  with  true  to save all dirty entities by \nreachability.",
            "title": "Deep Saving"
        },
        {
            "location": "/topics/hosting/",
            "text": "Hosting\n\n\nWith the hosting feature you can serve your website (html, css, js, images) right from your Baqend cloud instance while using your own domain.\n\n\nPublic File Access\n\n\nAll assets stored in the \nwww\n root folder can be accessed under your app domain (\n<appName>.app.baqend.com\n) as in the following examples:\n\n\n\n  \n\n    \nFolder (\nparent\n)\n\n    \nFile Name (\nname\n)\n\n    \nPublic Url\n\n  \n\n  \n\n    \nwww\n\n    \nindex.html\n\n    \n<appName>.app.baqend.com/\n\n  \n\n  \n\n    \nwww\n\n    \nabout.html\n\n    \n<appName>.app.baqend.com/about.html\n\n  \n\n  \n\n    \nwww/images\n\n    \nlogo.jpg\n\n    \n<appName>.app.baqend.com/images/logo.jpg\n\n  \n\n\n\n\n\n  \nTip:\n\n  Baqend hosting works great with \nstatic site generators\n like \nJekyll\n, \nHugo\n, \nOctopress\n, or \nHexo\n. You can start completely static or even import data from CMS like Wordpres.\n  Later you can gradually add dynamic parts using the Baqend SDK. From the first static blog post to a highly dynamic site, everything will be cached and accelerated by Baqend.\n\n\n\n\nDeployment\n\n\nTo deploy your assets you can either use the file explorer in the Baqend dashboard (e.g. drag-and-drop files and folders) or for an easy, automated deployment user the \nBaqend CLI\n.\n\n\nCustom Domains\n\n\nTo serve your website under your own domain you have to create a dns entry and register the custom domain in your Baqend dashboard:\n\n\n\n\n\n\nLog into the account at your domain provider and add a CNAME rule like the following to your DNS entries:\n\n\nwww.yourdomain.com. IN CNAME <appName>.app.baqend.com.\n\n\nNote\n: You should not use a top level domain as a CNAME, since many DNS providers do not support it. Instead use a sub domain\nsuch as \nwww.\nyourdomain.com. In addition you should ensure that no other DNS-entry is set for the used domain.\n\n\n\n\n\n\nLog into your Baqend dashboard and open your app settings. In the Hosting section simply add your custom domain \nwww.yourdomain.com\n and click the save button. Your domain will now be registered at the CDN. Instead of \n<appName>.app.baqend.com\n you can now use \nwww.yourdomain.com\n.\n\n\n\n\n\n\nConsult your DNS provider's instructions to configure the CNAME record for your domain name. The steps to add a CNAME record will vary for each registrar's control panel interface.\n\n\nIf you cannot find your provider's CNAME configuration instructions, Google maintains instructions for \nmost major providers\n. \n\n\nNote:\n The registration of your domain as well as your dns-entry can take a few minutes until they are accessable. If you have trouble configuring your CNAME records, contact us at \nsupport@baqend.com.\n\n\n\nNote:\n If you can't use a subdomain and want to directly use an \napex/naked-domain\n (such as \nexmaple.com\n, without \nwww\n) \nyou should create four \nA records\n which point to our Anycast IP addresses:\n\n\nyourdomain.com. IN A 151.101.2.8\nyourdomain.com. IN A 151.101.66.8\nyourdomain.com. IN A 151.101.130.8\nyourdomain.com. IN A 151.101.194.8\n\n\n\n\n\n\n\nSingle Page Apps\n\n\nHistory API\n\n\nIf you use the \nHistory API\n of your single page app framework (like Angular2 or React), you need to host your \nindex.html\n also as \n404.html\n. This leaves you with the two identical files:\n\n\n  \n\n    \nFolder (\nparent\n)\n\n    \nFile Name (\nname\n)\n\n    \nPublic Url\n\n  \n\n  \n\n    \nwww\n\n    \nindex.html\n\n    \n<appName>.app.baqend.com/\n\n  \n\n  \n\n    \nwww\n\n    \n404.html\n\n    \nEvery URL where no file is hosted\n\n  \n\n\n\nThis is in order to make sure that ever entrypoint into the app uses the code from your \nindex.html\n.\n\n\nIf a user for example directly opens a URL like \nhttp://yourapp.com/products/42\n this request needs to be handled by the single page app because there is no hosted HTML file under \n/www/products/42.html\n.\nThe \n404.html\n is returned whenever no hosted file is found for a URL (like \nhttp://yourapp.com/products/42\n). By hosting the same code in both your \nindex.html\n and \n404.html\n all entrypoints will be correctly handled.\n\n\nSSL Hosting\n\n\nAll data accessed over the Baqend SDK is SSL encrypted by enforcing encryption at \nconnect\n. \nIf you need SSL encryption for your hosted assets too please contact us (\nsupport@baqend.com\n),\nas this feature is not automated yet.",
            "title": "Hosting"
        },
        {
            "location": "/topics/hosting/#hosting",
            "text": "With the hosting feature you can serve your website (html, css, js, images) right from your Baqend cloud instance while using your own domain.",
            "title": "Hosting"
        },
        {
            "location": "/topics/hosting/#public-file-access",
            "text": "All assets stored in the  www  root folder can be accessed under your app domain ( <appName>.app.baqend.com ) as in the following examples:  \n   \n     Folder ( parent ) \n     File Name ( name ) \n     Public Url \n   \n   \n     www \n     index.html \n     <appName>.app.baqend.com/ \n   \n   \n     www \n     about.html \n     <appName>.app.baqend.com/about.html \n   \n   \n     www/images \n     logo.jpg \n     <appName>.app.baqend.com/images/logo.jpg \n     \n   Tip: \n  Baqend hosting works great with  static site generators  like  Jekyll ,  Hugo ,  Octopress , or  Hexo . You can start completely static or even import data from CMS like Wordpres.\n  Later you can gradually add dynamic parts using the Baqend SDK. From the first static blog post to a highly dynamic site, everything will be cached and accelerated by Baqend.",
            "title": "Public File Access"
        },
        {
            "location": "/topics/hosting/#deployment",
            "text": "To deploy your assets you can either use the file explorer in the Baqend dashboard (e.g. drag-and-drop files and folders) or for an easy, automated deployment user the  Baqend CLI .",
            "title": "Deployment"
        },
        {
            "location": "/topics/hosting/#custom-domains",
            "text": "To serve your website under your own domain you have to create a dns entry and register the custom domain in your Baqend dashboard:    Log into the account at your domain provider and add a CNAME rule like the following to your DNS entries:  www.yourdomain.com. IN CNAME <appName>.app.baqend.com.  Note : You should not use a top level domain as a CNAME, since many DNS providers do not support it. Instead use a sub domain\nsuch as  www. yourdomain.com. In addition you should ensure that no other DNS-entry is set for the used domain.    Log into your Baqend dashboard and open your app settings. In the Hosting section simply add your custom domain  www.yourdomain.com  and click the save button. Your domain will now be registered at the CDN. Instead of  <appName>.app.baqend.com  you can now use  www.yourdomain.com .    Consult your DNS provider's instructions to configure the CNAME record for your domain name. The steps to add a CNAME record will vary for each registrar's control panel interface.  If you cannot find your provider's CNAME configuration instructions, Google maintains instructions for  most major providers .   Note:  The registration of your domain as well as your dns-entry can take a few minutes until they are accessable. If you have trouble configuring your CNAME records, contact us at  support@baqend.com.  Note:  If you can't use a subdomain and want to directly use an  apex/naked-domain  (such as  exmaple.com , without  www ) \nyou should create four  A records  which point to our Anycast IP addresses:  yourdomain.com. IN A 151.101.2.8\nyourdomain.com. IN A 151.101.66.8\nyourdomain.com. IN A 151.101.130.8\nyourdomain.com. IN A 151.101.194.8",
            "title": "Custom Domains"
        },
        {
            "location": "/topics/hosting/#single-page-apps",
            "text": "",
            "title": "Single Page Apps"
        },
        {
            "location": "/topics/hosting/#history-api",
            "text": "If you use the  History API  of your single page app framework (like Angular2 or React), you need to host your  index.html  also as  404.html . This leaves you with the two identical files: \n   \n     Folder ( parent ) \n     File Name ( name ) \n     Public Url \n   \n   \n     www \n     index.html \n     <appName>.app.baqend.com/ \n   \n   \n     www \n     404.html \n     Every URL where no file is hosted \n    \nThis is in order to make sure that ever entrypoint into the app uses the code from your  index.html .  If a user for example directly opens a URL like  http://yourapp.com/products/42  this request needs to be handled by the single page app because there is no hosted HTML file under  /www/products/42.html .\nThe  404.html  is returned whenever no hosted file is found for a URL (like  http://yourapp.com/products/42 ). By hosting the same code in both your  index.html  and  404.html  all entrypoints will be correctly handled.",
            "title": "History API"
        },
        {
            "location": "/topics/hosting/#ssl-hosting",
            "text": "All data accessed over the Baqend SDK is SSL encrypted by enforcing encryption at  connect . \nIf you need SSL encryption for your hosted assets too please contact us ( support@baqend.com ),\nas this feature is not automated yet.",
            "title": "SSL Hosting"
        },
        {
            "location": "/topics/files/",
            "text": "Files\n\n\nBaqend comes with a powerful File and Asset API. You can create multiple root level folders and apply different \npermissions to those. Files can be uploaded, replaced, downloaded and deleted when the user has the right permissions. \n\n\nIn addition the SDK comes with a rich set of functionality to transform the file contents to different browser friendly \nformats. In the following table we list all supported file formats:\n\n\n\n  \n\n    \ntype\n\n    \nJavaScript type\n\n    \nDescription\n\n  \n\n  \n\n    \n'arraybuffer'\n\n    \nArrayBuffer\n\n    \nThe content is represented as a fixed-length raw binary data buffer\n\n    \nvar buffer = new ArrayBuffer(8)\n\n  \n\n  \n\n    \n'blob'\n\n    \nBlob\n|\nFile\n\n    \nThe content is represented as a simple blob\n\n    \nvar blob = new Blob([\"<a href=...\"], {type : 'text/html'})\n\n    Note: This does \nnot\n work in Baqend code\n\n  \n\n  \n\n    \n'json'\n\n    \nobject|array|string\n\n    \nThe file content is represented as json\n\n      \nvar json = {prop: \"value\"}\n\n  \n\n  \n\n    \n'text'\n\n    \nstring\n\n    \nThe file content is represented through the string\n\n    \n'A Simple Text'\n\n  \n\n  \n\n    \n'base64'\n\n    \nstring\n\n    \nThe file content as base64 encoded string\n\n    \n'PHN2ZyB4bWxucz...'\n\n  \n\n  \n\n    \n'data-url'\n\n    \nstring\n\n    \nA data url which represents the file content\n\n    \n'data:image/gif;base64,R0lGODlhD...'\n\n  \n\n  \n\n    \n'stream'\n\n    \nStream\n\n    \nA stream containing the file content\n\n    See our \nexample\n.\n\n    Note: This \nonly\n works in Baqend code.\n\n  \n\n  \n\n    \n'buffer'\n\n    \nBuffer\n\n    \nA buffer containing the file content\n\n    \n'var buffer = Buffer.from(array)'\n\n    Note: This \nonly\n works in Baqend code\n\n  \n\n\n\n\n\nThe file API accepts all the listed formats as upload type and transforms the content to the correct binary representation\nwhile uploading it. The SDK guesses the correct type except for the \nbase64\n type and transforms it automatically. \n\n\nWhen you download a file you can specify in which format the downloaded content should be provided.\n\n\nAccessing Files\n\n\nThe simplest way to access a file is to retrieve the absolute url form the Baqend SDK. Therefore you can use any existing\nfile reference or you can create one by yourself.\n\n\nThe are multiple ways to reference a file:\n\n\n// Absolute references have to start with '/file' followed by a root folder e.g. '/www'\nvar file = new DB.File('/file/www/myPic.jpg');\n// Alternatively you can give the path of the file, starting with the root folder\nvar file = new DB.File({path: '/www/myPic.jpg'});\n// Or you specify the name and parent (folder) of the file\nvar file = new DB.File({parent: '/www', name: 'myPic.jpg'});\n// Because '/www' is the default parent in can be omitted\nvar file = new DB.File({name: 'myPic.jpg'});\n\n\n\n\nTo get the full url to access the file just use the \nfile.url\n shorthand. This ensures that the domain is correctly used, \nchecks if the file is stale or can be directly served form the cache and attach authorization credentials if needed. \n\n\nIn a common html template engine you can just write:\n\n\n<img src=\"{{file.url}}\">\n\n\n\n\nYou can also manage your files in folders for example like this:\n\n\n//creates the same file reference\nvar file = new DB.File('/file/www/images/myPic.jpg');\n//parent start with the root folder, e.g. /www and followed by additional folders\nvar file = new DB.File({parent: '/www/images', name: 'myPic.jpg'});\n\n\n\n\nNote:\n Parent paths always start with a root folder, since the access control (who can access and modify the folder contents)\ncan only be set for the root folder and is applied to all nested files and folders.\n\n\n\nEmbedded Files\n\n\nFiles can also be embedded in other objects like for example a profile image in a user object (see \nprimitive types\n):\n\n\ndb.User.me.load().then(function(user) {\n    var file = user.profileImage;\n    console.log(file.url); // The file url, e.g. 'http://app.baqend.com/v1/file/users/img/myImg.png'\n});\n\n\n\n\nMetadata\n\n\nSuppose you have an uploaded file \n/www/images/myPic.jpg\n and a reference to it.\nThen you can use the \nload\n method to get additional file metadata (not the \ncontent itself\n):\n\n\nvar file = new DB.File('/file/www/images/myPic.jpg');\nfile.load(function() {\n    file.isMetadataLoaded // > true\n    file.lastModified // > The time of the last update\n    file.size // > Filesize in byte\n});\n\n\n\n\nListing Files\n\n\nYou can also list all files inside a folder. Either provide the path to the folder as string or a file reference representing the folder\n\n\nvar folder = new DB.File('/file/www/images/');\nDB.File.listFiles(folder).then(function(files) {\n    // all the files in the folder '/www/images/'\n});\n\n\n\n\n\nNote:\n If you have many files in a folder, you should always specify a limit on how many files are returned. See the \nSDK documentation\n for details.\n\n\n\nYou can also list all \nroot folders\n:\n\n\nDB.File.listBuckets().then(function(rootFolders) {\n    // all root folders\n});\n\n\n\n\n\nUploading Files\n\n\nTo upload a file you must first create a file with its name and its content.\nAfterwards you can simply upload the file by just invoking \nupload()\n:\n\n\nvar file = new DB.File({name: 'test.png', data: file, type: 'blob'})\nfile.upload().then(function(file) {\n    //upload succeed successfully \n    file.mimeType //contains the media type of the file\n    file.lastModified //the upload date\n    file.eTag //the eTag of the file\n}, function(error) {\n    //upload failed with an error \n});\n\n\n\n\nIn most cases you would like to upload the files which was provided by your user through a file input field or a file \ndrag & drop event. \n\n\n<input type=\"file\" id=\"input\" multiple onchange=\"uploadFiles(this.files)\">\n\n\n\n\nfunction uploadFiles(files) {\n  var pendingUploads = [];\n\n  for (var i = 0, numFiles = files.length; i < numFiles; i++) {\n    //If you omit the name parameter, the name of the provided file object is used\n    var file = new DB.File({data: files[i]});\n    pendingUploads.push(file.upload());\n  }\n\n  Promise.all(pendingUploads).then(function() {\n    //all files are successfully uploaded\n  });\n}\n\n\n\n\nIn the cases you want to upload base64 encoded binary data you can use the base64 type in the options object:\n\n\nvar file = new DB.File({name: 'test.png', data: 'R0lGODlhDAAeALMAAG...', type: 'base64', mimeType: 'image/gif'})\nfile.upload().then(function(file) {\n    //upload succeed successfully \n    file.mimeType //contains the media type of the file\n    file.lastModified //the upload date\n    file.eTag //the eTag of the file\n}, function(error) {\n    //upload failed with an error \n});\n\n\n\n\nIf you try to overwrite an existing file and do not have previously fetched the file or its metadata, or the file has \nbeen changed in the meantime the upload will be rejected to prevent accidental file replacement. \nIf you like to skip the verification, you can pass the \n{force: true}\n option to the \nupload()\n call. \n\n\nNote:\n To upload a file you must have at least the insert or update permission on the root folder and write access on the file. \n\n\n\nDownloading Files\n\n\nDownloading a file works similar to uploading one. Just create a file reference and call \nfile.download()\n:\n\n\nvar file = new DB.File({name: 'myPic.jpg'});\nfile.download(function(data) {\n    data //is provided as Blob per default\n\n    //accessing the metadata of the file \n    file.mimeType //contains the media type of the file\n    file.lastModified //the upload date\n    file.eTag //the eTag of the file\n});\n\n\n\n\nTo load the file content in a different format, just request a download \ntype\n\n\nvar file = new DB.File({name: 'myPic.jpg', type: 'data-url'});\nfile.download(function(data) {\n    //data is a data url string\n    data // \"data:image/jpeg;base64,R0lGODlhDAA...\"\n});\n\n\n\n\nNote:\n To download a file you must have at least the load on the root folder and read access on the file. \n\n\n\nDeleting Files\n\n\nTo delete a file just call the \ndelete()\n method after creating the file reference:\n\n\nvar file = new DB.File({name: 'test.png'})\nfile.delete().then(function(file) {\n    //deletion succeed\n}, function(error) {\n    //upload failed with an error \n});\n\n\n\n\nIf you try to delete a file and you have previously fetched the file or its metadata and the file has \nbeen changed in the meantime the deletion will be rejected to prevent accidental file deletions. \nIf you like to skip the verification, you can pass the \n{force: true}\n option to the \ndelete()\n call. \n\n\nFile ACLs\n\n\nThe File Permissions works similar to the object acls, you can define permissions on the root folders similar to class-based \npermissions and file permissions similar to object level permissions.\n\n\nThe root folder permissions are applied to all nesting folders and files.\n\n\nFile Permissions\n\n\nThe following table gives an overview of the required permissions per operation:\n\n\n\n  \n\n    \nMethod\n\n    \nRoot-folder-based permission\n\n    \nFile-based permission\n\n  \n\n  \n\n    \n.download(), .url\n\n    \nfolder.load\n\n    \nobject.acl.read\n\n  \n\n  \n\n    \n.upload(<new file>)\n\n    \nfolder.insert\n\n    \n-\n\n  \n\n  \n\n    \n.upload(<existing file>)\n\n    \nfolder.update\n\n    \nobject.acl.write\n\n  \n\n  \n\n    \n.upload({force: true})\n\n    \nboth folder.insert and folder.update will be checked\n\n    \nobject.acl.write\n\n  \n\n  \n\n    \n.delete()\n\n    \nfolder.delete\n\n    \nobject.acl.write\n\n  \n\n\n\n\n\nSet root folder Permissions\n\n\nPer default only the admin can access root folders with one exception. The \nwww\n folder is public readable for the file \nhosting feature of Baqend.\n\n\nTo change the permissions for a specific root folder yous should commonly use the Baqend Dashboard. \nBut if you like to change the permissions programmatically you can use the \nsaveMetadata()\n method:\n\n\n//grant full access on the pictures root folder for the current user\nDB.File.saveMetadata('pictures', {\n   load: new DB.util.Permission().allowAccess(db.User.me),\n   insert: new DB.util.Permission().allowAccess(db.User.me),\n   update: new DB.util.Permission().allowAccess(db.User.me),\n   delete: new DB.util.Permission().allowAccess(db.User.me),\n   query: new DB.util.Permission().allowAccess(db.User.me)\n});\n\n\n\n\nNote:\n To actually change the permissions of a root folder, you must own the admin role or you code must be executed \nas Baqend code.\n\n\n\nSet file Permissions\n\n\nThe file permissions can be set when a file is uploaded. Therefore you can pass the acl option to the File constructor \nor to the upload method. \n\n\nvar file = new DB.File({\n    name: 'test.png', \n    data: file, \n    acl: new DB.Acl()\n        .allowReadAccess(db1.User.me)\n        .allowWriteAccess(db1.User.me)\n});\nfile.upload().then(...);",
            "title": "Files"
        },
        {
            "location": "/topics/files/#files",
            "text": "Baqend comes with a powerful File and Asset API. You can create multiple root level folders and apply different \npermissions to those. Files can be uploaded, replaced, downloaded and deleted when the user has the right permissions.   In addition the SDK comes with a rich set of functionality to transform the file contents to different browser friendly \nformats. In the following table we list all supported file formats:  \n   \n     type \n     JavaScript type \n     Description \n   \n   \n     'arraybuffer' \n     ArrayBuffer \n     The content is represented as a fixed-length raw binary data buffer \n     var buffer = new ArrayBuffer(8) \n   \n   \n     'blob' \n     Blob | File \n     The content is represented as a simple blob \n     var blob = new Blob([\"<a href=...\"], {type : 'text/html'}) \n    Note: This does  not  work in Baqend code \n   \n   \n     'json' \n     object|array|string \n     The file content is represented as json \n       var json = {prop: \"value\"} \n   \n   \n     'text' \n     string \n     The file content is represented through the string \n     'A Simple Text' \n   \n   \n     'base64' \n     string \n     The file content as base64 encoded string \n     'PHN2ZyB4bWxucz...' \n   \n   \n     'data-url' \n     string \n     A data url which represents the file content \n     'data:image/gif;base64,R0lGODlhD...' \n   \n   \n     'stream' \n     Stream \n     A stream containing the file content \n    See our  example . \n    Note: This  only  works in Baqend code. \n   \n   \n     'buffer' \n     Buffer \n     A buffer containing the file content \n     'var buffer = Buffer.from(array)' \n    Note: This  only  works in Baqend code \n     The file API accepts all the listed formats as upload type and transforms the content to the correct binary representation\nwhile uploading it. The SDK guesses the correct type except for the  base64  type and transforms it automatically.   When you download a file you can specify in which format the downloaded content should be provided.",
            "title": "Files"
        },
        {
            "location": "/topics/files/#accessing-files",
            "text": "The simplest way to access a file is to retrieve the absolute url form the Baqend SDK. Therefore you can use any existing\nfile reference or you can create one by yourself.  The are multiple ways to reference a file:  // Absolute references have to start with '/file' followed by a root folder e.g. '/www'\nvar file = new DB.File('/file/www/myPic.jpg');\n// Alternatively you can give the path of the file, starting with the root folder\nvar file = new DB.File({path: '/www/myPic.jpg'});\n// Or you specify the name and parent (folder) of the file\nvar file = new DB.File({parent: '/www', name: 'myPic.jpg'});\n// Because '/www' is the default parent in can be omitted\nvar file = new DB.File({name: 'myPic.jpg'});  To get the full url to access the file just use the  file.url  shorthand. This ensures that the domain is correctly used, \nchecks if the file is stale or can be directly served form the cache and attach authorization credentials if needed.   In a common html template engine you can just write:  <img src=\"{{file.url}}\">  You can also manage your files in folders for example like this:  //creates the same file reference\nvar file = new DB.File('/file/www/images/myPic.jpg');\n//parent start with the root folder, e.g. /www and followed by additional folders\nvar file = new DB.File({parent: '/www/images', name: 'myPic.jpg'});  Note:  Parent paths always start with a root folder, since the access control (who can access and modify the folder contents)\ncan only be set for the root folder and is applied to all nested files and folders.",
            "title": "Accessing Files"
        },
        {
            "location": "/topics/files/#embedded-files",
            "text": "Files can also be embedded in other objects like for example a profile image in a user object (see  primitive types ):  db.User.me.load().then(function(user) {\n    var file = user.profileImage;\n    console.log(file.url); // The file url, e.g. 'http://app.baqend.com/v1/file/users/img/myImg.png'\n});",
            "title": "Embedded Files"
        },
        {
            "location": "/topics/files/#metadata",
            "text": "Suppose you have an uploaded file  /www/images/myPic.jpg  and a reference to it.\nThen you can use the  load  method to get additional file metadata (not the  content itself ):  var file = new DB.File('/file/www/images/myPic.jpg');\nfile.load(function() {\n    file.isMetadataLoaded // > true\n    file.lastModified // > The time of the last update\n    file.size // > Filesize in byte\n});",
            "title": "Metadata"
        },
        {
            "location": "/topics/files/#listing-files",
            "text": "You can also list all files inside a folder. Either provide the path to the folder as string or a file reference representing the folder  var folder = new DB.File('/file/www/images/');\nDB.File.listFiles(folder).then(function(files) {\n    // all the files in the folder '/www/images/'\n});  Note:  If you have many files in a folder, you should always specify a limit on how many files are returned. See the  SDK documentation  for details.  You can also list all  root folders :  DB.File.listBuckets().then(function(rootFolders) {\n    // all root folders\n});",
            "title": "Listing Files"
        },
        {
            "location": "/topics/files/#uploading-files",
            "text": "To upload a file you must first create a file with its name and its content.\nAfterwards you can simply upload the file by just invoking  upload() :  var file = new DB.File({name: 'test.png', data: file, type: 'blob'})\nfile.upload().then(function(file) {\n    //upload succeed successfully \n    file.mimeType //contains the media type of the file\n    file.lastModified //the upload date\n    file.eTag //the eTag of the file\n}, function(error) {\n    //upload failed with an error \n});  In most cases you would like to upload the files which was provided by your user through a file input field or a file \ndrag & drop event.   <input type=\"file\" id=\"input\" multiple onchange=\"uploadFiles(this.files)\">  function uploadFiles(files) {\n  var pendingUploads = [];\n\n  for (var i = 0, numFiles = files.length; i < numFiles; i++) {\n    //If you omit the name parameter, the name of the provided file object is used\n    var file = new DB.File({data: files[i]});\n    pendingUploads.push(file.upload());\n  }\n\n  Promise.all(pendingUploads).then(function() {\n    //all files are successfully uploaded\n  });\n}  In the cases you want to upload base64 encoded binary data you can use the base64 type in the options object:  var file = new DB.File({name: 'test.png', data: 'R0lGODlhDAAeALMAAG...', type: 'base64', mimeType: 'image/gif'})\nfile.upload().then(function(file) {\n    //upload succeed successfully \n    file.mimeType //contains the media type of the file\n    file.lastModified //the upload date\n    file.eTag //the eTag of the file\n}, function(error) {\n    //upload failed with an error \n});  If you try to overwrite an existing file and do not have previously fetched the file or its metadata, or the file has \nbeen changed in the meantime the upload will be rejected to prevent accidental file replacement. \nIf you like to skip the verification, you can pass the  {force: true}  option to the  upload()  call.   Note:  To upload a file you must have at least the insert or update permission on the root folder and write access on the file.",
            "title": "Uploading Files"
        },
        {
            "location": "/topics/files/#downloading-files",
            "text": "Downloading a file works similar to uploading one. Just create a file reference and call  file.download() :  var file = new DB.File({name: 'myPic.jpg'});\nfile.download(function(data) {\n    data //is provided as Blob per default\n\n    //accessing the metadata of the file \n    file.mimeType //contains the media type of the file\n    file.lastModified //the upload date\n    file.eTag //the eTag of the file\n});  To load the file content in a different format, just request a download  type  var file = new DB.File({name: 'myPic.jpg', type: 'data-url'});\nfile.download(function(data) {\n    //data is a data url string\n    data // \"data:image/jpeg;base64,R0lGODlhDAA...\"\n});  Note:  To download a file you must have at least the load on the root folder and read access on the file.",
            "title": "Downloading Files"
        },
        {
            "location": "/topics/files/#deleting-files",
            "text": "To delete a file just call the  delete()  method after creating the file reference:  var file = new DB.File({name: 'test.png'})\nfile.delete().then(function(file) {\n    //deletion succeed\n}, function(error) {\n    //upload failed with an error \n});  If you try to delete a file and you have previously fetched the file or its metadata and the file has \nbeen changed in the meantime the deletion will be rejected to prevent accidental file deletions. \nIf you like to skip the verification, you can pass the  {force: true}  option to the  delete()  call.",
            "title": "Deleting Files"
        },
        {
            "location": "/topics/files/#file-acls",
            "text": "The File Permissions works similar to the object acls, you can define permissions on the root folders similar to class-based \npermissions and file permissions similar to object level permissions.  The root folder permissions are applied to all nesting folders and files.",
            "title": "File ACLs"
        },
        {
            "location": "/topics/files/#file-permissions",
            "text": "The following table gives an overview of the required permissions per operation:  \n   \n     Method \n     Root-folder-based permission \n     File-based permission \n   \n   \n     .download(), .url \n     folder.load \n     object.acl.read \n   \n   \n     .upload(<new file>) \n     folder.insert \n     - \n   \n   \n     .upload(<existing file>) \n     folder.update \n     object.acl.write \n   \n   \n     .upload({force: true}) \n     both folder.insert and folder.update will be checked \n     object.acl.write \n   \n   \n     .delete() \n     folder.delete \n     object.acl.write",
            "title": "File Permissions"
        },
        {
            "location": "/topics/files/#set-root-folder-permissions",
            "text": "Per default only the admin can access root folders with one exception. The  www  folder is public readable for the file \nhosting feature of Baqend.  To change the permissions for a specific root folder yous should commonly use the Baqend Dashboard. \nBut if you like to change the permissions programmatically you can use the  saveMetadata()  method:  //grant full access on the pictures root folder for the current user\nDB.File.saveMetadata('pictures', {\n   load: new DB.util.Permission().allowAccess(db.User.me),\n   insert: new DB.util.Permission().allowAccess(db.User.me),\n   update: new DB.util.Permission().allowAccess(db.User.me),\n   delete: new DB.util.Permission().allowAccess(db.User.me),\n   query: new DB.util.Permission().allowAccess(db.User.me)\n});  Note:  To actually change the permissions of a root folder, you must own the admin role or you code must be executed \nas Baqend code.",
            "title": "Set root folder Permissions"
        },
        {
            "location": "/topics/files/#set-file-permissions",
            "text": "The file permissions can be set when a file is uploaded. Therefore you can pass the acl option to the File constructor \nor to the upload method.   var file = new DB.File({\n    name: 'test.png', \n    data: file, \n    acl: new DB.Acl()\n        .allowReadAccess(db1.User.me)\n        .allowWriteAccess(db1.User.me)\n});\nfile.upload().then(...);",
            "title": "Set file Permissions"
        },
        {
            "location": "/topics/caching/",
            "text": "Caching\n\n\nHow Baqends Caching works\n\n\nBaqend uses a combination of CDN and client caching using a Bloom filter-based data structures called \nCache-Sketch\n. This enables Baqend-based applications to use not only CDN caches but also expiration-based caches \u200a\u2014 \u200ain most cases the browser cache\u200a \u2014 \u200ato cache any \ndynamic\n data.\n\n\nCaching everything, not just assets\n\n\nThe tricky thing when using such caches is that you must specify a cache lifetime (TTL) when you first deliver the data from the server. After that you do not have any chance to kick the data out. It will be served by the browser cache up to the moment the TTL expires. For static assets it is not such a complex thing, since they usually only change when you deploy a new version of your web application. Therefore, you can use cool tools like\u00a0\ngulp-rev-all\n\u00a0and\ngrunt-filerev\n\u00a0to hash the assets. By renaming the assets at deployment time you ensure that all users will see the latest version of your page while using caches at their best\n\n\nBut wait! What do you do with all the data which is loaded and changed by your application at runtime? Changing user profiles, updating a post or adding a new comment are seemingly impossible to combine with the browsers cache, since you cannot estimate when such updates will happen in the future. Therefore, caching is just disabled or very low TTLs are used.\n\n\n\n\nBaqend\u2019s Cache-Sketch\n\n\nWe have researched and developed a solution where we can check the staleness of any data before we actually fetch them. At the begin of each user session the \nconnect\ncall fetches a very small data structure called a Bloom filter, which is a highly compressed representation of a set. Before making a request, the SDK first checks this set to know if it contains an entry for the resource we fetch. An entry in the set indicates that the content was changed in the near past and that the content may be stale. In such cases the SDK bypasses the browser cache and fetches the content from the nearest CDN edge server. In all other cases the content is served directly from the browsers cache. Using the browser cache saves network traffic, bandwidth and is rocket-fast.\n\n\nIn addition, we ensure that the CDN always contains the most recent data, by instantly purging data when it becomes stale.\n\n\n\n\nThe\u00a0\nBloom filter\n\u00a0is a probabilistic data structure with a tunable false positive rate, which means that the set may Indicate containment for objects which were never added. This is not a huge problem since it just means the we first revalidate the freshness of an object before we serve it from the browsers cache. Note that the false positive rate is very low and it is what enables us to make the footprint of the set very small. For an example we just need 11Kbyte to store 20,000 distinct updates.\n\n\nThere is lot of stream processing (query match detection), machine learning (optimal TTL estimation) and distributed coordination (scalable Bloom filter maintenance) happening at the server side. If you\u2019re interested in the nitty-gritty details have a look at this\u00a0\npaper\n\u00a0or\u00a0\nthese slides\n\u00a0for a deep-dive.\n\n\nNote:\n Caching is active for all CRUD operations by default. Query Caching is currently in beta, if you would like to test it please contact \nsupport@baqend.com\n.\n\n\n\nConfiguring Freshness\n\n\nAny new page load will always return the newest data (a fresh Bloom filter is fetched). While the app is running you can allow a configurable maximum staleness to make optimal use of the browser cache. This does not mean that you will actually see any outdated content, it just provides you with an upper bound that is never exceeded.\n\n\nThere are two settings affecting Bloom filter freshness that can be configured in the dashboard:\n\n\n\n\nMaximum CDN staleness\n: this is the staleness bound for all new clients (i.e. that have not cached a Bloom fitler, yet). The default setting is to only do micro-caching of 1 second. This incurs 1 second of staleness at the maximum and protects the server from excessive load under high user volumes.\n\n\nMaximum total staleness\n: defines the maximum staleness seen by the client (CDN staleness + client cache staleness). Internally the client makes sure to update the Bloom filter, when it gets too old.\n\n\n\n\nTip:\n You can increase both staleness settings, if your application is under very heavy load. This saves you requests and prevents scalability bottlenecks if you are in the free tier.\n\n\n\nIf you want to override the total staleness in individual clients, you can set it manually:\n\n\nDB.configure({\n    staleness : 10\n}).connect().then(...);\n\n\n\n\nFor individual operations you can optionally bypass the cache to get \nstrong consistency\n (linearizability):\n\n\n//To get the newest version via the id\nvar todo = DB.Todo.load(\"myTodo\", {refresh : true });\n\n//To update a known instance to the latest version\ntodo.load({refresh : true });\n\n\n\n\nLocal Objects\n\n\nYou can request already loaded objects using the \nlocal\n flag. It will try to give you an instance you have already loaded and only load it, if it's not present:\n\n\n//If we have seen \"myTodo\" in the code we will get exactly that instance\nDB.Todo.load(\"myTodo\", {local : true }).then(...);\n\n//local is the default for the instance method\ntodo.load().then(...);\n\n//This is also useful to see your own unsaved changes, irrespective of updates from other users\ntodo.done = true;\nDB.Todo.load(\"myTodo\", {local : true }).then(function() {\n    console.log(todo.done); // true\n});",
            "title": "Caching"
        },
        {
            "location": "/topics/caching/#caching",
            "text": "",
            "title": "Caching"
        },
        {
            "location": "/topics/caching/#how-baqends-caching-works",
            "text": "Baqend uses a combination of CDN and client caching using a Bloom filter-based data structures called  Cache-Sketch . This enables Baqend-based applications to use not only CDN caches but also expiration-based caches \u200a\u2014 \u200ain most cases the browser cache\u200a \u2014 \u200ato cache any  dynamic  data.",
            "title": "How Baqends Caching works"
        },
        {
            "location": "/topics/caching/#caching-everything-not-just-assets",
            "text": "The tricky thing when using such caches is that you must specify a cache lifetime (TTL) when you first deliver the data from the server. After that you do not have any chance to kick the data out. It will be served by the browser cache up to the moment the TTL expires. For static assets it is not such a complex thing, since they usually only change when you deploy a new version of your web application. Therefore, you can use cool tools like\u00a0 gulp-rev-all \u00a0and grunt-filerev \u00a0to hash the assets. By renaming the assets at deployment time you ensure that all users will see the latest version of your page while using caches at their best  But wait! What do you do with all the data which is loaded and changed by your application at runtime? Changing user profiles, updating a post or adding a new comment are seemingly impossible to combine with the browsers cache, since you cannot estimate when such updates will happen in the future. Therefore, caching is just disabled or very low TTLs are used.",
            "title": "Caching everything, not just assets"
        },
        {
            "location": "/topics/caching/#baqends-cache-sketch",
            "text": "We have researched and developed a solution where we can check the staleness of any data before we actually fetch them. At the begin of each user session the  connect call fetches a very small data structure called a Bloom filter, which is a highly compressed representation of a set. Before making a request, the SDK first checks this set to know if it contains an entry for the resource we fetch. An entry in the set indicates that the content was changed in the near past and that the content may be stale. In such cases the SDK bypasses the browser cache and fetches the content from the nearest CDN edge server. In all other cases the content is served directly from the browsers cache. Using the browser cache saves network traffic, bandwidth and is rocket-fast.  In addition, we ensure that the CDN always contains the most recent data, by instantly purging data when it becomes stale.   The\u00a0 Bloom filter \u00a0is a probabilistic data structure with a tunable false positive rate, which means that the set may Indicate containment for objects which were never added. This is not a huge problem since it just means the we first revalidate the freshness of an object before we serve it from the browsers cache. Note that the false positive rate is very low and it is what enables us to make the footprint of the set very small. For an example we just need 11Kbyte to store 20,000 distinct updates.  There is lot of stream processing (query match detection), machine learning (optimal TTL estimation) and distributed coordination (scalable Bloom filter maintenance) happening at the server side. If you\u2019re interested in the nitty-gritty details have a look at this\u00a0 paper \u00a0or\u00a0 these slides \u00a0for a deep-dive.  Note:  Caching is active for all CRUD operations by default. Query Caching is currently in beta, if you would like to test it please contact  support@baqend.com .",
            "title": "Baqend\u2019s Cache-Sketch"
        },
        {
            "location": "/topics/caching/#configuring-freshness",
            "text": "Any new page load will always return the newest data (a fresh Bloom filter is fetched). While the app is running you can allow a configurable maximum staleness to make optimal use of the browser cache. This does not mean that you will actually see any outdated content, it just provides you with an upper bound that is never exceeded.  There are two settings affecting Bloom filter freshness that can be configured in the dashboard:   Maximum CDN staleness : this is the staleness bound for all new clients (i.e. that have not cached a Bloom fitler, yet). The default setting is to only do micro-caching of 1 second. This incurs 1 second of staleness at the maximum and protects the server from excessive load under high user volumes.  Maximum total staleness : defines the maximum staleness seen by the client (CDN staleness + client cache staleness). Internally the client makes sure to update the Bloom filter, when it gets too old.   Tip:  You can increase both staleness settings, if your application is under very heavy load. This saves you requests and prevents scalability bottlenecks if you are in the free tier.  If you want to override the total staleness in individual clients, you can set it manually:  DB.configure({\n    staleness : 10\n}).connect().then(...);  For individual operations you can optionally bypass the cache to get  strong consistency  (linearizability):  //To get the newest version via the id\nvar todo = DB.Todo.load(\"myTodo\", {refresh : true });\n\n//To update a known instance to the latest version\ntodo.load({refresh : true });",
            "title": "Configuring Freshness"
        },
        {
            "location": "/topics/caching/#local-objects",
            "text": "You can request already loaded objects using the  local  flag. It will try to give you an instance you have already loaded and only load it, if it's not present:  //If we have seen \"myTodo\" in the code we will get exactly that instance\nDB.Todo.load(\"myTodo\", {local : true }).then(...);\n\n//local is the default for the instance method\ntodo.load().then(...);\n\n//This is also useful to see your own unsaved changes, irrespective of updates from other users\ntodo.done = true;\nDB.Todo.load(\"myTodo\", {local : true }).then(function() {\n    console.log(todo.done); // true\n});",
            "title": "Local Objects"
        },
        {
            "location": "/topics/logging/",
            "text": "Logging\n\n\nAs required by many apps, we provide an easy to use logging API to log data out of your app. Additionally the Baqend dashboard shows\naccess logs which contain all the resources requested by your users.\n\n\nApp logs and Access logs are accessible through the Baqend dashboard and kept for \n30 days\n. In addition you can view, query and\nmanage the permissions of the logs like any other data you persist to Baqend. But you can't modify the schema, the\nlogged data nor the permissions of insert, update and delete operations.\n\n\nNote:\n When querying logs you must always use a date predicate, otherwise you will only get the last 5 minutes of \nthe logs.\n\n\n\nApp Logging\n\n\nThe Baqend SDK provides a simple logging API which you can use in your app as well as in Baqend code.\n\n\nThe SDK provides a simple log method which takes a log level, a message, arguments and a optional data object.\nIn addition the SDK logs the current date and the logged in user.\n\n\nLog Levels\n\n\nYou can use multiple log levels to categorize your logs. You can use one of the predefined logging levels \n\ntrace\n, \ndebug\n, \ninfo\n, \nwarn\n, \nerror\n. Log levels can later be used to filter logs.\n\n\nDB.log('debug', 'A simple debug message');\n\n\n\n\nIf you do not provide a log level, the log level becomes \ninfo\n.\n\n\nFor easier usage the log method also expose additional log methods for each log level:\n\n\nDB.log.trace('A simple trace message');\nDB.log.debug('A simple debug message');\nDB.log.info('A simple info message');\nDB.log.warn('A simple warn message');\nDB.log.error('A simple error message');\n\n\n\n\nBy default only \nerror\n, \nwarn\n and \ninfo\n logs are activated. If you want to use \ndebug\n or \ntrace\n logs or maybe deactivate one of the other levels you can specify the minimum log level to track like this:\n\n\nDB.log.level = 'debug'; // to track all logs except for 'trace'\nDB.log.level = 'warn'; // to track only 'warn' and 'error'\n\n\n\n\nLog Arguments\n\n\nIt is easy to include dynamic data into the log message. You can use placeholder in your log message which will be\nreplaced by the additional passed values.\nThe can use the placeholders \n%s\n for strings, \n%d\n for numbers and \n%j\n for a json conversion before the values are \nincluded into the log message.\n\n\nDB.log('debug', 'The value %d is greater then %d', 10, 5);\n//logs the message 'The value 10 is greater then 5'\n\n\n\n\nOften you want to log additional data, which should not be converted to a string and included into the log message itself. \nAll the log methods allows one additional argument as the last argument. The argument should be a json like object \nand will be logged in addition to the log message. \n\n\nDB.log('debug', 'The value %d is greater then %d', 10, 5, {val1: 10, val2: 5});\n//logs the message 'The value 10 is greater then 5'\n//and the data {val1: 10, val2: 5}\n\n\n\n\nYou can also use the log level helper methods:\n\n\nDB.log.debug('The value %d is greater then %d', 10, 5, {val1: 10, val2: 5});\n\n\n\n\nNote:\n App logs can be inserted by everyone by default, to restrict log insertion you can change the insert permission\nof the AppLog class in the dashboard.\n\n\n\nAccess Logs\n\n\nAccess logs will be automatically collected whenever a resource of your app is accessed through a fastly server. \n\n\nThe following data will be collected by us:\n\n\n\n\ndate - The UTC date of the access\n\n\nip - The IP address of the user\n\n\nmethod - The HTTP Method, one of (HEAD, GET, POST, PUT, DELETE, OPTIONS)\n\n\nserver - The server who has generated the log entry, indicates the fastly pop location by default\n\n\nurl - The URL of the resource that is requested\n\n\nstatus - The returned response status of the Baqend server\n\n\ndownload - The amount of data transferred to the client (includes head and body payload)\n\n\nupload - The amount of data transferred from the client (includes head and body payload)\n\n\nlatency - The latency to handle the actual request measured by the fastly server \n\n\ncacheHit - Indicates if the request was directly served by the fastly server without contacting Baqend (Cache HIT)",
            "title": "Logging"
        },
        {
            "location": "/topics/logging/#logging",
            "text": "As required by many apps, we provide an easy to use logging API to log data out of your app. Additionally the Baqend dashboard shows\naccess logs which contain all the resources requested by your users.  App logs and Access logs are accessible through the Baqend dashboard and kept for  30 days . In addition you can view, query and\nmanage the permissions of the logs like any other data you persist to Baqend. But you can't modify the schema, the\nlogged data nor the permissions of insert, update and delete operations.  Note:  When querying logs you must always use a date predicate, otherwise you will only get the last 5 minutes of \nthe logs.",
            "title": "Logging"
        },
        {
            "location": "/topics/logging/#app-logging",
            "text": "The Baqend SDK provides a simple logging API which you can use in your app as well as in Baqend code.  The SDK provides a simple log method which takes a log level, a message, arguments and a optional data object.\nIn addition the SDK logs the current date and the logged in user.",
            "title": "App Logging"
        },
        {
            "location": "/topics/logging/#log-levels",
            "text": "You can use multiple log levels to categorize your logs. You can use one of the predefined logging levels  trace ,  debug ,  info ,  warn ,  error . Log levels can later be used to filter logs.  DB.log('debug', 'A simple debug message');  If you do not provide a log level, the log level becomes  info .  For easier usage the log method also expose additional log methods for each log level:  DB.log.trace('A simple trace message');\nDB.log.debug('A simple debug message');\nDB.log.info('A simple info message');\nDB.log.warn('A simple warn message');\nDB.log.error('A simple error message');  By default only  error ,  warn  and  info  logs are activated. If you want to use  debug  or  trace  logs or maybe deactivate one of the other levels you can specify the minimum log level to track like this:  DB.log.level = 'debug'; // to track all logs except for 'trace'\nDB.log.level = 'warn'; // to track only 'warn' and 'error'",
            "title": "Log Levels"
        },
        {
            "location": "/topics/logging/#log-arguments",
            "text": "It is easy to include dynamic data into the log message. You can use placeholder in your log message which will be\nreplaced by the additional passed values.\nThe can use the placeholders  %s  for strings,  %d  for numbers and  %j  for a json conversion before the values are \nincluded into the log message.  DB.log('debug', 'The value %d is greater then %d', 10, 5);\n//logs the message 'The value 10 is greater then 5'  Often you want to log additional data, which should not be converted to a string and included into the log message itself. \nAll the log methods allows one additional argument as the last argument. The argument should be a json like object \nand will be logged in addition to the log message.   DB.log('debug', 'The value %d is greater then %d', 10, 5, {val1: 10, val2: 5});\n//logs the message 'The value 10 is greater then 5'\n//and the data {val1: 10, val2: 5}  You can also use the log level helper methods:  DB.log.debug('The value %d is greater then %d', 10, 5, {val1: 10, val2: 5});  Note:  App logs can be inserted by everyone by default, to restrict log insertion you can change the insert permission\nof the AppLog class in the dashboard.",
            "title": "Log Arguments"
        },
        {
            "location": "/topics/logging/#access-logs",
            "text": "Access logs will be automatically collected whenever a resource of your app is accessed through a fastly server.   The following data will be collected by us:   date - The UTC date of the access  ip - The IP address of the user  method - The HTTP Method, one of (HEAD, GET, POST, PUT, DELETE, OPTIONS)  server - The server who has generated the log entry, indicates the fastly pop location by default  url - The URL of the resource that is requested  status - The returned response status of the Baqend server  download - The amount of data transferred to the client (includes head and body payload)  upload - The amount of data transferred from the client (includes head and body payload)  latency - The latency to handle the actual request measured by the fastly server   cacheHit - Indicates if the request was directly served by the fastly server without contacting Baqend (Cache HIT)",
            "title": "Access Logs"
        },
        {
            "location": "/starters/",
            "text": "Angular2 and Baqend Starter\n\n\nWith this Angular2 and Baqend starter kit you can build \nblazingly fast single page applications\n in no time. Setup your project by following the simple steps below.\n\n\nThe starter is based on the \nAngular2 Webpack Starter\n and uses:\n\n\n\n\nWebpack\n as a great module bundler\n\n\nSASS\n as a CSS precompiler with cool features and syntax\n\n\nTypeScript\n for typed JavaScript, ES6 features and because it is recommended for Angular2\n\n\nBootstrap\n for easy modern styling\n\n\nBaqend\n as a fully managed backend service for backend-less development\n\n\n\n\nHow to use the template\n\n\n\n\nMake sure you have \nNode.js\n installed on your machine\n\n\nClone the repository with \ngit clone https://github.com/Baqend/angular2-starter.git\n\n\nInstall the project with \nnpm install\n\n\nStart the server with \nnpm start\n (or \nnpm run server:dev:hmr\n for \nhot module replacement\n - only changed files are recompiled)\n\n\nOpen the url in your browser \nhttp://localhost:3000\n, you should see a small sample application with signup capability\n\n\n\n\nYour app is currently connected to a Baqend test instance called 'app-starter', which provides common backend features like data and file storage, user authentication (used in the example), queries and push notifications among others.\n\n\nTo develop your own application \n\n\n\n\nLaunch a free Baqend instance at \nbaqend.com\n\n\nChange the app name in your projects \nsrc/app/db.service.ts\n from \napp-starter\n to your app name\n\n\nYour Angular2 app will automatically connect to your app instance\n\n\nTo start accessing data or backend features, simply import the \ndb\n-object with \nimport {db} from \"baqend\";\n \nand see our \nGuide\n and \nAPI Docs\n for details\n\n\n\n\nFor more information: on \nAngular2\n, the structure of this \n\nproject\n or \nBaqend\n.\n\n\nHow the Baqend integration into Angular2 works\n\n\nBefore the Baqend SDK can be used, a connection to the Baqend instance must be established. There are two options \nto wait for the initialization. \n\n\n\n\n\n\nYou can use the \nDBReady\n resolver to delay the route component rendering, or \nDBLoggedIn\n to prevent navigation to \nprotected routes that are only accessible by logged in users. For a live example look into the \nsrc/app/app.routes.ts\n.\n\n\n\n\n\n\nOr you can manually wait on \ndb.ready()\n within your components and use the SDK afterwards.\n\n\n\n\n\n\nimport {Component, OnInit} from '@angular/core';\nimport {db} from \"baqend\";\n\n@Component({\n  selector: 'myRoute'\n})\nexport class MyRoute implement OnInit {\n\n  ngOnInit(private router:Router) {\n    db.ready().then(() => {\n      db.MyClass.find()...\n    });\n  }\n\n\n\n\nHow Baqend fits your Backend requirements\n\n\nBaqend is a fully managed Backend-as-a-Service platform with a strong focus on performance and scalability (\nclick here for details\n). The \nJavaScript API\n gives you access to common backend features while the \ndashboard\n lets you define data models and access rules as well as business logic to execute on the server side.\n\n\nBaqend's feature set includes: \n\n\n\n\nAutomated Browser and CDN Caching\n\n\nScalable Data Storage\n\n\nRealtime Streaming Queries\n\n\nPowerful Search and Query Language\n\n\nPush Notifications\n\n\nUser Authentication and OAuth\n\n\nFile Storage and Hosting\n\n\nAccess Control on Object and Schema Level\n\n\n\n\n Bootstrap Baqend Starter Kit\n\n\nWith \nthis starter project\n you can easily build application based on:\n\n\n\n\nBootstrap\n for a responsive, easy-to-use frontend\n\n\nBaqend\n for hosting the application, storing data, managing users and executing server-side logic\n\n\nHandlebars\n for templating and arranging your HTML in the client\n\n\nLess\n for powerfull CSS styling\n\n\nGulp\n for building, deploying and live-reloading\n\n\n\n\nHow to use it\n\n\n$ git clone git@github.com:Baqend/bootstrap-starter.git\n$ cd bootstrap-starter\n$ npm install\n\n\n\nAfterwards, run\n\n\n$ gulp\n\n\n\n...for a local server with live-reloading anytime you change a file: \nhttp://localhost:5000\n\n\nIf gulp cannot be found, you need to install it globally with \nnpm install -g gulp\n or if you do not want to install gulp globally \nnpm run gulp\n. If you do not have npm installed, \nget it here\n.\n\n\nConnect to Baqend\n\n\nBy default this start connects to \ntoodle\n the instance of the \nBaqend tutorial\n. To change this go to app > js > main.js and change\n\n\nvar app = 'toodle';\nDB.connect(app);\n\n\n\n\nto match your Baqend app. If you do not have one yet, start \none for free\n.\n\n\nThe \nBaqend guide\n explains everything else you need to know.\n\n\nDeploy\n\n\nYou can easily deploy to Baqend via the command line, by installing it globally with \nnpm install -g baqend\n. Then:\n\n\n$ gulp dist\n$ baqend login\n$ baqend deploy -f dist your-app-name\n\n\n\nYour app is now published and available, exposing your \nindex.html\n the URL \nyour-app-name.app.baqend.com\n.\n\n\nIf you do not have \nbaqend\n installed globally, you can also use the local version of Baqend:\n\n\n$ npm run dist -- build\n$ npm run baqend -- login\n$ npm run baqend -- -f dist your-app-name\n\n\n\nNote:\n for now, you need an account registered via email, not via OAuth. If you do not have one, invite your email account via the \nCollaboration\n tab in the dashboard and use that account for the Baqend CLI.\n\n\nExample Tooling for developing with this project\n\n\n\n\nInstall \nWebstorm\n.\n\n\nFork \nthis Github project\n to have your own repository.\n\n\nClone your project via \ngit clone git@github.com:<your cloned repo>\n and import that project folder via \"File > New > Project from Existing Sources\".\n\n\nOr:\n use the dialog \"File > New > Project from Version Control > Github\" instead.\n\n\nYou can either use the Gulp plugin to run tasks or use the commands (e.g. \nnpm run gulp\n) in the terminal.\n\n\nRun gulp default (resp. \nnpm run gulp\n) and navigate to \nhttp://localhost:5000\n to see that it works.\n\n\n\n\n\n\nIonic 2 and Baqend Starter\n\n\nWith \nthis Ionic 2 and Baqend starter kit\n you can build \nblazingly fast hybrid apps\n in no time.\n\n\nThis starter is based on the \nIonic2-Tabs-Starter\n.\n\n\nHOW-TO\n\n\nThe easiest way to use this starter is to use the ionic cli:\n\n\nbash\n git clone git@github.com:Baqend/ionic2-starter.git\n cd ionic2-starter\n npm install -g ionic cordova\n npm install\n ionic serve\n\n\nThe ionic app is already connected to a Baqend test instance. To connect it to your \nown Baqend instance\n change the variable \nappName\n in the \ndb.service.ts\n to the name of your Baqend instance.\n\n\nThe app uses a \nMessage\n object, which is defined in \nthe Baqend schema\n. It has three string attributes: \nname\n, \ntext\n, \nface\n.  \n\n\nHow Baqend fits your Backend requirements\n\n\nBaqend is a fully managed Backend-as-a-Service platform with a strong focus on performance and scalability (\nclick here for details\n). The \nJavaScript API\n gives you access to common backend features while the \ndashboard\n lets you define data models and access rules as well as business logic to execute on the server side.\n\n\nBaqend's feature set includes: \n\n\n\n\nAutomated Browser and CDN Caching\n\n\nScalable Data Storage\n\n\nRealtime Streaming Queries\n\n\nPowerful Search and Query Language\n\n\nPush Notifications\n\n\nUser Authentication and OAuth\n\n\nFile Storage and Hosting\n\n\nAccess Control on Object and Schema Level\n\n\n\n\n\n\nIonic and Baqend Starter\n\n\nWith this \nIonic and Baqend starter kit\n you can build \nblazingly fast hybrid apps\n in no time.\n\n\nThis starter is based on the \nIonic-Tabs-Starter\n.\n\n\nHOW-TO\n\n\nThe easiest way to use this starter is to use the ionic cli:\n\n\n$ git clone git@github.com:Baqend/ionic-starter.git\n$ cd ionic-starter\n$ npm install -g ionic cordova\n$ npm install\n$ ionic serve\n\n\n\nThe ionic app is already connected to a Baqend test instance. To connect it to your \nown Baqend instance\n change the variable \nappName\n in the \nservice.js\n to the name of your Baqend instance. If you will use your app on iOS please\n replace \napp-starter\n with your Baqend instance name at the bottom of the \nconfig.xml\n.\n\n\nThe app uses a \nMessage\n object, which is defined in \nthe Baqend schema\n. It has three string attributes: \nname\n, \ntext\n, \nface\n.",
            "title": "Starter Kits"
        },
        {
            "location": "/starters/#angular2-and-baqend-starter",
            "text": "With this Angular2 and Baqend starter kit you can build  blazingly fast single page applications  in no time. Setup your project by following the simple steps below.  The starter is based on the  Angular2 Webpack Starter  and uses:   Webpack  as a great module bundler  SASS  as a CSS precompiler with cool features and syntax  TypeScript  for typed JavaScript, ES6 features and because it is recommended for Angular2  Bootstrap  for easy modern styling  Baqend  as a fully managed backend service for backend-less development",
            "title": "Angular2 and Baqend Starter"
        },
        {
            "location": "/starters/#how-to-use-the-template",
            "text": "Make sure you have  Node.js  installed on your machine  Clone the repository with  git clone https://github.com/Baqend/angular2-starter.git  Install the project with  npm install  Start the server with  npm start  (or  npm run server:dev:hmr  for  hot module replacement  - only changed files are recompiled)  Open the url in your browser  http://localhost:3000 , you should see a small sample application with signup capability   Your app is currently connected to a Baqend test instance called 'app-starter', which provides common backend features like data and file storage, user authentication (used in the example), queries and push notifications among others.  To develop your own application    Launch a free Baqend instance at  baqend.com  Change the app name in your projects  src/app/db.service.ts  from  app-starter  to your app name  Your Angular2 app will automatically connect to your app instance  To start accessing data or backend features, simply import the  db -object with  import {db} from \"baqend\";  \nand see our  Guide  and  API Docs  for details   For more information: on  Angular2 , the structure of this  project  or  Baqend .",
            "title": "How to use the template"
        },
        {
            "location": "/starters/#how-the-baqend-integration-into-angular2-works",
            "text": "Before the Baqend SDK can be used, a connection to the Baqend instance must be established. There are two options \nto wait for the initialization.     You can use the  DBReady  resolver to delay the route component rendering, or  DBLoggedIn  to prevent navigation to \nprotected routes that are only accessible by logged in users. For a live example look into the  src/app/app.routes.ts .    Or you can manually wait on  db.ready()  within your components and use the SDK afterwards.    import {Component, OnInit} from '@angular/core';\nimport {db} from \"baqend\";\n\n@Component({\n  selector: 'myRoute'\n})\nexport class MyRoute implement OnInit {\n\n  ngOnInit(private router:Router) {\n    db.ready().then(() => {\n      db.MyClass.find()...\n    });\n  }",
            "title": "How the Baqend integration into Angular2 works"
        },
        {
            "location": "/starters/#how-baqend-fits-your-backend-requirements",
            "text": "Baqend is a fully managed Backend-as-a-Service platform with a strong focus on performance and scalability ( click here for details ). The  JavaScript API  gives you access to common backend features while the  dashboard  lets you define data models and access rules as well as business logic to execute on the server side.  Baqend's feature set includes:    Automated Browser and CDN Caching  Scalable Data Storage  Realtime Streaming Queries  Powerful Search and Query Language  Push Notifications  User Authentication and OAuth  File Storage and Hosting  Access Control on Object and Schema Level",
            "title": "How Baqend fits your Backend requirements"
        },
        {
            "location": "/starters/#bootstrap-baqend-starter-kit",
            "text": "With  this starter project  you can easily build application based on:   Bootstrap  for a responsive, easy-to-use frontend  Baqend  for hosting the application, storing data, managing users and executing server-side logic  Handlebars  for templating and arranging your HTML in the client  Less  for powerfull CSS styling  Gulp  for building, deploying and live-reloading",
            "title": "Bootstrap Baqend Starter Kit"
        },
        {
            "location": "/starters/#how-to-use-it",
            "text": "$ git clone git@github.com:Baqend/bootstrap-starter.git\n$ cd bootstrap-starter\n$ npm install  Afterwards, run  $ gulp  ...for a local server with live-reloading anytime you change a file:  http://localhost:5000  If gulp cannot be found, you need to install it globally with  npm install -g gulp  or if you do not want to install gulp globally  npm run gulp . If you do not have npm installed,  get it here .",
            "title": "How to use it"
        },
        {
            "location": "/starters/#connect-to-baqend",
            "text": "By default this start connects to  toodle  the instance of the  Baqend tutorial . To change this go to app > js > main.js and change  var app = 'toodle';\nDB.connect(app);  to match your Baqend app. If you do not have one yet, start  one for free .  The  Baqend guide  explains everything else you need to know.",
            "title": "Connect to Baqend"
        },
        {
            "location": "/starters/#deploy",
            "text": "You can easily deploy to Baqend via the command line, by installing it globally with  npm install -g baqend . Then:  $ gulp dist\n$ baqend login\n$ baqend deploy -f dist your-app-name  Your app is now published and available, exposing your  index.html  the URL  your-app-name.app.baqend.com .  If you do not have  baqend  installed globally, you can also use the local version of Baqend:  $ npm run dist -- build\n$ npm run baqend -- login\n$ npm run baqend -- -f dist your-app-name  Note:  for now, you need an account registered via email, not via OAuth. If you do not have one, invite your email account via the  Collaboration  tab in the dashboard and use that account for the Baqend CLI.",
            "title": "Deploy"
        },
        {
            "location": "/starters/#example-tooling-for-developing-with-this-project",
            "text": "Install  Webstorm .  Fork  this Github project  to have your own repository.  Clone your project via  git clone git@github.com:<your cloned repo>  and import that project folder via \"File > New > Project from Existing Sources\".  Or:  use the dialog \"File > New > Project from Version Control > Github\" instead.  You can either use the Gulp plugin to run tasks or use the commands (e.g.  npm run gulp ) in the terminal.  Run gulp default (resp.  npm run gulp ) and navigate to  http://localhost:5000  to see that it works.",
            "title": "Example Tooling for developing with this project"
        },
        {
            "location": "/starters/#ionic-2-and-baqend-starter",
            "text": "With  this Ionic 2 and Baqend starter kit  you can build  blazingly fast hybrid apps  in no time.  This starter is based on the  Ionic2-Tabs-Starter .",
            "title": "Ionic 2 and Baqend Starter"
        },
        {
            "location": "/starters/#how-to",
            "text": "The easiest way to use this starter is to use the ionic cli:  bash\n git clone git@github.com:Baqend/ionic2-starter.git\n cd ionic2-starter\n npm install -g ionic cordova\n npm install\n ionic serve  The ionic app is already connected to a Baqend test instance. To connect it to your  own Baqend instance  change the variable  appName  in the  db.service.ts  to the name of your Baqend instance.  The app uses a  Message  object, which is defined in  the Baqend schema . It has three string attributes:  name ,  text ,  face .",
            "title": "HOW-TO"
        },
        {
            "location": "/starters/#how-baqend-fits-your-backend-requirements_1",
            "text": "Baqend is a fully managed Backend-as-a-Service platform with a strong focus on performance and scalability ( click here for details ). The  JavaScript API  gives you access to common backend features while the  dashboard  lets you define data models and access rules as well as business logic to execute on the server side.  Baqend's feature set includes:    Automated Browser and CDN Caching  Scalable Data Storage  Realtime Streaming Queries  Powerful Search and Query Language  Push Notifications  User Authentication and OAuth  File Storage and Hosting  Access Control on Object and Schema Level",
            "title": "How Baqend fits your Backend requirements"
        },
        {
            "location": "/starters/#ionic-and-baqend-starter",
            "text": "With this  Ionic and Baqend starter kit  you can build  blazingly fast hybrid apps  in no time.  This starter is based on the  Ionic-Tabs-Starter .",
            "title": "Ionic and Baqend Starter"
        },
        {
            "location": "/starters/#how-to_1",
            "text": "The easiest way to use this starter is to use the ionic cli:  $ git clone git@github.com:Baqend/ionic-starter.git\n$ cd ionic-starter\n$ npm install -g ionic cordova\n$ npm install\n$ ionic serve  The ionic app is already connected to a Baqend test instance. To connect it to your  own Baqend instance  change the variable  appName  in the  service.js  to the name of your Baqend instance. If you will use your app on iOS please\n replace  app-starter  with your Baqend instance name at the bottom of the  config.xml .  The app uses a  Message  object, which is defined in  the Baqend schema . It has three string attributes:  name ,  text ,  face .",
            "title": "HOW-TO"
        },
        {
            "location": "/roadmap/",
            "text": "Roadmap\n\n\nIn this roadmap you will find what we're thinking about, what we're working on now, and what we've done recently.\n\n\nSee the \nSubmit Card\n to post your own ideas in the comments!\n\n\nYou can \ncomment\n on any feature to express your ideas, thoughts, and suggestions.\n\nUpvote\n the features you want to see implemented first.\nClick into any of the cards to open the Trello-based roadmap in a new tab.\n\n\nSee the roadmap board on Trello\n\n\n\n  \n\n\n\n\n\nNote:\n We are open for any feature suggestions you have. Feel free to send an email to \nsupport@baqend.com\n or post one in the chat.",
            "title": "Roadmap"
        },
        {
            "location": "/roadmap/#roadmap",
            "text": "In this roadmap you will find what we're thinking about, what we're working on now, and what we've done recently.  See the  Submit Card  to post your own ideas in the comments!  You can  comment  on any feature to express your ideas, thoughts, and suggestions. Upvote  the features you want to see implemented first.\nClick into any of the cards to open the Trello-based roadmap in a new tab.  See the roadmap board on Trello  \n     Note:  We are open for any feature suggestions you have. Feel free to send an email to  support@baqend.com  or post one in the chat.",
            "title": "Roadmap"
        }
    ]
}