💎 Elegant and simple way to build requests for REST API

Overview

Elegant and simple way to build requests for REST API

This package helps you quickly to build requests for REST API. Move your logic and backend requests to dedicated classes. Keep your code clean and elegant.

🔥 If you use Laravel, this package matches perfectly with spatie/laravel-query-builder.

Links

Contributors

Thanks to the following people who have contributed to this project:

See all contributors

Thanks

Why another package if we have those? Because currently (march, 2018) they restricted backend response to JSON API specification.

Contact

Twitter @robsontenorio

Issues
  • Fix for $find to use a constructor on the result

    Fix for $find to use a constructor on the result

    Fixes the result of find not being able to use methods such as save because it wasn't using a constructor.

    opened by rossity 21
  • Implement Model.withoutWrapping to return full response when set to false

    Implement Model.withoutWrapping to return full response when set to false

    Fixes #54

    You can disable response unwrapping by setting one simple var:

    Model.withoutWrapping = false
    

    Tests included, please let me know if you can merge it 👍

    Edit: Kind of a big change to support nested unwrapping of data. Example API response, Model.withoutWrapping to false returns the same result:

    {
      data: [
        {
          id: 1,
          someId: 'ap319-0nh56',
          firstname: 'John',
          lastname: 'Doe',
          age: 25,
          comments: {
            data: [
              {
                id: 1,
                post_id: 1,
                someId: 'ma018-9ha12',
                text: 'Hello'
              },
              {
                id: 2,
                post_id: 1,
                someId: 'mw012-7ha19',
                text: 'How are you?'
              }
            ]
          }
        },
        {
          id: 1,
          someId: 'by887-0nv66',
          firstname: 'Mary',
          lastname: 'Doe',
          age: 25,
          comments: {
            data: [
              {
                id: 1,
                post_id: 1,
                someId: 'ma018-9ha12',
                text: 'Hello'
              },
              {
                id: 2,
                post_id: 1,
                someId: 'mw012-7ha19',
                text: 'How are you?'
              }
            ]
          }
        }
      ]
    }
    

    When Model.withoutWrapping is set to true (or not defined) we return it like this:

    [
        {
          id: 1,
          someId: 'ap319-0nh56',
          firstname: 'John',
          lastname: 'Doe',
          age: 25,
          comments: [
              {
                id: 1,
                post_id: 1,
                someId: 'ma018-9ha12',
                text: 'Hello'
              },
              {
                id: 2,
                post_id: 1,
                someId: 'mw012-7ha19',
                text: 'How are you?'
              }
          ]
        },
        {
          id: 1,
          someId: 'by887-0nv66',
          firstname: 'Mary',
          lastname: 'Doe',
          age: 25,
          comments: [
              {
                id: 1,
                post_id: 1,
                someId: 'ma018-9ha12',
                text: 'Hello'
              },
              {
                id: 2,
                post_id: 1,
                someId: 'mw012-7ha19',
                text: 'How are you?'
              }
          ]
        }
    ]
    opened by peterquentin 14
  • Upload a PDF file

    Upload a PDF file

    Hello there,

    I am trying to use this awesome plugin to upload a PDF file. I have created a model for this:

    import Model from './Model';
    
    export default class JobApplication extends Model {
      resource() {
        return 'v2/job_applications';
      }
    }
    

    Then, I call the model within the .vue file like that:

    ...
     import JobApplication from "./../models/JobApplication";
    ...
    async onSubmit() {
      let job = new JobApplication({
        first_name,
        last_name,
        email,
        mobile_phone,
        resume: this.$refs.resume.files[0]
      });
      await job
        .save()
        .then(response => {
          console.log(response);
        })
        .catch(error => {
          console.error(error.response);
        });
    }
    ...
    

    The problem is that the POST request fails every time I try to submit the form because of the resume field. What am I doing wrong in here? Do I have to do any extra steps? Thank you

    enhancement released 
    opened by Tes3awy 12
  • feat(builder): add support to nested filters

    feat(builder): add support to nested filters

    Add support to nested filters to where and whereIn.

    Closes #81

    TODO

    • [x] Update documentation of where and whereIn

    Usage

    await Model.where(['user', 'status'], 'active').get()
    // GET /resource?filter[user][status]=active
    
    await Model.whereIn(['user', 'status'], ['active', 'inactive']).get()
    // GET /resource?filter[user][status]=active,inactive
    
    released 
    opened by JoaoPedroAS51 11
  • validation errors on model.save()

    validation errors on model.save()

    how can handle validation errors on model.save() from backend such as laravel ?

    i think if this library has a utility for that, it's awesome

    question 
    opened by DJafari 10
  • data wrapping, model hydratation and access to response instance

    data wrapping, model hydratation and access to response instance

    This pull request is to handle request to JSON API’s with and without data wrapping. Basically you only need to configure your model and define how your data is wrapper in each response operation.

    Configration

    You only need to define de value of dataWrappers()
    By default, all models operate without data wrapping, for backward compatibility.

      dataWrappers() {
        return {
          index: null,
          store: null,
          show: null,
          update: null,
          destroy: null,
        }
      }
    

    So, if your API returns all your data inside a data attribute, then you should set up dataWrappers() like this:

      dataWrappers() {
        return {
          index: 'data',
          store: 'data',
          show: 'data',
          update: 'data',
          destroy: 'data',
        }
      }
    

    In case your API only wraps the resources collections, then, you only need to set up that response type:

     dataWrappers() {
       return {
         index: 'data',
         store: null,
         show: null,
         update: null,
         destroy: null,
       }
     }
    

    Well, you get the idea...

    Model Instance hydration

    Another thing this pull request solves is the model hydratation. All models will be hydratated after each CRUD operation. This is usefull if your API returns a full representation of the resource. This avoids a second request to get the new values.

     // resource before request
     // {
     //   id: 1,
     //   username: 'arya'
     //   email: '[email protected]'
     //   token: '1234'
     // }
    
     // PUT /users/1
     let user = new User({ id: 1, email: '[email protected]' })
     await user.save()
    
     // response from API for PUT /users/1
     // {
     //   data: {
     //     id: 1,
     //     username: 'arya'
     //     email: '[email protected]'
     //     token: '1234'
     //   }
     // }
    
     user = {
       id: 1,
       username: 'arya'
       email: '[email protected]'
       token: '1234'
     }
    

    This is very useful even for a DELETE request, if you return the deleted values.

    Access to response instance on save.

    Finally, now, method save() returns the response instance unmodified. The models are stored in the instance itself (hydrated), but the returned value is the http response. Again, this is useful if we want to access metadata information in the response data.

      let user = new User({name: 'Arya'})
      res = user.save()
    
      // "user" is the User Instance
      user = {
        id: 1,
        name: 'arya',
      }
    
      // "res" is the http response
      res = {  
        data: {},
        status: 200,
        statusText: 'OK',
        headers: {},
        config: {},
        request: {}  
      }
    

    Tests...

    I've added test for all the cases (I think). By the way, I added some "deprecated" comments (in tests) for methods $get(), $first(), $find() as I think those methods are redundant now? I don't know, what do you think?

    opened by jaumesala 10
  • Possible dependencies/devDependencies defined wrong

    Possible dependencies/devDependencies defined wrong

    Today I updated to package version 1.4.1. Now, when I compile my code, I get:

    These dependencies were not found:
    
    * @babel/runtime/helpers/assertThisInitialized in ./node_modules/vue-api-query/build/Model.js
    * @babel/runtime/helpers/classCallCheck in ./node_modules/vue-api-query/build/StaticModel.js, ./node_modules/vue-api-query/build/Parser.js and 2 others
    * @babel/runtime/helpers/createClass in ./node_modules/vue-api-query/build/Model.js, ./node_modules/vue-api-query/build/StaticModel.js and 2 others
    * @babel/runtime/helpers/getPrototypeOf in ./node_modules/vue-api-query/build/Model.js
    * @babel/runtime/helpers/inherits in ./node_modules/vue-api-query/build/Model.js
    * @babel/runtime/helpers/interopRequireDefault in ./node_modules/vue-api-query/build/index.js, ./node_modules/vue-api-query/build/StaticModel.js and 3 others
    * @babel/runtime/helpers/possibleConstructorReturn in ./node_modules/vue-api-query/build/Model.js
    * @babel/runtime/helpers/slicedToArray in ./node_modules/vue-api-query/build/Builder.js
    
    To install them, you can run: npm install --save @babel/runtime/helpers/assertThisInitialized @babel/runtime/helpers/classCallCheck @babel/runtime/helpers/createClass @babel/runtime/helpers/getPrototypeOf @babel/runtime/helpers/inherits @babel/runtime/helpers/interopRequireDefault @babel/runtime/helpers/possibleConstructorReturn @babel/runtime/helpers/slicedToArray 
    

    I think, there are some dependencies are needed in the "dependencies" section, not "devDependencies". So far I can reconstruct, the error starts with 1.3.0

    opened by prodigy7 9
  • data wrapping for single items

    data wrapping for single items

    It is typical for JSON API's to wrap not only multiple results but also single results in a data key. (Even Laravel's API Resources default to this behaviour.)

    For multiple results (arrays of items), vue-api-query automagically works regardless of whether or not the data key wrapper is present.

    I feel that for single results there should be the same behaviour.

    Backward-compatibility can be ensured by adding a configuration option or optional function argument to enable this behaviour. (Similar to withoutWrapping in Laravel's API Resources. See Eloquent: API Resources)

    So, if the backend responds with:

    {
        "data": {
            id: 1,
            firstname: "John",
            lastname: "Doe",
            age: 25
        }
    }
    

    And withWrapping is set to true, the behaviour should be the same as if the response was:

    {
        id: 1,
        firstname: "John",
        lastname: "Doe",
        age: 25
    }
    
    opened by derekphilipau 9
  • updating the object sends a POST request

    updating the object sends a POST request

    Here is the code I have that I am using to update and I can get the save/update to work?

    this.productObj = await Product.include('variants', 'additional_info', 'nutrition_fact')
                    .append('min_priced_variant')
                    .find(this.productId)
    
    this.productObj.name = 'Test';
    this.productObj.category_id = 3;
    
    this.productObj.save();
    

    Is there any reason why this would send a POST request to /products instead of a PUT request to /products/{id}.

    Am I missing something?

    opened by abishekrsrikaanth 9
  • Catching Errors on model.save()

    Catching Errors on model.save()

    Hello,

    I am trying to catch error on POST data.

    My code:

    <form
              @submit.prevent="onSubmit"
              class="apply-form-section__form"
              action
              method="POST"
              ref="form"
              role="form"
            >
              <div class="apply-form-section__input-wrapper">
                <input
                  type="text"
                  class="apply-form-section__input-wrapper--input-field"
                  placeholder="Name"
                  v-model.lazy.trim="formResponses.name"
                >
              </div>
              <div class="apply-form-section__input-wrapper">
                <input
                  type="tel"
                  class="apply-form-section__input-wrapper--input-field"
                  placeholder="Phone number"
                  v-model.lazy.trim="formResponses.mobile"
                >
              </div>
              <div class="apply-form-section__input-wrapper">
                <input
                  type="text"
                  class="apply-form-section__input-wrapper--input-field"
                  placeholder="Company"
                  v-model.lazy.trim="formResponses.company"
                >
              </div>
    </form>
    
    data() {
          return {
            formResponses: {
              name: "",
              mobile: "",
              company: "",
              position: "",
              email: ""
            },
          };
        },
    methods: {
          async onSubmit() {
            console.log("form responses:", this.formResponses);
            let newApplication = new CardApplication({
              name: this.formResponses.name,
              mobile_phone: this.formResponses.mobile,
              company: this.formResponses.company,
              position: this.formResponses.position,
              email: this.formResponses.email
            });
    
            await newApplication
              .save()
              .then(response => {
                this.formSubmitted = true;
                if(response.meta.code == 200) {
                  console.log("success:", response);
                  console.log("form data:", this.formResponses);
                }
              })
              .catch(err => {
                console.log("ERROR SAVING APPLICATION:", err);
              });
          }
    

    The problem is that I don't get the supposed response object on error. I only get Error: Request failed with status code 400 in the console.

    Can you help me with this?

    opened by Tes3awy 9
  • Problems with trailing slash at the end of each request

    Problems with trailing slash at the end of each request

    It is a standard practice that any backend would follow to add trailing slash at the end of every api request. There are few ways of handling it.

    Irrespective of efforts at the backend, some browsers are appending it which creates the issue.

    This can be solved by adding a trailing slash to all the requests.

    Note: we can add that to the resourse, but it does creates the problem of adding additional slash when we use find() or something similar. Hope this is clear.

    opened by ramsane 6
Releases(v1.9.1)
  • v1.9.1(May 25, 2021)

  • v1.9.0(Jan 16, 2021)

  • v1.8.2(Dec 4, 2020)

  • v1.8.1(Nov 10, 2020)

  • v1.8.0(Nov 10, 2020)

  • v1.7.1(Nov 1, 2020)

  • v1.7.0(Oct 31, 2020)

    Features

    • model: handle 'data' wrapped responses for create and update (#109) (1bc6248) (@fadugyamfi)
    • model: add support to nested keys for relations (#127) (095c1c3) (@JoaoPedroAS51)

    Bug Fixes

    • model: add null check in isValidId (#115) (279f9dc) (@guirociozanini)
    • model: relations are not being applied if any is null (#134) (92932cc) (@JoaoPedroAS51)

    Docs

    • add new documentation website :tada: (#130) (e1afa2a) (@JoaoPedroAS51)

    See https://robsontenorio.github.io/vue-api-query/

    Source code(tar.gz)
    Source code(zip)
  • 1.6.1(Oct 9, 2020)

  • 1.6.0(Oct 9, 2020)

    Thanks @JoaoPedroAS51 !

    You can also apply a model instance to a nested object by setting the key and the model in relations method.

    If the backend responds with:

    // response from API for /posts/1
    {
      title: 'My title'
      body: 'Some text here',
      user: {
        firstName: 'John',
        lastName: 'Doe'
      }
    }
    

    We just need to set user to User model:

    /models/Post.js

    class Post extends Model {
      relations () {
        return {
          // Apply User model to `user` object
          user: User
        }
      }
    }
    

    It also works for collections. So if the backend responds with:

    // response from API for /comments
    {
      text: 'Some text here',
      user: {
        firstName: 'John',
        lastName: 'Doe'
      },
      replies: [
        {
          text: 'A reply here',
          user: {
            firstName: 'Joe',
            lastName: 'Doe'
          }
        },
        {
          text: 'Another reply here',
          user: {
            firstName: 'Mary',
            lastName: 'Doe'
          },
          replies: [
            {
              text: 'Yes, this is the reply of the reply!',
              user: {
                firstName: 'Max',
                lastName: 'Doe'
              }
            }
          ]
        }
      ]
    }
    

    Then we just need to set user to User model and replies to Comment model:

    /models/Comment.js

    class Comment extends Model {
      relations () {
        return {
          // Apply User model to `user` object
          user: User,
          // Apply Comment model to each object of `replies` array
          replies: Comment
        }
      }
    }
    
    Source code(tar.gz)
    Source code(zip)
  • 1.5.2(May 15, 2020)

    • Update all dependencies
    • Small fix on README @manniL
    • Reset query string @MichMich
    • save() method makes a PUT request to the correct URL on nested object thas was fetched with find() method @taai

    Thanks to @Peter-Krebs for reviewing.

    Source code(tar.gz)
    Source code(zip)
  • 1.5.1(May 2, 2019)

  • 1.5.0(Apr 17, 2019)

    Thanks @leeovery for #61.

    Introduces new fetch style request for find() and first() methods. See README for more info.

    let user = await User.$find(1)
    
    let user = await User.$first()
    
    Source code(tar.gz)
    Source code(zip)
  • 1.4.1(Feb 26, 2019)

  • 1.4.0(Feb 23, 2019)

    Thanks @Peter-Krebs

    The custom() method can be called with multiple arguments to build resource endpoints and hierarchies. Simply supply them in the correct order. Any combination of strings and models is possible.

        let user = new User({ id: 1 })
        let post = new Post()
    
        // GET /users/1/posts/latest
        const result = await Post.custom(user, post, 'latest').get()
    
    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Feb 18, 2019)

    Update dependencies

    Updated to latest babel and eslint features.

    Added ability to customize query parameter names

    If you need to change default values just override parametersName() on your Base Model. So, the generated query string will use this new values.

    import { Model as BaseModel } from 'vue-api-query'
    
    export default class Model extends BaseModel {
    
      parameterNames () {
        return {
          include: 'include_custom',
          filter: 'filter_custom',
          sort: 'sort_custom',
          fields: 'fields_custom',
          append: 'append_custom',
          page: 'page_custom',
          limit: 'limit_custom'
        }
      }
    }
    

    Thanks @suth https://github.com/robsontenorio/vue-api-query/pull/42

    Fix array strategy validation for SSR

    Got error on using vue-api-query with NUXT on universal mode (SSR)

    Thanks @MisterEffix https://github.com/robsontenorio/vue-api-query/pull/43

    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Nov 21, 2018)

     let user = new User({id: 1})
     let post = await user.posts().first()
     
     // Related objects go in order of their appearance in the URL.
     let comment = new Comment({text: 'for() takes multiple objects.'}).for(user, post)
      // POST /users/1/posts/1/comments
     await comment.save()
    
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Jul 25, 2018)

    If you need to get a nested resource, without getting the parent model at first, you can do something like this.

    // GET /users/1/posts
    
    let User = new User({id: 1})
    let Post = await User.posts().get()
    
    // GET /users/1/posts/2
    let User = new User({id: 1})
    let Post = await User.posts().find(2)
    
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Jul 16, 2018)

    • Tag 1.0.0 stable
    • for() method for creating new related objects

    Creating new related objects is easy. Just use the for() method, passing the related object.

      let post = new Post({title: 'Woo!'})  
    
      // POST /posts
      await post.save()
    
      let comment = new Comment({text: 'New one for this post'}).for(post)
    
      // POST /posts/1/comments
      await comment.save()
    
    Source code(tar.gz)
    Source code(zip)
  • 0.7.0(Jun 4, 2018)

    If you need to pass any extra param not provided by vue-api-query pattern, just use the params() method while querying:

    // GET /users?doSomething=yes&process=no
    
    let users = await User
      .params({
        doSomething: 'yes',
        process: 'no'
      })
      .get()
    

    Of course you can chain it with other methods, including on relationships.

    // GET /posts/1/comments?include=user&blah=123
    
    let comments = await post
      .comments()
      .include('user')
      .params({blah: 123})
      .get()
    
    Source code(tar.gz)
    Source code(zip)
  • 0.6.0(May 16, 2018)

  • 0.5.0(Apr 10, 2018)

  • 0.4.1(Apr 6, 2018)

  • 0.4.0(Apr 5, 2018)

  • 0.3.0(Mar 30, 2018)

  • 0.2.0(Mar 30, 2018)

Owner
Robson Tenório
Laravel, Vue, Nuxt, Electron.
Robson Tenório
Stale-while-revalidate data fetching for Vue

swrv swrv (pronounced "swerve") is a library using the @vue/composition-api for remote data fetching. It is largely a port of swr. Documentation The n

Kong 1.2k Jun 12, 2021
Control your API calls by using an amazing component which supports axios and vue-resource

Vue API Request Vue API Request provides a full control on your APIs, making the calls simple, fast and easy to implement. Also, your code will be cle

Felipe Gibran Eleuterio Toledo 123 Apr 25, 2021
VueJS reactive RESTful API

Vue Chimera VueJS RESTful client with reactive features. Vue-Chimera is based on axios http client library. Overview of features: Loading flags Bindin

null 161 Apr 15, 2021
Smart asynchronous data and computed properties for vue components.

vue-async-properties Vue Component Plugin for asynchronous data and computed properties. A Marketdial Project new Vue({ props: { articleId: Numb

MarketDial 37 Mar 29, 2021
> Solution to remove and simplify axios in components vue

Vue fast axios Solution to remove and simplify axios in components vue Dependencies: Only Vue.js 2.x Before install Before installing, you must instal

Leonardo Vilarinho 40 Mar 16, 2021
集成axios的vue插件

vue-apis A vue plug-in integrated with axios. Build the API using chain programming and return the request instance as a Promise. A nice simplificatio

兔子人开源 26 Dec 24, 2020
The HTTP client for Vue.js

vue-resource The plugin for Vue.js provides services for making web requests and handle responses using a XMLHttpRequest or JSONP. Features Supports t

Pagekit 10.1k Jun 14, 2021
V-Model is a model plugin for Vue.js, like ng-resource.

V-Model V-Model is a model plugin for Vue.js, like ng-resource. based on axios, path-to-regexp, and bluebird. The V-Model provides interaction support

Gaoding Inc 56 Mar 16, 2021
Async computed properties for Vue.js

vue-async-computed With this plugin, you can have computed properties in Vue that are computed asynchronously. Without using this plugin, you can't do

Benjamin Fox 1k Jun 13, 2021
A tiny library for handling JSONP request.

Vue-jsonp A tiny library for handling JSONP request. Quick Start As Vue plugin: import { VueJsonp } from 'vue-jsonp' // Vue Plugin. Vue.use(VueJsonp)

LancerComet 123 Jun 4, 2021
Async data loading plugin for Vue.js 2.0

vue-async-data for Vue.js 2.0 Async data loading plugin for Vue.js Install this plugin is written in ES2015, so recommend compile with babel/babel-pol

kamijin_fanta 33 Mar 16, 2021
⚡️ A request library for Vue 3. 一个能轻松帮你管理请求状态的 Vue 3 请求库。欢迎使用~

English | 简体中文 VueRequest ⚡️ A request library for Vue 3. Status: Beta Features ?? All data is reactive ?? Interval polling ?? Automatic error retry ?

Atto 162 Jun 12, 2021
Backend mocking for rapid project testing and previews

Vue-Resource-Mock This package requires no specific version of Vue but vue-resource. It works for both Vue/Vue2 as the time of this writing. Copy and

xiuxiuxiu 28 Jul 30, 2020
axios plugin for Vuejs project

vue-axios-plugin 简体中文 | English axios plugin for Vuejs project How to install Script tag <!-- add it after vue.js --> <script src="https://unpkg.com/v

Yuga Sun 55 Feb 19, 2021