{"id":22799975,"url":"https://github.com/dadi/api-wrapper-core","last_synced_at":"2025-04-19T16:53:22.410Z","repository":{"id":57105407,"uuid":"75391462","full_name":"dadi/api-wrapper-core","owner":"dadi","description":"Core high-level methods for interacting with DADI API","archived":false,"fork":false,"pushed_at":"2019-11-02T02:35:48.000Z","size":121,"stargazers_count":2,"open_issues_count":5,"forks_count":2,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-29T10:33:30.703Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dadi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-02T11:52:42.000Z","updated_at":"2019-05-07T09:04:34.000Z","dependencies_parsed_at":"2022-08-20T23:50:08.132Z","dependency_job_id":null,"html_url":"https://github.com/dadi/api-wrapper-core","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadi%2Fapi-wrapper-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadi%2Fapi-wrapper-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadi%2Fapi-wrapper-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadi%2Fapi-wrapper-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dadi","download_url":"https://codeload.github.com/dadi/api-wrapper-core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248868419,"owners_count":21174751,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-12T07:10:39.930Z","updated_at":"2025-04-19T16:53:22.377Z","avatar_url":"https://github.com/dadi.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DADI API wrapper (core)\n\n\u003e Core high-level methods for interacting with DADI API\n\n[![npm (scoped)](https://img.shields.io/npm/v/@dadi/api-wrapper-core.svg?maxAge=10800\u0026style=flat-square)](https://www.npmjs.com/package/@dadi/api-wrapper-core)\n[![Coverage Status](https://coveralls.io/repos/github/dadi/api-wrapper-core/badge.svg?branch=master)](https://coveralls.io/github/dadi/api-wrapper-core?branch=master)\n[![Build Status](https://travis-ci.org/dadi/api-wrapper-core.svg?branch=master)](https://travis-ci.org/dadi/api-wrapper-core)\n[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/)\n\n## Overview\n\n[DADI API](https://github.com/dadi/api) is a high performance RESTful API layer designed in support of API-first development and the principle of COPE.\n\nThis package exposes a set of chainable methods that allow developers to compose complex read and write operations using a simplistic and natural syntax, providing a high-level abstraction of the REST architectural style.\n\nIt can be used as a standalone module to generate request objects containing information about the HTTP verb, URL and payload, or used in conjunction with [DADI API Wrapper](https://github.com/dadi/api-wrapper) to provide a full-featured API consumer, capable of handling authentication and the HTTP communication.\n\n## Getting started\n\n1. Install the `@dadi/api-wrapper-core` module:\n\n   ```shell\n   npm install @dadi/api-wrapper-core --save\n   ```\n\n2. Add the library and configure the API settings:\n\n   ```js\n   const APIWrapper = require('@dadi/api-wrapper-core')\n\n   const api = new APIWrapper({\n     uri: 'http://api.example.com',\n     port: 80,\n     version: 'vjoin',\n     database: 'testdb'\n   })\n   ```\n\n3. Make a query:\n\n   ```js\n   // Example: getting all documents where `name` contains \"john\" and age is greater than 18\n   const requestObject = api\n    .in('users')\n    .whereFieldContains('name', 'john')\n    .whereFieldIsGreaterThan('age', 18)\n    .find()\n   ```\n\n## Methods\n\nEach query consists of a series of chained methods to form the request, always containing a terminator method. Terminators return a Promise with the result of one or more requests to the database and can make use of a series of [filtering methods](#filters) to create the desired subset of documents to operate on.\n\n### Terminators\n\n#### `.create()`\n\nCreates a document.\n\n```js\n// Example\napi.in('users')\n   .create({\n      name: 'John Doe',\n      age: 45,\n      address: '123 Fake St'\n   })\n   .then(function (doc) {\n      console.log('New document:', doc)\n   })\n   .catch(function (err) {\n      console.log('! Error:', err)\n   })\n```\n\n*Output:*\n\n```json\n{\n  \"body\": {\n    \"name\": \"John Doe\",\n    \"age\": 45,\n    \"address\": \"123 Fake St\"\n  },\n  \"method\": \"POST\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/vjoin/testdb/users\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/vjoin/testdb/users\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n\n#### `.delete()`\n\nDeletes one or more documents.\n\n```js\napi.in('users')\n   .whereFieldDoesNotExist('name')\n   .delete()\n```\n\n*Output:*\n\n```json\n{\n  \"body\": {\n    \"query\": {\n      \"name\": {\n        \"$eq\": null\n      }\n    }\n  },\n  \"method\": \"DELETE\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/vjoin/testdb/users\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/vjoin/testdb/users\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n#### `.find()`\n\nReturns a list of documents.\n\n```js\napi.in('users')\n   .whereFieldIsGreaterThan('age', 21)\n   .useFields(['name', 'age'])\n   .find()\n```\n\n*Output:*\n\n```json\n{\n  \"method\": \"GET\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/vjoin/testdb/users?filter={\\\"age\\\":{\\\"$gt\\\":21}}\u0026fields={\\\"name\\\":1,\\\"age\\\":1}\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/vjoin/testdb/users?filter={\\\"age\\\":{\\\"$gt\\\":21}}\u0026fields={\\\"name\\\":1,\\\"age\\\":1}\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n#### `.getCollections()`\n\nGets the list of collections for the API.\n\n```js\napi.getCollections()\n```\n\n*Output:*\n\n```json\n{\n  \"method\": \"GET\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/api/collections\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/api/collections\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n#### `.getConfig()`\n\nGets the config for a collection or for the API.\n\n```js\n// Gets the collection config\napi.in('users')\n   .getConfig()\n```\n\n*Output:*\n\n```json\n{\n  \"method\": \"GET\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/vjoin/testdb/users/config\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/vjoin/testdb/users/config\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n```js\n// Gets the API config\napi.getConfig()\n```\n\n*Output:*\n\n```json\n{\n  \"method\": \"GET\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/api/config\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/api/config\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n#### `.getSignedUrl()`\n\nGets a signed URL from a media collection.\n\n```js\napi.in('images')\n   .getSignedUrl({\n    fileName: \"foobar.jpg\"\n   })\n```\n\n*Output:*\n\n```json\n{\n  \"body\": {\n    \"fileName\": \"foobar.jpg\"\n  },\n  \"method\": \"POST\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/media/images/sign\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/media/images/sign\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n#### `.getStats()`\n\nGets collection stats.\n\n```js\napi.in('users')\n   .getStats()\n```\n\n*Output:*\n\n```json\n{\n  \"method\": \"GET\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/api/stats\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/api/stats\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n#### `.getStatus()`\n\nGets the the API status.\n\n```js\napi.getStatus()\n```\n\n*Output:*\n\n```json\n{\n  \"method\": \"POST\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/api/status\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/api/status\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n#### `.setConfig()`\n\nSets the config for a collection or for the API.\n\n```js\n// Sets the collection config\nvar collectionConfig = {cache: false}\n\napi.in('users')\n   .setConfig(collectionConfig)\n```\n\n*Output:*\n\n```json\n{\n  \"body\": {\n    \"cache\": false\n  },\n  \"method\": \"POST\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/vjoin/testdb/users/config\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/vjoin/testdb/users/config\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n```js\n// Sets the API config\nvar apiConfig = {cors: true}\n\napi.setConfig(apiConfig)\n```\n\n*Output:*\n\n```json\n{\n  \"body\": {\n    \"cors\": true\n  },\n  \"method\": \"POST\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/api/config\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/api/config\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n#### `.update(update)`\n\nUpdates a list of documents.\n\n```js\napi.in('users')\n   .whereFieldIsLessThan('age', 18)\n   .update({\n      adult: false\n   })\n```\n\n*Output:*\n\n```json\n{\n  \"body\": {\n    \"query\": {\n      \"age\": {\n        \"$lt\": 18\n      }\n    },\n    \"update\": {\n      \"adult\": false\n    }\n  },\n  \"method\": \"PUT\",\n  \"uri\": {\n    \"href\": \"http://api.example.com:80/vjoin/testdb/users\",\n    \"hostname\": \"api.example.com\",\n    \"path\": \"/vjoin/testdb/users\",\n    \"port\": \"80\",\n    \"protocol\": \"http:\"\n  }\n}\n```\n\n### Filters\n\nFiltering methods are used to create a subset of documents that will be affected by subsequent operation terminators.\n\n#### `.goToPage(page)`\n\nDefines the page of documents to be used.\n\n```js\n// Example\napi.goToPage(3)\n```\n\n#### `.limitTo(limit)`\n\nDefines a maximum number of documents to be retrieved.\n\n```js\n// Example\napi.limitTo(10)\n```\n\n#### `.sortBy(field, order)`\n\nSelects a field to sort on and the sort direction. Order defaults to ascending (`asc`).\n\n```js\n// Example\napi.sortBy('age', 'desc')\n```\n\n#### `.useFields(fields)`\n\nSelects the fields to be returned in the response. Accepts array format.\n\n```js\n// Example\napi.useFields(['name', 'age'])\n```\n\n#### `.where(query)`\n\nFilters documents using a MongoDB query object or a Aggregation Pipeline array. The methods above are ultimately just syntatic sugar for `where()`. This method can be used for complex queries that require operations not implemented by any other method.\n\n```js\n// Example\napi.where({name: 'John Doe'})\n```\n\n#### `.whereFieldBeginsWith(field, text)`\n\nFilters documents where `field` begins with `text`.\n\n```js\n// Example\napi.whereFieldBeginsWith('name', 'john')\n```\n\n#### `.whereFieldContains(field, text)`\n\nFilters documents where `field` contains `text`.\n\n```js\n// Example\napi.whereFieldContains('name', 'john')\n```\n\n#### `.whereFieldDoesNotContain(field, text)`\n\nFilters documents `field` does not contain `text`.\n\n```js\n// Example\napi.whereFieldDoesNotContain('name', 'john')\n```\n\n#### `.whereFieldEndsWith(field, text)`\n\nFilters documents where field starts with `text`.\n\n```js\n// Example\napi.whereFieldEndsWith('name', 'john')\n```\n\n#### `.whereFieldExists(field)`\n\nFilters documents that contain a field.\n\n```js\n// Example\napi.whereFieldExists('name')\n```\n\n#### `.whereFieldDoesNotExist(field)`\n\nFilters documents that do not contain a field.\n\n```js\n// Example\napi.whereFieldDoesNotExist('address')\n```\n\n#### `.whereFieldIsEqualTo(field, value)`\n\nFilters documents where `field` is equal to `value`.\n\n```js\n// Example\napi.whereFieldIsEqualTo('age', 53)\n```\n\n#### `.whereFieldIsGreaterThan(field, value)`\n\nFilters documents where `field` is greater than `value`.\n\n```js\n// Example\napi.whereFieldIsGreaterThan('age', 18)\n```\n\n#### `.whereFieldIsGreaterThanOrEqualTo(field, value)`\n\nFilters documents where `field` is greater than or equal to `value`.\n\n```js\n// Example\napi.whereFieldIsGreaterThanOrEqualTo('age', 19)\n```\n\n#### `.whereFieldIsLessThan(field, value)`\n\nFilters documents where `field` is less than `value`.\n\n```js\n// Example\napi.whereFieldIsLessThan('age', 65)\n```\n\n#### `.whereFieldIsLessThanOrEqualTo(field, value)`\n\nFilters documents where `field` is less than or equal to `value`.\n\n```js\n// Example\napi.whereFieldIsLessThanOrEqualTo('age', 64)\n```\n\n#### `.whereFieldIsOneOf(field, matches)`\n\nFilters documents where the value of `field` is one of the elements of `matches`.\n\n```js\n// Example\napi.whereFieldIsOneOf('name', ['John', 'Jack', 'Peter'])\n```\n\n#### `.whereFieldIsNotEqualTo(field, value)`\n\nFilters documents where `field` is not equal to `value`.\n\n```js\n// Example\napi.whereFieldIsEqualTo('age', 53)\n```\n\n#### `.whereFieldIsNotOneOf(field, matches)`\n\nFilters documents where the value of `field` is not one of the elements of `matches`.\n\n```js\n// Example\napi.whereFieldIsNotOneOf('name', ['Mark', 'Nathan', 'David'])\n```\n\n#### `.whereHookNameIs(name)`\n\nSelects the hook with a given name.\n\n```js\n// Example\napi.whereFieldIsNotOneOf('name', ['Mark', 'Nathan', 'David'])\n```\n\n#### `.withComposition(value)`\n\nDefines whether nested documents should be resolved using composition. The default is to let API decide based on the queried collection's settings.\n\n```js\n// Example\napi.withComposition()\napi.withComposition(true) // same as above\napi.withComposition(false)\n```\n\n### Other methods\n\n#### `.fromEndpoint(endpoint)`\n\nSelects a custom endpoint to use. Please note that unlike collections, custom endpoints do not have a standardised syntax, so it is up to the authors to make sure the endpoint complies with standard DADI API formats, or they will not function as expected.\n\n```js\n// Example\napi.fromEndpoint('custom-endpoint')\n```\n\n#### `.in(collection)`\n\nSelects the collection to use.\n\n```js\n// Example\napi.in('users')\n```\n\n#### `.inHooks()`\n\nSelects \"hook mode\", meaning filters and terminators will operate on hooks and not on documents.\n\n```js\n// Example\napi.inMedia('images')\n```\n\n#### `.inMedia(bucket)`\n\nSelects a media bucket to be used.\n\n```js\n// Example\napi.inMedia('images')\n```\n\n#### `.useDatabase(database)`\n\nSelects the database to use. Overrides any database defined in the initialisation options, and is reset when called without arguments.\n\n```js\n// Example\napi.useDatabase('testdb')\n```\n\n#### `.useVersion(version)`\n\nSelects the version to use. Overrides any version defined in the initialisation options, and is reset when called without arguments.\n\n```js\n// Example\napi.useVersion('1.0')\n```\n\n### Defining a callback\n\nBy default, calling a terminator will return a request object, which is a plain JavaScript object formed of `method`, `uri` and, optionally, `body`. Alternatively, you can choose to specify what exactly terminators will return, by defining a callback that will be executed before they return. This callback will receive the request object as an argument, giving you the option to modify it or wrap it with something else.\n\nA callback is defined by setting a `callback` property on the options object used to initialise API wrapper.\n\n```js\nconst APIWrapper = require('@dadi/api-wrapper-core')\n\nconst api = new APIWrapper({\n  uri: 'http://api.example.com',\n  port: 80,\n  version: 'vjoin',\n  database: 'testdb',\n  callback: function (requestObject) {\n    // This callback will return a JSON-stringified version\n    // of the request object.\n    return JSON.stringify(requestObject)\n  }\n})\n```\n\n### Debug mode\n\nWith debug mode, you'll be able to see exactly how the requests made to API look like. This functionality is enabled by setting a `debug` property in the config:\n\n```js\nconst APIWrapper = require('@dadi/api-wrapper-core')\nconst api = new APIWrapper({\n  uri: 'http://api.example.com',\n  port: 80,\n  version: 'vjoin',\n  database: 'testdb',\n  debug: true\n})\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdadi%2Fapi-wrapper-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdadi%2Fapi-wrapper-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdadi%2Fapi-wrapper-core/lists"}