{"id":18736656,"url":"https://github.com/radiergummi/vue-abstract-api","last_synced_at":"2026-05-03T09:37:45.293Z","repository":{"id":88617341,"uuid":"130350222","full_name":"Radiergummi/vue-abstract-api","owner":"Radiergummi","description":"A lean, OOP API abstraction layer","archived":false,"fork":false,"pushed_at":"2018-05-21T12:23:20.000Z","size":1050,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-28T16:46:33.892Z","etag":null,"topics":["api-client","javascript","rest-api","rpc-api","vue","vuejs2"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Radiergummi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-20T10:56:23.000Z","updated_at":"2018-05-28T09:20:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"7f69675b-6576-433a-af29-131219932c68","html_url":"https://github.com/Radiergummi/vue-abstract-api","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Radiergummi%2Fvue-abstract-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Radiergummi%2Fvue-abstract-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Radiergummi%2Fvue-abstract-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Radiergummi%2Fvue-abstract-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Radiergummi","download_url":"https://codeload.github.com/Radiergummi/vue-abstract-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239611992,"owners_count":19668274,"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":["api-client","javascript","rest-api","rpc-api","vue","vuejs2"],"created_at":"2024-11-07T15:22:00.731Z","updated_at":"2025-11-16T18:30:12.842Z","avatar_url":"https://github.com/Radiergummi.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue-abstract-api\n\u003e This is a lean API connector for Vue.js (though there is no dependency on it: You can use this in any framework you'd like to).\n\n\n## Features\n - Abstraction of endpoints and resources into extendable classes\n - Flexible configuration using class properties\n - Well documented, readable code\n - Adapts to almost any API structure\n - Lightweight layer on top of [axios](https://github.com/axios/axios)\n\n**You can try it here: [radiergummi.github.io/vue-abstract-api](https://radiergummi.github.io/vue-abstract-api/)**\n\n## Installation\nTo install the plugin, just `npm install` it.\n\n```bash\nnpm install vue-abstract-api\n```\n\nFor development/to preview the example app (not complete yet, but working):\n```bash\ncd vue-abstract-api\nnpm install\n\nnpm run build // to build the library\nnpm run example:start // to start the example app on port 8080\nnpm run example:build // to build the example app\n```\n\n## Usage\nTo use vue-abstract-api, you'll first need to set up your configuration. Please refer to [the configuration section](#configuration) before proceeding; for now, we'll the following example configuration:\n\n```js\nimport Cats from './Cats';\nimport Dogs from './Dogs';\n\nexport default {\n    baseUrl:   'https://api.example.tld/v1',\n    endpoints: [ Cats, Dogs ]\n}\n```\n\n\nLastly, insert the following *before* constructing your app:\n\n```js\nimport Vue from 'vue';\nimport VueAbstractApi from 'vue-abstract-api';\n\n// import your configuration here\nimport myApiConfig from './apiConfig';\n\n// install the plugin\nVue.use( VueAbstractApi, myApiConfig );\n```\n\nThat's it, you're ready to use the following in your components:\n```js\n// ...\n\n    const twentyBlackCats = await this.$api.cats\n        .paginate(20)\n        .filterBy('color_fur_eq', 'black')\n        .filterBy('color_eyes_eq', 'orange')\n        .index();\n\n    // twentyBlackCats.results === [ { cat } , ... ]\n    // twentyBlackCats.total === 5124\n    // twentyBlackCats.count === 20\n    // twentyBlackCats.first === { cat }\n    // twentyBlackCats.last === { cat }\n\n    this.$api.cats.update(twentyBlackCats.first.id, {\n        adopted: true,\n        reason:  'SHE IS SO BEAUTIFUL 😍'\n    });\n```\n\nTo find out on how to wire things together, read on.\n\n\n## Configuration\nThere are two means of configuration:\n\n### 1. The API configuration (file)\nThe API configuration is a plain object with two required parameters: The `baseURL` which holds the common shared URL for all of your endpoints, and `endpoints`, an Array holding all of said endpoints.\nWhat you want to do here is put in all of your endpoint classes (no instances) just as you imported them so the plugin knows about them. In the background, the endpoints will be *mounted* on the `Api` instance, providing them with access to the HTTP driver and more.\n\nAdditional available, optional options:\n\n#### `headers`\nKey-value map of headers to append to every request.\n\n#### `authentication`\nObject with the properties `username` and `password`. They will be directly passed to axios, therefore transformed into an `Authorization: Basic ${username}:${password}` header. See [here](https://github.com/axios/axios#request-config).\n\n#### `interceptors`\nObject with the properties `request` and `response`. Both can contain the respective interceptors and will be directly passed down to axios. See [here](https://github.com/axios/axios#interceptors).\nInterceptors must be passed as objects like this:\n\n```js\ninterceptors: {\n\n    // request interceptors\n    request: [\n\n        // a single interceptor\n        {\n            // required, we need at least the success interceptor\n            success: request =\u003e {\n                // handle the request, return it back\n                return request;\n            },\n\n            // optional, passing a success handler is enough\n            error: response =\u003e {}\n        }\n    ],\n\n    // response interceptors - see above\n    response: []\n}\n```\n\nWhat's **not** included right now is to change the content-type to anything but JSON. That will likely change soon, though.\n\nYou can either put that configuration object in a separate file for readability, or just throw all the imports in your `main.js`.\n\n### 2. The endpoint classes\nEndpoints, in this plugins terms, are classes that represent an endpoint on the remote API. Since they extend the provided classes and each configuration option has a sensible default, ideally, your full endpoint file looks like this:\n\n```js\nimport Resource from '@vue-abstract-api/Resource';\n\nclass Point extends Resource {\n}\n\nexport default Point;\n```\n\nThere are two base classes available; configuration is the same no matter which one you use.\n\n#### `Endpoint`\nThis class provides access to the HTTP methods and should be used for non-REST, RPC or otherwise irregular API endpoints. Just define a method named like the action you are going to carry out, wire up the right API call (using `this.get('/foo')`, for example), and you're good to go.\n\n#### `Resource` *(Inherits from Endpoint)*\nThis class provides several pre-defined methods for working with data collection endpoints, aka resources. These methods include `index`, `all`, `one`, `create`, `update` and `destroy`. You'll probably use these most of the time when working with CRUD resources.\n\nAll configuration happens via static property getters. This has several advantages:\n - Properties are shared across all endpoint instances\n - They can be overridden from anywhere in the chain, including instances\n - Their types are documented and available via TypeScript definitions (included)\n\nAdditionally, any methods accept an options object as their last parameter that will get passed down to axios.\n\n#### Configuration options\nThe following list shows all available getters. To view an example of a fully configured endpoint, take a look at [`examples/endpoints/Photos`](./examples/endpoints/Photos.js).\n\n##### `path`\nRetrieves the endpoint API path that will be attached to the base URL. If you omit this, the path is automaticallygenerated from the lower-cased class name.  \nThis must be a string.\n\n```js\nstatic get path () {\n  return '/photos';\n}\n```\n\n##### `cachable`\nWhether this endpoint is cachable. If this property is true, any GET response will be stored in a cache `Map` (keyed by the final request URL). On subsequent requests, instead of performing another HTTP request, the cached Response object is returned, resulting in immediate responses.  \nYou can still skip the cache lookup by passing the `cache: false` option on requests, however.  \nBe aware of the implications, though: The cache has no automatic TTL, so you need to flush the cache manually using the `flushCache()` method, if necessary.  \nTODO: Ideally, all the writing methods should intelligently figure out the consequences of their actions, flushing the entire cache or just partials after execution.\n\nResponses that have been served from cache have the property `fromCache` set to true.\n\n```js\nstatic get cachable () {\n  return true;\n}\n```\n\n##### `parameterNames`\nRetrieves the parameter names. Now this one is almost a must for your endpoints: It allows you to set \"alias\" names for common parameters vue-abstract-api provides special modifiers for.  \nThat is, you can chain `.paginate()` before your method call, resulting in the appropriate parameters being attached to your requests. To make this work, we need to know which parameters to use, so using this getter, you can define your own.  \nThe list of available aliases and their defaults is as follows:\n\n| alias name           | default value  | comment                                                    |\n|:---------------------|:---------------|:-----------------------------------------------------------|\n| limit                | limit          | used to set the number of items per page in paginated mode |\n| offset               | offset         | used to set the offset from the previous request           |\n| orderDirection       | direction      | used to set the direction the results should be ordered in |\n| orderColumn          | order_column   | used to set the column the results should be ordered by    |\n| multipleOrderColumns | order_columns  | used to set multiple ordering columns                      |\n| filterColumns        | filter_columns |  used to set multiple filtering columns                    |\n\nNow anywhere in your app you use \"limit\", it will result in the correct parameter being attached to the request URL, no matter what endpoint you're using it on.\n\nTo disable some parameters (for example because their value should be directly appended to the URL),  set them to `null`.\nRead on regarding filters and ordering.\n\n```js\n  static get parameterNames () {\n    return {\n      limit:                'limit',\n      offset:               'offset',\n      orderDirection:       'direction',\n      orderColumn:          'order_column',\n      multipleOrderColumns: 'order_columns',\n      filterColumns:        null\n    };\n  }\n```\n\n##### `defaultParameters`\nRetrieves the default parameters for each request. This must return an object containing any of the request options available; it is up to you to figure out which ones. By default, this will add pagination limited to 10 results, sorting is set to ascending.  \nDefault parameters are a powerful tool - they allow you to configure different settings for your application views, while sticking with the globally valid parameter names.\n\n```js\nstatic get defaultParameters () {\n  return {\n    paginate:             true,\n    limit:                10,\n    offset:               0,\n    orderDirection:       'ASC',\n    multipleOrderColumns: false\n  };\n}\n```\n\n\n##### `mapResults`\nRetrieves a mapper function to figure out results and meta data. By default, we assume the API just returns all matched entities as an array, without any additional meta data - there may be cases though where your response data is wrapped inside a `results` field, for example. This callback allows you to unwrap the results and set more meta fields on your responses.\nAs I said you can set additional meta data fields here, the most popular being \"count\" and \"total\". Count reflects the number of retrieved items (usually the length of the response data, but there are additional concerns where using an API-provided value might be better), Total is the total number of available, matching entities on the server. This is most useful for paginated results.\nBeyond these, there might be more fields you want to populate. The `ApiResponse` object will provide getters for any of them, so what you want to do here is populate the fields with values from the response data.  \nSince we receive the actual `AxiosResponse` object here, we also have access to headers and so on.  \n\nThe only mandatory key in the return object is \"results\". Count will be set to the results length, total to \"-1\" if missing.\n\n```js\nstatic get mapResults () {\n  return response =\u003e {\n    const results = Array.from( response.data );\n    \n    return {\n      results: results,\n      count:   results.length,\n      total:   response.headers[ 'X-Total-Count' ]\n    };\n  };\n}\n```\n\n##### `mapFilters`\nRetrieves a mapper function to assemble the filter parameter value. This might sound a little\ncomplicated first, but bear with me: if you decide to filter your results, a parameter named\n\"filter_columns\" (or whatever you set in defaultParameterNames for filterColumns) will be\nappended to your request URL. The value of this property might require a special format to be\nunderstood by your API, so this callback gives you a possibility to create the string on your\nown. What you will receive is an object structured as `{ \"my-FieldName\": \"filter value\"}`,\nso the below approach to map the entries might work best.\nWhatever the output you require, just return a string in the end.\n\nBy default, the output looks like so:\n`'my-FieldName:filter value,my-other_field:123,foo:true'`\n\n```js\nstatic get mapFilters () {\n  return filters =\u003e Object\n    .entries( filters )\n    .map( ( [ field, value ] ) =\u003e `${field}:${value}` )\n    .join( ',' );\n}\n```\n\n##### `mapOrders`\nRetrieves a mapper function to assemble the order parameter value, should you use multiple field ordering. The same things said for \"mapFilters\" apply here, too: Multi-ordering might be complex in your application, so you can use this to create a custom field value.\n\n```js\nstatic get mapOrders () {\n  return orders =\u003e Object\n    .entries( orders )\n    .map( ( [ field, direction ] ) =\u003e `${field}:${direction}` )\n    .join( ',' );\n}\n```\n\n## Compatibility with other frameworks (React, Angular, [Vanilla](http://vanilla-js.com/))\nBasically, [src/index.js](./src/index.js) provides a Vue plugin. There is nothing special happening there you wouldn't be able to recreate in any other framework. Important are just the following lines:\n\n```js\nVue.prototype.$api = new Api( options.baseUrl, options );\n\n    for ( let EndpointClass of options.endpoints ) {\n      Vue.prototype.$api.mount( new EndpointClass() );\n    }\n```\n\nwhich translate directly to:\n\n```js\nconst api = new Api( options.baseUrl, options );\n\n    for ( let EndpointClass of options.endpoints ) {\n        api.mount( new EndpointClass() );\n    }\n```\n\nIf there is anyone interested in providing plugins for other frameworks and would be willing to create a PR, I'll merge it.\n\n## Contribution\nI'm happy for anyone contributing code! Ideas:\n\n - Implement testing\n - Automatic, selective cache purging\n - More examples\n -\n\nSprinkled throughout this readme are several other points that could be improved upon. If you're unsure, just open an issue.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradiergummi%2Fvue-abstract-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fradiergummi%2Fvue-abstract-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradiergummi%2Fvue-abstract-api/lists"}