๐ŸŽ A tiny and fast GraphQL client for Vue.js

Overview

villus

codecov circleci Bundle Size npm npm

Villus is a finger-like structures in the small intestine. They help to absorb digested food.

A small and fast GraphQL client for Vue.js.

This is forked from my previous work at vue-gql before they decide to go for a different direction with this library.

Features

  • ๐Ÿ“ฆ Minimal: Its all you need to query GQL APIs
  • ๐Ÿฆ Tiny: Very small footprint
  • ๐Ÿ—„ Caching: Simple and convenient query caching by default
  • ๐Ÿ‘• TypeScript: Written in Typescript and Supports GraphQL TS tooling
  • ๐Ÿ–‡ Composable: Built for the Composition API
  • โšก๏ธ Suspense: Supports the <Suspense> API in Vue 3
  • ๐Ÿ”Œ Plugins: Use existing plugins and create custom ones
  • Higher-order components available
  • Supports both Vue 2.x (with @vue/composition-api) and 3.0

Why use this

GraphQL is just a simple HTTP request. This library is meant to be a tiny client without all the bells and whistles attached to Apollo and its ecosystem which subsequently means it is faster across the board due to it's smaller bundle size and reduced overhead. villus offers simple strategies to cache and batch, dedup your GraphQL requests.

villus also supports file uploads and subscriptions without compromising bundle size through plugins.

If you are looking for a more full-featured client use vue-apollo, it has everything you need.

You can read more about it in the announcement post.

Documentation

You can find the documentation here

Quick Start

First install villus:

yarn add villus graphql

# or npm

npm install villus graphql --save

Or because villus is so simple, you can use it via CDN:

<!-- Import Vue 2 or 3 -->
<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<!-- Vue Demi is needed for Vue 2 and 3 support -->
<script src="https://unpkg.com/[email protected]/lib/index.iife.js"></script>
<!-- Villus -->
<script src="https://unpkg.com/villus@latest/dist/villus.min.js"></script>

You can now use it with either the new Vue composition API or higher order components.

Usage

Configure the GraphQL client for your root component:

import { useClient } from 'villus';

export default {
  name: 'App',
  setup() {
    useClient({
      url: 'http://localhost:3002/graphql',
    });
  },
};

Then you can use useQuery in any child component:

<template>
  <div>
    <div v-if="data">
      <pre>{{ data }}</pre>
    </div>
  </div>
</template>

<script>
import { useQuery } from 'villus';

export default {
  setup() {
    const AllPosts = `
      query AllPosts {
        posts {
          title
        }
      }
    `;

    const { data } = useQuery({
      query: AllPosts,
    });

    return { data };
  },
};
</script>

There is also the higher-order component flavor if you prefer to use them instead. Read the docs for more examples and details.

villus makes frequent tasks such as re-fetching, caching, deduplication, mutations, and subscriptions a breeze. It has even built-in Suspense support with Vue 3! Consult the documentation for more use-cases and examples.

Compatibility

This library relies on the fetch web API to run queries, you can use unfetch (client-side) or node-fetch (server-side) to use as a polyfill.

Examples

Live examples can be found here

License

MIT

Comments
  • feat: enable useQuery etc function outside of setup and outside component

    feat: enable useQuery etc function outside of setup and outside component

    I'd love to use useQuery, useMutation, but we only can define it in setup. so I extended it to use outside of setup and component. The idea to extends comes from pinia.

    I create a sampe here: https://stackblitz.com/edit/vue-9ebjy6?file=src/App.vue , and this commit should enable it.

    something should be notice:

    • add a new choice param(manualClient) in useQuery etc, to enable these function outside of component. eg: before app mounted. We can manually send the created client to enable it.
    • when useSubscription outside of setup, due to unable register beforeUnmounted, It is recommended to pause it by user.

    This commit should fix https://github.com/logaretm/villus/issues/149;

    hope it will be help.

    opened by GavinXue 15
  • Nuxt3 SSR Deployed on netlify

    Nuxt3 SSR Deployed on netlify

    in the root app I am using useClient inside setup like so:

    <script setup lang="ts">
    ...
    useClient({
      url: 'https://...',
      use: [myPlugin, ...defaultPlugins()],
    })
    </script>
    
    

    and in the page I have

    export default {
      async setup() {
        ...
        const { data } = await useQuery({
          ...
        })
      }
    }
    

    locally everything works fine but when deployed to netlify with SSR I am getting the following error:

    image
    opened by fanckush 9
  • [AFTER PATCH] Did you forget to call `useClient`?

    [AFTER PATCH] Did you forget to call `useClient`?

    Versions with Issue : Rc0 + Rc1

    image

    Issue happens when getReport() is called on change of a date. When getReport() is called during page load /setup it works fine.

    Logic of program is when date input is changed, send useQuery to fetch data using the selected date.

    App.VUE

    <script lang="ts">
    import { SubscriptionClient } from "subscriptions-transport-ws";
    import { defineComponent, computed } from "vue";
    import DesktopMenu from "./components/DesktopMenu.vue";
    import { router } from "./main";
    import { useClient } from "villus";
    
    import { ActionTypes, MutationTypes, useStore } from "./store";
    
    export default defineComponent({
      name: "Navigation",
      components: {
        DesktopMenu,
      },
      setup() {
        const store = useStore();
    
        useClient({
          url: "/graphql",
        });
    
      },
    });
    </script>
    
    

    Home.VUE

    <template>
      <div>
        Home
        <input v-model="datePage" type="date" />
        <p v-if="returnData">
          {{ returnData }}
        </p>
      </div>
    </template>
    
    <script lang="ts">
    import { defineComponent, ref, computed, watchEffect } from "vue";
    import { useQuery } from "villus";
    
    import { CostDocument } from "../generated/graphql-operations";
    
    export default defineComponent({
      name: "HelloWorld",
      setup() {
        const returnData = ref();
        const datePage = ref("2020-10-18");
        const formattedDate = computed(() =>
          datePage.value.toString().split("-").join(""),
        );
    
        const data = ref(null);
        watchEffect(async (datePage) => {
          async function getReport() {
            try {
              console.log("date value changed:", formattedDate);
    
              const { data, error } = await useQuery({
                query: CostDocument,
                variables: { date: formattedDate.value },
              });
    
              console.log("Query:", data, error);
              returnData.value = data;
            } catch (error) {
              console.log("error", error);
            }
          }
          data.value = await getReport();
        });
    
        return { returnData, datePage };
      },
    });
    </script>
    
    opened by kingkong404 9
  • How to use in e.g. Pinia

    How to use in e.g. Pinia

    Hi, I'm pretty new to Vue3, and I'm wondering how I would need to go about invoking an API request using Villus in e.g. an action inside a Pinia Store?

    It gives the following error: image

    Even though I useClient in the Store right before the call.

    If you could help me out I'd love to open a PR to update the documentation with an example as well

    ๐Ÿค” needs reproduction 
    opened by MidasLamb 8
  • How to set the headers for the batch plugin

    How to set the headers for the batch plugin

    Hi! First of all, amazing GraphQL client!

    There is however one thing I can't seem to figure out. I was wondering how I should set the headers for the batch plugin. Without the batch plugin I made an auth plugin as stated in the docs and this works fine until I add the batch plugin to the mix. I need to set the credentials to include as well as set an X-XSRF-TOKEN header. if I add the batch plugin the requests all return a 419 No reason phase as the X-XSRF-TOKEN header doesn't get set.

    How should I do that?

    ๐Ÿ› bug 
    opened by DaLukasTI 7
  • How to extract useQuery outside .vue file

    How to extract useQuery outside .vue file

    Hi, many thanks for creating villus. Since using typed useQuery() is quite verbose, is it possible to extract this to a function outside the .vue component, also to be able to reuse it better across different components? If so, can you provide an example?

    opened by natemate90 7
  • Recommended implementation for writing unit tests with villus

    Recommended implementation for writing unit tests with villus

    I'm trying to write unit tests in Jest for my Vue application, but I'm running into problems because of Villus, and I'm not entirely sure how I should go about mocking things like useMutation and useQuery. Any tips?

    This is the error I'm getting:

      โ— GameCard.vue โ€บ renders platforms and developers when passed
    
        Cannot detect villus Client, did you forget to call `useClient`?
    
          57 |     });
          58 |
        > 59 |     const { execute: executeFavoriteGame } = useMutation(FavoriteGameDocument);
    

    The Jest test looks like this:

    import { createLocalVue, mount } from '@vue/test-utils'
    import GameCard from '@/components/GameCard.vue'
    
    const localVue = createLocalVue();
    
    describe('GameCard.vue', () => {
      it('renders platforms and developers when passed', () => {
        const wrapper = mount(GameCard, {
          stubs: ['router-link', 'router-view'],
          localVue,
          propsData: {
            game: {
              id: 1,
              platforms: {
                nodes: [
                  {
                    id: 1,
                    name: 'Nintendo Switch'
                  }
                ]
              },
              developers: {
                nodes: [
                  {
                    id: 1,
                    name: 'Valve'
                  }
                ]
              },
              isFavorited: true
            }
          }
        })
        expect(wrapper.text()).toMatch('Nintendo Switch')
      })
    })
    

    and my component looks like this:

    <template>
      <div class="custom-card game-card">
        <router-link :to="{ name: 'Game', params: { id: game.id } }" class="card-container">
          <figure class="game-cover">
            <img v-if="game.coverUrl !== null" :src="game.coverUrl" />
            <img v-else src="@/assets/images/no-cover.png"/>
          </figure>
          <div class="card-content">
            <p class="title is-4 mr-10">{{ game.name }}</p>
            <p class="subtitle is-6" v-if="platforms !== null">{{ platforms }}</p>
            <p class="subtitle is-6" v-if="developers !== null">{{ developers }}</p>
          </div>
        </router-link>
    
        <!-- Game card Dropdown -->
        <div class="dropdown dropdown-dynamic game-card-dropdown is-right" :class="{ 'is-active': isActive }" v-if="userSignedIn">
          <div class="dropdown-trigger">
            <button class="button is-borderless is-shadowless" aria-haspopup="true" aria-controls="dropdown-menu" @click="toggleActive">
              <SvgIcon :name="'chevron-down'" :classes="['icon']" :size="15" />
            </button>
          </div>
          <div class="dropdown-menu" id="dropdown-menu" role="menu">
            <div class="dropdown-content">
              <a v-if="game.isFavorited || localIsFavorited" class="dropdown-item" @click="unfavoriteGame">Unfavorite</a>
              <a v-else class="dropdown-item" @click="favoriteGame">Favorite</a>
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <script lang="ts">
    import { Company, FavoriteGameDocument, Platform, UnfavoriteGameDocument } from '@/generated/graphql';
    import { computed, defineComponent, ref } from '@vue/composition-api';
    import SvgIcon from '@/components/SvgIcon.vue';
    import { useMutation } from 'villus';
    
    export default defineComponent({
      name: 'GameCard',
      components: {
        SvgIcon
      },
      props: {
        game: {
          required: true,
          type: Object
        }
      },
      setup(props, context) {
        const platforms = computed(() => {
          if (props.game.platforms.nodes.size === 0) { return null; }
          return props.game.platforms.nodes.map((p: Platform) => p.name).join(', ');
        });
        const developers = computed(() => {
          if (props.game.developers.nodes.size === 0) { return null; }
          return props.game.developers.nodes.map((d: Company) => d.name).join(', ');
        });
    
        const { execute: executeFavoriteGame } = useMutation(FavoriteGameDocument);
        const { execute: executeUnfavoriteGame } = useMutation(UnfavoriteGameDocument);
    
        let isActive = ref<boolean>(false);
    
        // Tracks whether the game has been favorited, will be toggled when the
        // mutation is executed so we don't have to reload the game record.
        let localIsFavorited = ref<boolean>(props.game.isFavorited);
    
        const favoriteGame = () => {
          executeFavoriteGame({ id: props.game.id }).then(() => {
            toggleActive();
            localIsFavorited.value = true;
          });
        };
    
        const unfavoriteGame = () => {
          executeUnfavoriteGame({ id: props.game.id }).then(() => {
            toggleActive();
            localIsFavorited.value = false;
          });
        };
    
        const toggleActive = () => isActive.value = !isActive.value;
    
        const userSignedIn = computed(() => {
          return context.root.$store.state.userSignedIn;
        });
    
        return {
          isActive,
          platforms,
          developers,
          favoriteGame,
          unfavoriteGame,
          toggleActive,
          userSignedIn,
          localIsFavorited
        };
      }
    });
    </script>
    

    I'm using Vue 2.x with TypeScript and @vue/composition-api.

    See similar docs for Apollo: https://apollo.vuejs.org/guide/testing.html#testing

    ๐Ÿ“š documentation 
    opened by connorshea 7
  • Subscription pause and resume problem

    Subscription pause and resume problem

    {pause, resume} = useSubscription({query: Something})
    
    pause()
    resume()
    pause()
    resume()
    pause()
    resume()
    

    The resume function will create a new subscription, and restart previous subscription. There are multiple subscriptions be subscribed at the same time.

    opened by ghost-void 7
  • Access GraphQL errors when HTTP status code is 500

    Access GraphQL errors when HTTP status code is 500

    Is there a way to prevent Villus from imposing a [Network] Internal Server Error when the GraphQL server responds with a 500 status code ? When I configure the server to send 200 on error instead, I can access the GraphQL errors returned from the combined error just fine.

    Maybe add some kind of custom error handling / formatting feature ?

    opened by lewebsimple 6
  • TypeScript complains about subscriptionForwarder type

    TypeScript complains about subscriptionForwarder type

    When configuring subscriptions like the documentation suggests, TS complains with the following error:

    Type 'Observable<ExecutionResult<{ [key: string]: any; }, { [key: string]: any; }>>' is not assignable to type 'ObservableLike<OperationResult<any>>'.
      Types of property 'subscribe' are incompatible.
        Type '(observer: Observer<ExecutionResult<{ [key: string]: any; }, { [key: string]: any; }>>) => { unsubscribe: () => void; }' is not assignable to type '(observer: ObserverLike<OperationResult<any>>) => Unsub'.
          Types of parameters 'observer' and 'observer' are incompatible.
            Type 'ObserverLike<OperationResult<any>>' is not assignable to type 'Observer<ExecutionResult<{ [key: string]: any; }, { [key: string]: any; }>>'.
              Types of property 'next' are incompatible.
                Type '(value: OperationResult<any>) => void' is not assignable to type '(value: ExecutionResult<{ [key: string]: any; }, { [key: string]: any; }>) => void'.
                  Types of parameters 'value' and 'value' are incompatible.
                    Property 'error' is missing in type 'ExecutionResult<{ [key: string]: any; }, { [key: string]: any; }>' but required in type 'OperationResult<any>'.
    

    What I'm doing is the following:

    import { createClient, handleSubscriptions, defaultPlugins } from "villus";
    import { SubscriptionClient } from "subscriptions-transport-ws";
    
    const subscriptionClient = new SubscriptionClient("ws://localhost:4000/api/graphql", { reconnect: true });
    
    export const villus = createClient({
      url: "/api/graphql",
      use: [handleSubscriptions((operation) => subscriptionClient.request(operation)), ...defaultPlugins()],
    });
    
    

    Any idea what I'm doing wrong ?

    opened by lewebsimple 6
  • Query Batching error [Wordpress graphql]

    Query Batching error [Wordpress graphql]

    Hello i try to use query batching with worpdress graphql but i got a error CombinedError

    When i don't use the batcher() i see 2 call with no error

    Screen Shot 2020-04-13 at 11 34 56 AM

    When i activate it

        useClient({
          url: '/cms/graphql',
          fetch: batcher()
        })
    

    I see the call, the response seem to be good, an array of 2 objects

    Screen Shot 2020-04-13 at 11 34 28 AM

    But i get an error on each component response.

    Screen Shot 2020-04-13 at 11 33 53 AM

    Do you have an idea of who we can fix that ? A villius issue or wp-graphql issue ?

    Thanks

    ๐Ÿ› bug 
    opened by stephanedemotte 6
  • Mutation response undefined

    Mutation response undefined

    Hello,

    I'm following the documentation page https://villus.logaretm.com/guide/mutations/#handling-errors but I'm receiving an undefined response from the mutation.

    My method

        login(test) {
          const {execute} = useMutation(loginMutation);
    
          return execute({
            test: test,
          }).then((result) => {
            console.log("result", result);
          }).catch((error) => {
            console.error(error);
          });
        },
    

    Response from the server

    {"errors":[{"message":"test is invalid.","path":["login"],"extensions":{"code":"INTERNAL_SERVER_ERROR","exception":{"message":"test is invalid.","path":["login"],"stacktrace":["GraphQLError: test is invalid.","    at login (file:///****/AuthModule.js:113:17)","    at processTicksAndRejections (node:internal/process/task_queues:96:5)","    at async file:///***/@graphql-tools/batch-execute/index.mjs:354:36","    at async Promise.all (index 0)","    at async DataLoader.batchExecuteLoadFn [as _batchLoadFn] (file:///****/@graphql-tools/batch-execute/index.mjs:352:25)"]}}}],"data":null}
    

    Result from the console

    test {data: undefined, error: undefined}
    

    Versions:

    • Villus: 2.0.1
    • Vue: 3.2.45
    • Vite: 4.0.0
    • NPM 8.1.4

    Is this an issue or what I'm doing wrong?

    Thanks in advance!

    opened by ludgart 1
  • Uncaught Error: Cannot detect villus Client, did you forget

    Uncaught Error: Cannot detect villus Client, did you forget

    to call useClient? Alternatively, you can explicitly pass a client as the manualClient argument.

    To start off, thank you logaretm! Villus looks really cool and since apollo does not seem to work via cdn, it really keeps the spirit alive of vue usable for any size project.

    I'm trying to do a minimal proof of concept, following along https://gitmemories.com/logaretm/villus Maybe I'm getting access to villus in the most awkward way possible, but what happens is the useClient is called successfully in the mounted() handling, but on the clickLoad handler I get "vue.global.js:1414 Uncaught Error: Cannot detect villus Client, did you forget to call useClient? Alternatively, you can explicitly pass a client as the manualClient argument."

    I haven't messed around with the manualClient because it seems like I must be doing something fundamentally wrong. Am I way off in the weeds here?

    I looked at the two comments where you explained that it can only be used during a composition api setup call. Will this not work at all when using options? I see this true: https://github.com/logaretm/villus/issues/72#issuecomment-716261003 Oddly, even when I move over to composition api and use the <script setup> I'm still having this same problem. I can't find anything manualClient either.

    opened by cworkschris 3
  • Replace WaitForExpect in Testing docs

    Replace WaitForExpect in Testing docs

    Essentially, the most recent versions of Vue CLI/Jest don't play nicely with WaitForExpect anymore, unfortunately. Because of this, I had to switch to waitFor() from the @vue/testing-library package. Only once I did that was I able to upgrade to Jest v27. The "Writing Tests" docs recommend the waitForExpect package, but it might be a good idea to update that to recommend testing library's waitFor, or at least mention it as an alternative? https://villus.logaretm.com/guide/testing#writing-tests

    I have a commit here with some more details and the specific change I ended up going with for my own project: https://github.com/connorshea/vglist-frontend/commit/6aa9128004b8907dd40cc8c170535bcd37ff6f02

    ๐Ÿ“š documentation 
    opened by connorshea 1
  • How to use with JWT/RefreshToken? (and implement a retry strat)

    How to use with JWT/RefreshToken? (and implement a retry strat)

    sorry this is not an issue per se; but I couldn't find a satisfying answer anywhere else


    Is there a proven strategy for the following?

    • User calls the api using a JWT auth
    • Authorizer rejects the token (eg: expired) and returns 401
    • App calls a refresh token api and renew the JWT
    • App re-execute the query that originally failed transparently

    I've been toying with the Plugin API and could get up to the refresh part, but there doesn't seem to be a way to centralize the "retry" strategy in this case.

    We're to the point where we are wrapping useQuery/useMutation to handle this in 1 place, but I was wondering if there's a better way? ๐Ÿค”

    Thanks

    ๐Ÿ“š documentation 
    opened by OClement 1
  • Typings Error when using graphql-ws

    Typings Error when using graphql-ws

    When using the graphql-ws example in the docs from the subscriptions page, I get the follow typings issue:

    Argument of type '(operation: any) => { subscribe: (obs: any) => void; }' is not assignable to parameter of type 'SubscriptionForwarder<any>'.
      Call signature return types '{ subscribe: (obs: any) => void; }' and 'ObservableLike<StandardOperationResult<any>>' are incompatible.
        The types returned by 'subscribe(...)' are incompatible between these types.
          Type 'void' is not assignable to type 'Unsubscribable'.
    
    opened by sasial-dev 0
  • Add a guide to the documentation for Nuxt 3 Support

    Add a guide to the documentation for Nuxt 3 Support

    As a first time user to the repo, I had a quick look at the issues and there's a lot about Nuxt 3. As a fellow Nuxt 3 user, it would be helpful to have a nuxt/SSR guide.

    ๐Ÿ“š documentation 
    opened by sasial-dev 0
Releases(v2.1.0)
  • v2.1.0(Dec 30, 2022)

    A couple of nice features to help with the caching and fetching logic of mutations and queries. As always, feedback is welcome and make sure to report any bugs you encounter.

    ๐Ÿ†• New Features

    Added the ability to tag queries using the tags option when calling useQuery. This marks a query with the specified tags for a couple of features.

    Clearing tagged queries cache after mutation

    const { data } = useQuery(GetPosts, {
      tags: ['all_posts'],
    });
    
    // This will clear the previous query cache whenever `execute` concludes successfully.
    const { execute } = useMutation(CreatePost, {
      clearCacheTags: ['all_posts'],
    });
    

    Refetching tagged queries cache after mutation

    const { data } = useQuery(GetPosts, {
      tags: ['all_posts'],
    });
    
    // This will auto-fetch the previous query whenever `execute` concludes successfully.
    const { execute } = useMutation(CreatePost, {
      refetchTags: ['all_posts'],
    });
    

    This refetching bypasses the cache so it will also clear the affected queries cache as well, so there is some overlap between clearing and autofetching.

    Source code(tar.gz)
    Source code(zip)
  • v2.0.2(Dec 28, 2022)

    ๐Ÿ‘• TypeScript

    • Fixed a couple of typing issues with useMutation and its execute() where the data and error values returned were not nullable #182 (#183)
    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(Oct 23, 2022)

    โš™๏ธ Misc

    • Exposed several network utilities to make creating fetch plugins easier, the exposed functions are mergeFetchOptions, makeFetchOptions and parseResponse #163 (47348e197b6b8edd3511f3a95b0960160f4a6ffc)
    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Aug 7, 2022)

    A new major release of villus with Vue 2.7 support and API improvements.

    Vue 2.7 Support ๐ŸŽ‰

    Villus now supports Vue 2.7+ releases, so go ahead and try it out in your Vue 2.7 projects!

    ๐Ÿ’€ Breaking Changes

    Dropping higher-order components

    Villus is now strictly a composition API library, the higher-order components were dropped in favor of a lighter footprint and compatibility with Vue 2.7 due to differences in VDOM API.

    The Higher-order components API was mostly around for compatibility purposes and wasn't documented properly to encourage using the composition API.

    Pausing Queries/Subscriptions

    The API for stopping auto-refetch behaviors was changed. Instead of having explicit resume and pause functions you could pass a boolean, function that returns a boolean or a boolean ref.

    Here are a few examples of how that works now:

    const { data } = useQuery({
      query: GetPostById,
      variables,
      // Don't re-fetch automatically unless the id is present
      paused: ({ id }) => !id,
    })
    
    const { data, execute } = useQuery({
      query: GetPostById,
      variables,
      // This query is now "lazy" and you have to trigger executions manually with `execute`.
      paused: true,
    });
    

    The docs offer more examples and use cases for this API.

    Aside from that, it also offers a clear distinction from the recently introduced skipped queries.

    Source code(tar.gz)
    Source code(zip)
  • v1.2.5(Jul 31, 2022)

    ๐Ÿ› Bug Fixes

    • Fixed an issue with batch plugin dropping some fetch options set by previous plugins #166 (#167) thanks to @DaLukasTI
    Source code(tar.gz)
    Source code(zip)
  • v1.2.4(Jul 11, 2022)

  • v1.2.3(Jul 3, 2022)

    ๐Ÿ†• New Features

    • Added maxOperationCount option to the batch plugin to allow fine control over how many queries can be executed in a batch. Docs

    ๐Ÿ› Bug Fixes

    • Fixed calling query.unwatchVariables() can error out if variables are not watched by default (#164) thanks to @callumacrae
    Source code(tar.gz)
    Source code(zip)
  • v1.2.2(Jul 3, 2022)

  • v1.2.1(Jun 6, 2022)

  • v1.2.0(May 30, 2022)

    ๐Ÿ†• New Features

    • Added skip option to useQuery which prevents executing queries if it is evaluated to true.
    const route = useRoute();
    
    // skip fetching if route param `id` does not exist
    const shouldSkip = computed(() => {
      return !route.params.id
    });
    
    const { data, isFetching } = useQuery({
      // pass as ref ...
      skip: shouldSkip,
    });
    
    
    // pass as a function, which rescives the current variables as an argument
    const { data, isFetching } = useQuery({
      // ...,
      skip: (variables) => {
        return !variables.id;
      },
    });
    
    • useQuery variables option can now be a function that returns a variables object. This is mainly a DX improvement to avoid having to create computed properties to pass to useQuery.
    const route = useRoute();
    
    const { data, isFetching } = useQuery({
      variables: () => {
        return { id: route.params.id };
      },
    });
    
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Apr 23, 2022)

    ๐Ÿ‘• TypeScript

    • fix: add export types for villus.d.ts by @GavinXue in https://github.com/logaretm/villus/pull/155

    ๐Ÿ†• New Features

    • feat: enable useQuery etc function outside of setup and outside component by @GavinXue in https://github.com/logaretm/villus/pull/156

    This change will allow you to use useQuery and friends in a limited fashion outside the setup function. This should reduce the occurrences where a client instance cannot be found due to the inject/provide API caveats.

    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Nov 6, 2021)

  • v1.0.0(Oct 18, 2021)

    Villus has been stable for quite some time now aided by its goal to be a minimal GraphQL client for Vue.js and I think after all this time it is safe to say that the API is very stable and happy to go to v1.0 with this which would help anyone who is on the fence of adopting a beta or RC releases.

    There is some stuff being experimented with and plans for improving villus, check the PRs and issues for those.

    These are changes for this release:

    ๐Ÿ†•

    Added paused option for useSubscription to start a subscription in lazy mode #142 (#143)

    ๐Ÿฆ– TypeScript

    Added volar slot typing support for Query, Mutation and Subscription components (1aec7e727a2b2dee2a3f58708307c91198609f78)

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.21(Aug 26, 2021)

    ๐Ÿ› Bug Fixes

    • batch handled failure when attempting to unbatch a non-JSON or empty responses, it should provide a new custom error instead. This is observed when servers running nginx return 502 randomly.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.20(Aug 7, 2021)

    ๐Ÿฆ– TypeScript

    • Changed the interface of ObserverLike to have optional callbacks to match other implementations in the wild closes #132 (2ecd80b995f4af235f25f1fc009f1e3719733d8c)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.19(Jul 25, 2021)

    ๐Ÿ†• New Features

    The cache-and-network cache policy behavior has been changed to update the reactive data and error of the useQuery when the fresh data is fetched from the network, meaning now it will always reflect the fresh data available. #76 (23cd60ba3646b95514af37cd3f174e21f2151867)

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.18(Jun 29, 2021)

    ๐Ÿฆ– TypeScript

    • Updated the return result of Client.executeQuery and Client.executeMutation to include the query type #128 (80426e21c98301d9896f814e94c106a1374cd385)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.17(May 12, 2021)

  • v1.0.0-rc.16(May 12, 2021)

  • v1.0.0-rc.15(Mar 6, 2021)

  • v1.0.0-rc.14(Mar 6, 2021)

    ๐Ÿ› Bug Fixes

    • Fixed a race condition causing queries and mutation state integrity issues (43d936b91a407af0e3e83a1f1a1c81dbb00d0806)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.13(Feb 27, 2021)

    ๐Ÿ› Bug Fixes

    • Fixed the default fetch plugin not considering partial data/error responses (6c0a6fa81a57131c9c23758435a1143f3fafd33d)
    • Fixed the batch plugin not considering partial data/error respones and properly handle non-200 responses #104 (5cb088df59d0b0d64b71a27b21181a1e50e9e57e)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-rc.12(Feb 17, 2021)

    ๐Ÿฆ– TypeScript

    • Exposed the OperationResult interface #97 (7ba39728e144392de299eb202bb21775d735508a)

    ๐Ÿ†• New Features

    • Added context option to useQuery and useMutation to support modifying headers on per query basis #96 (8248b06674a4bf2757f0025740d7b775945acc09)
    useQuery({
      query: SomeQuery,
      context: {
        headers: {
          // some headers
        }
      }
    });
    
    // can be reactive as well
    useQuery({
      query: SomeQuery,
      context: computed(() => { .... })
    });
    
    useMutation(SomeMutation, {
      context: {
        headers: {
          // some headers
        }
      }
    });
    
    // can be reactive as well
    useMutation(SomeMutation, {
      context: computed(() => { .... })
    });
    
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Jan 20, 2021)

    ๐Ÿฆ– TypeScript

    • Fixed typing issue with Subscription forwarder type not accepting standard GraphQL ExecutionResult objects #93 (9ced480d387edb8d1d8893cc88d3ae0e856a897c)

    ๐Ÿ› Bugs Fixed

    • Fixed an issue where subscriptions did not report query errors correctly #93 (9ced480d387edb8d1d8893cc88d3ae0e856a897c)

    ๐Ÿ’– Enhancements

    • Tweaked the pause behavior with subscriptions to not unsubscribe from the observable when paused, instead it will ignore the result and freeze the state until resume is called again #94
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Jan 15, 2021)

    ๐Ÿฆ– Types

    • Enhanced the return type from the useQuery suspense API.
    • Enhanced the data and error return type to be nullable to reflect real world GQL.

    ๐Ÿ†• New Features

    • added variables option to override query variables on demand (only for a single execution)
    const { execute } = useQuery();
    
    execute({
      variables: {
         // ...
       }
    })
    
    Source code(tar.gz)
    Source code(zip)
  • @villus/[email protected](Dec 16, 2020)

  • [email protected](Nov 26, 2020)

    ๐Ÿ†• New Features

    • added install method to the villus client instance to make it installable as a Vue plugin #81 (#83) thanks to @sibbng
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Nov 25, 2020)

    ๐Ÿ†• New Features

    • Exposed getQueryKey helper function to allow including other values into the generated query ids (used for caching and dedup). 26548d575d579bd1cff44c7cbacc93c07e06fee8 5d18e8a7c3016cc9adef0bacfe43076878654a73

    • useSubscription now accepts refs for both query and variables, and will re-execute the subscription if either change. 0ec46802c80788531a7b84c516eac9d879b076e8

    Source code(tar.gz)
    Source code(zip)
  • [email protected](Nov 25, 2020)

  • [email protected](Nov 25, 2020)

Owner
Abdelrahman Awad
Frontend Engineer. I dabble in Vue.js, Nuxt.js and Node.js
Abdelrahman Awad
A template repository / quick start to build Azure Static Web Apps with a Node.js function. It uses Vue.js v3, Vue Router, Vuex, and Vite.js.

Azure Static Web App Template with Node.js API This is a template repository for creating Azure Static Web Apps that comes pre-configured with: Vue.js

Marc Duiker 6 Jun 25, 2022
Mosha-vue-toastify - A light weight and fun Vue 3 toast or notification or snack bar or however you wanna call it library.

Mosha Vue Toastify A lightweight and fun Vue 3 toast or notification or snack bar or however you wanna call it library. English | ็ฎ€ไฝ“ไธญๆ–‡ Talk is cheap,

Baidi Liu 187 Jan 2, 2023
Veloce: Starter template that uses Vue 3, Vite, TypeScript, SSR, Pinia, Vue Router, Express and Docker

Veloce Lightning-fast cold server start Instant hot module replacement (HMR) and dev SSR True on-demand compilation Tech Stack Vue 3: UI Rendering lib

Alan Morel 10 Oct 7, 2022
:tada: A magical vue admin https://panjiachen.github.io/vue-element-admin

English | ็ฎ€ไฝ“ไธญๆ–‡ | ๆ—ฅๆœฌ่ชž | Spanish SPONSORED BY ๆดปๅŠจๆœๅŠก้”€ๅ”ฎๅนณๅฐ ๅฎขๆˆทๆถˆๆฏ็›ด่พพๅทฅไฝœ็พค Introduction vue-element-admin is a production-ready front-end solution for admin inter

่Šฑ่ฃค่กฉ 80.1k Dec 31, 2022
:eyes: Vue in React, React in Vue. Seamless integration of the two. :dancers:

vuera NOTE: This project is looking for a maintainer! Use Vue components in your React app: import React from 'react' import MyVueComponent from './My

Aleksandr Komarov 4k Dec 30, 2022
๐ŸŽ‰ ๅŸบไบŽ vite 2.0 + vue 3.0 + vue-router 4.0 + vuex 4.0 + element-plus ็š„ๅŽๅฐ็ฎก็†็ณป็ปŸvue3-element-admin

vue3-element-admin ?? ๅŸบไบŽ Vite 2.0 + Vue3.0 + Vue-Router 4.0 + Vuex 4.0 + element-plus ็š„ๅŽๅฐ็ฎก็†็ณป็ปŸ ็ฎ€ไป‹ vue3-element-admin ๆ˜ฏไธ€ไธชๅŽๅฐๅ‰็ซฏ่งฃๅ†ณๆ–นๆกˆ๏ผŒๅฎƒๅŸบไบŽ vue3 ๅ’Œ element-plu

้›ชๆœˆๆฌงๅทด 84 Nov 28, 2022
Jenesius vue modal is simple library for Vue 3 only

Jenesius Vue Modal Jenesius vue modal is simple library for Vue 3 only . Site Documentation Installation npm i jenesius-vue-modal For add modals in yo

ะั€ั…ะธะฟั†ะตะฒ ะ•ะฒะณะตะฝะธะน 63 Dec 30, 2022
A plugin that can help you create project friendly with Vue for @vue/cli 4.5

vue-cli-plugin-patch A plugin that can help you create project friendly with Vue for @vue/cli 4.5. Install First you need to install @vue/cli globally

null 2 Jan 6, 2022
โšก๏ธ Minimal GraphQL Client + Code Generation for Nuxt

nuxt-graphql-client โšก๏ธ Minimal GraphQL Client + Code Generation for Nuxt โšก๏ธ Minimal GraphQL Client + Code Generation for Nuxt Features Zero Configurat

Dizzy 245 Dec 27, 2022
โšก๏ธ Minimal GraphQL Client + Code Generation for Nuxt3

nuxt-graphql-client โšก๏ธ Minimal GraphQL Client + Code Generation for Nuxt โšก๏ธ Minimal GraphQL Client + Code Generation for Nuxt Documentation Features Z

Conrawl Rogers 245 Dec 27, 2022
:necktie: :briefcase: Build fast :rocket: and easy multiple beautiful resumes and create your best CV ever! Made with Vue and LESS.

best-resume-ever ?? ?? Build fast ?? and easy multiple beautiful resumes and create your best CV ever! Made with Vue and LESS. Cool Creative Green Pur

Sara Steiert 15.8k Jan 9, 2023
AT-UI is a modular front-end UI framework for developing fast and powerful web interfaces based on Vue.js.

AT UI AT-UI is a modular front-end UI framework for developing fast and powerful web interfaces based on Vue.js. ไธญๆ–‡ README Features Based on Vue A npm

null 2.3k Jan 4, 2023
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 Dec 30, 2022
Mobile app development framework and SDK using HTML5 and JavaScript. Create beautiful and performant cross-platform mobile apps. Based on Web Components, and provides bindings for Angular 1, 2, React and Vue.js.

Onsen UI - Cross-Platform Hybrid App and PWA Framework Onsen UI is an open source framework that makes it easy to create native-feeling Progressive We

null 8.7k Jan 4, 2023
Real world app using Fastify-DX, Solid.js, Auth0 and GraphQL

Fastify DX and Solid.js In the Real World These are only the essentials to set up a "real world" application with Fastify DX, Solid.js, Auth0 and Grap

Zentered 6 Nov 14, 2022
A Nuxt.js module that injects a server route to serve the GraphQL Playground

@pin-pon/nuxt-graphql-playground A Nuxt.js module that injects a server route to serve the GraphQL Playground Setup Add @pin-pon/nuxt-graphql-playgrou

Pin-Pon 3 Sep 22, 2022
A tiny, SSR-safe directive for binding random data to an element.

1๏ธโƒฃ vue-bind-once A tiny, SSR-safe directive for binding random data to an element. A tiny, SSR-safe directive for binding random data to an element.

Daniel Roe 113 Jan 8, 2023
Matteo Bruni 4.7k Jan 4, 2023
NativeScript empowers you to access native api's from JavaScript directly. Angular, Vue, Svelte, React and you name it compatible.

NativeScript empowers you to access native APIs from JavaScript directly. The framework currently provides iOS and Android runtimes for rich mobile de

NativeScript 22k Jan 4, 2023