Code Monkey home page Code Monkey logo

nuxt-graphql-request's Introduction

nuxt-graphql-request

๐Ÿ“ก GraphQL Request Module

ci npm version Dependencies npm downloads code style: prettier License: MIT

Easy Minimal GraphQL client integration with Nuxt.js.

Features

  • Most simple and lightweight GraphQL client.
  • Promise-based API (works with async / await).
  • Typescript support.
  • AST support.
  • GraphQL Loader support.

๐Ÿ“– Release Notes ๐Ÿ“„ Docs

Setup

npx nuxi@latest module add graphql-request

For Nuxt2, use nuxt-graphql-request v6:

yarn add nuxt-graphql-request@v6 graphql --dev

nuxt.config.js

module.exports = {
  modules: ['nuxt-graphql-request'],

  build: {
    transpile: ['nuxt-graphql-request'],
  },

  graphql: {
    /**
     * An Object of your GraphQL clients
     */
    clients: {
      default: {
        /**
         * The client endpoint url
         */
        endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
        /**
         * Per-client options overrides
         * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
         */
        options: {},
      },
      secondClient: {
        // ...client config
      },
      // ...your other clients
    },

    /**
     * Options
     * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
     */
    options: {
      method: 'get', // Default to `POST`
    },

    /**
     * Optional
     * default: true (this includes cross-fetch/polyfill before creating the graphql client)
     */
    useFetchPolyfill: true,

    /**
     * Optional
     * default: false (this includes graphql-tag for node_modules folder)
     */
    includeNodeModules: true,
  },
};

Runtime Config

If you need to supply your endpoints at runtime, rather than build time, you can use the Runtime Config to provide your values:

nuxt.config.js

module.exports = {
  publicRuntimeConfig: {
    graphql: {
      clients: {
        default: {
          endpoint: '<client endpoint>',
        },
        secondClient: {
          endpoint: '<client endpoint>',
        },
        // ...more clients
      },
    },
  },
};

TypeScript

Type definitions should work out-of-the-box. You should already have Typescript set up to extend Nuxt's auto-generated config. If not, you can start here:

{
  "extends": "./.nuxt/tsconfig.json"
}

Usage

Component

useAsyncData

<script setup>
import { gql } from 'nuxt-graphql-request/utils';

const { $graphql } = useNuxtApp();

const query = gql`
  query planets {
    allPlanets {
      planets {
        id
        name
      }
    }
  }
`;

const { data: planets } = await useAsyncData('planets', async () => {
  const data = await $graphql.default.request(query);
  return data.allPlanets.planets;
});
</script>

User-defined functions

<script setup>
import { gql } from 'nuxt-graphql-request/utils';

const { $graphql } = useNuxtApp();

const query = gql`
  query planets {
    allPlanets {
      planets {
        id
        name
      }
    }
  }
`;

const planets = ref([])

const fetchPlanets = () => {
  const data = await $graphql.default.request(query);
  planets.value = data.allPlanets.planets;
}
</script>

Store actions

import { defineStore } from 'pinia';
import { gql } from 'nuxt-graphql-request/utils';
import { useNuxtApp } from '#imports';

type Planet = { id: number; name: string };

export const useMainStore = defineStore('main', {
  state: () => ({
    planets: null as Planet[] | null,
  }),
  actions: {
    async fetchAllPlanets() {
      const query = gql`
        query planets {
          allPlanets {
            planets {
              id
              name
            }
          }
        }
      `;

      const data = await useNuxtApp().$graphql.default.request(query);
      this.planets = data.allPlanets.planets;
    },
  },
});

GraphQL Request Client

Examples from the official graphql-request library.

Authentication via HTTP header

export default defineNuxtConfig({
  graphql: {
    clients: {
      default: {
        endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
        options: {
          headers: {
            authorization: 'Bearer MY_TOKEN',
          },
        },
      },
    },
  },
});
Incrementally setting headers

If you want to set headers after the GraphQLClient has been initialised, you can use the setHeader() or setHeaders() functions.

const { $graphql } = useNuxtApp();

// Override all existing headers
$graphql.default.setHeaders({ authorization: 'Bearer MY_TOKEN' });

// Set a single header
$graphql.default.setHeader('authorization', 'Bearer MY_TOKEN');
Set endpoint

If you want to change the endpoint after the GraphQLClient has been initialised, you can use the setEndpoint() function.

const { $graphql } = useNuxtApp();

$graphql.default.setEndpoint(newEndpoint);
passing-headers-in-each-request

It is possible to pass custom headers for each request. request() and rawRequest() accept a header object as the third parameter

<script setup>
import { gql } from 'nuxt-graphql-request/utils';

const { $graphql } = useNuxtApp();

const requestHeaders = {
  authorization: 'Bearer MY_TOKEN',
};

const planets = ref();

const fetchSomething = async () => {
  const query = gql`
    query planets {
      allPlanets {
        planets {
          id
          name
        }
      }
    }
  `;

  // Overrides the clients headers with the passed values
  const data = await $graphql.default.request(query, {}, requestHeaders);
  planets.value = data.allPlanets.planets;
};
</script>

Passing more options to fetch

export default defineNuxtConfig({
  graphql: {
    clients: {
      default: {
        endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
        options: {
          credentials: 'include',
          mode: 'cors',
        },
      },
    },
  },
});

Or using setHeaders / setHeader:

const { $graphql } = useNuxtApp();

// Set a single header
$graphql.default.setHeader('credentials', 'include');
$graphql.default.setHeader('mode', 'cors');

// Override all existing headers
$graphql.default.setHeaders({
  credentials: 'include',
  mode: 'cors',
});

Using GraphQL Document variables

<script setup>
import { gql } from 'nuxt-graphql-request/utils';

const { $graphql } = useNuxtApp();

const fetchSomething = async () => {
  const query = gql`
    query planets($first: Int) {
      allPlanets(first: $first) {
        planets {
          id
          name
        }
      }
    }
  `;

  const variables = { first: 10 };

  const planets = await this.$graphql.default.request(query, variables);
};
</script>

Error handling

<script setup>
import { gql } from 'nuxt-graphql-request/utils';

const { $graphql } = useNuxtApp();

const fetchSomething = async () => {
  const mutation = gql`
    mutation AddMovie($title: String!, $releaseDate: Int!) {
      insert_movies_one(object: { title: $title, releaseDate: $releaseDate }) {
        title
        releaseDate
      }
    }
  `;

  const variables = {
    title: 'Inception',
    releaseDate: 2010,
  };

  const data = await $graphql.default.request(mutation, variables);
};
</script>

GraphQL Mutations

<script setup>
import { gql } from 'nuxt-graphql-request/utils';

const { $graphql } = useNuxtApp();

const fetchSomething = async () => {
  const query = gql`
    {
      Movie(title: "Inception") {
        releaseDate
        actors {
          fullname # "Cannot query field 'fullname' on type 'Actor'. Did you mean 'name'?"
        }
      }
    }
  `;

  try {
    const data = await $graphql.default.request(query);
    console.log(JSON.stringify(data, undefined, 2));
  } catch (error) {
    console.error(JSON.stringify(error, undefined, 2));
    process.exit(1);
  }
};
</script>

Receiving a raw response

The request method will return the data or errors key from the response. If you need to access the extensions key you can use the rawRequest method:

import { gql } from 'nuxt-graphql-request/utils';

const { $graphql } = useNuxtApp();

const query = gql`
  query planets($first: Int) {
    allPlanets(first: $first) {
      planets {
        id
        name
      }
    }
  }
`;

const variables = { first: 10 };

const { data, errors, extensions, headers, status } = await $graphql.default.rawRequest(
  endpoint,
  query,
  variables
);
console.log(JSON.stringify({ data, errors, extensions, headers, status }, undefined, 2));

Batch queries

<script setup>
const { $graphql } = useNuxtApp();

const fetchSomething = async () => {
  const query1 = /* GraphQL */ `
    query ($id: ID!) {
      capsule(id: $id) {
        id
        landings
      }
    }
  `;

  const variables1 = {
    id: 'C105',
  };

  const query2 = /* GraphQL */ `
    {
      rockets(limit: 10) {
        active
      }
    }
  `;

  const query3 = /* GraphQL */ `
    query ($id: ID!) {
      core(id: $id) {
        id
        block
        original_launch
      }
    }
  `;

  const variables3 = {
    id: 'B1015',
  };

  try {
    const data = await $graphql.default.batchRequests([
      { document: query1, variables: variables1 },
      { document: query2 },
      { document: query3, variables: variables3 },
    ]);

    console.log(JSON.stringify(data, undefined, 2));
  } catch (error) {
    console.error(JSON.stringify(error, undefined, 2));
    process.exit(1);
  }
};
</script>

Cancellation

It is possible to cancel a request using an AbortController signal.

<script setup>
import { gql } from 'nuxt-graphql-request/utils';

const { $graphql } = useNuxtApp();

const fetchSomething = async () => {
  const query = gql`
    query planets {
      allPlanets {
        planets {
          id
          name
        }
      }
    }
  `;

  const abortController = new AbortController();

  const planets = await $graphql.default.request({
    document: query,
    signal: abortController.signal,
  });

  abortController.abort();
};
</script>

In Node environment, AbortController is supported since version v14.17.0. For Node.js v12 you can use abort-controller polyfill.

import 'abort-controller/polyfill';

const abortController = new AbortController();

Middleware

It's possible to use a middleware to pre-process any request or handle raw response.

Request & response middleware example (set actual auth token to each request & log request trace id if error caused):

function requestMiddleware(request: RequestInit) {
  const token = getToken();
  return {
    ...request,
    headers: { ...request.headers, 'x-auth-token': token },
  };
}

function responseMiddleware(response: Response<unknown>) {
  if (response.errors) {
    const traceId = response.headers.get('x-b3-traceid') || 'unknown';
    console.error(
      `[${traceId}] Request error:
        status ${response.status}
        details: ${response.errors}`
    );
  }
}

export default defineNuxtConfig({
  modules: ['nuxt-graphql-request'],

  graphql: {
    /**
     * An Object of your GraphQL clients
     */
    clients: {
      default: {
        /**
         * The client endpoint url
         */
        endpoint: 'https://swapi-graphql.netlify.com/.netlify/functions/index',
        /**
         * Per-client options overrides
         * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
         */
        options: {
          requestMiddleware: requestMiddleware,
          responseMiddleware: responseMiddleware,
        },
      },

      // ...your other clients
    },

    /**
     * Options
     * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
     */
    options: {
      method: 'get', // Default to `POST`
    },

    /**
     * Optional
     * default: false (this includes cross-fetch/polyfill before creating the graphql client)
     */
    useFetchPolyfill: true,

    /**
     * Optional
     * default: false (this includes graphql-tag for node_modules folder)
     */
    includeNodeModules: true,
  },
});

Why use nuxt-graphql-request over @nuxtjs/apollo?

Don't get me wrong, Apollo Client is great and well maintained by the vue / nuxt community, I used Apollo Client for 18months before switching to graphql-request.

However, as I am obsessed with performances, Apollo Client doesn't work for me at all:

  • I don't need another state management as the Vue ecosystem is enough (Vuex & Persisted data).
  • I don't need an extra ~120kb parsed in my app for fetching my data.
  • I don't need subscriptions as I use pusher.com, there are also alternatives for a WS client: http://github.com/lunchboxer/graphql-subscriptions-client

Why do I have to install graphql?

graphql-request uses a TypeScript type from the graphql package such that if you are using TypeScript to build your project and you are using graphql-request but don't have graphql installed TypeScript build will fail. Details here. If you are a JS user then you do not technically need to install graphql. However, if you use an IDE that picks up TS types even for JS (like VSCode) then it's still in your interest to install graphql so that you can benefit from enhanced type safety during development.

Do I need to wrap my GraphQL documents inside the gql template exported by graphql-request?

No. It is there for convenience so that you can get the tooling support like prettier formatting and IDE syntax highlighting. You can use gql from graphql-tag if you need it for some reason too.

What's the difference between graphql-request, Apollo and Relay?

graphql-request is the most minimal and simplest to use GraphQL client. It's perfect for small scripts or simple apps.

Compared to GraphQL clients like Apollo or Relay, graphql-request doesn't have a built-in cache and has no integrations for frontend frameworks. The goal is to keep the package and API as minimal as possible.

Does nuxt-graphql-request support mutations?

Sure, you can perform any GraphQL queries & mutations as before ๐Ÿ‘

Development

  1. Clone this repository
  2. Install dependencies using yarn install or npm install
  3. Start development server using yarn dev or npm run dev

Roadmap

๐Ÿ“‘ License

MIT License

nuxt-graphql-request's People

Contributors

blindpupil avatar danielroe avatar drewbaker avatar gomah avatar narduin avatar nicktrn avatar samturrell avatar sykes10 avatar zsavajji avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nuxt-graphql-request's Issues

What is AST support?

I'm curious what the AST: true option does? I've come from Apollo and haven't seen that before. Could you explain in the docs a little perhaps? Thanks.

how to configure header for stateful authentication?

Hi
I'm new to Nuxt 3 GraphQL with Laravel Sanctum
I'm getting CSRF token from the server using below code and it is stored in browser cookie

export default defineNuxtPlugin(csrf => {
    $fetch('http://localhost/sanctum/csrf-cookie').catch((error) => console.log(error));
  })

image

but not sure to set these to GraphQL header.

If these feature is already supported, I would request you to make the documentation more clear for stateful authentication otherwise would like to have this feature soon

Response always returns null?

Apologies for opening another issue, but I'm really hoping I can get this library to work.

In a page, I'm running this fetch function:

async fetch ({ env, $graphql, req }) {
  const payload = {
    requestHeaders: { authorization: handleCookies.get('gc-token', req.headers.cookie) }
  };
  const res = await userService.currentUser(payload);
},

And in that service file, I'm running this:


import { GraphQLClient } from 'graphql-request';
import ME_QUERY from '~/apollo/queries/user/me.gql';

const url = process.env.NUXT_ENV_BACKEND_API_URL;
const client = new GraphQLClient(url);

async function currentUser ({ requestHeaders }) {
  await client.request(ME_QUERY, {}, requestHeaders)
    .then(data => console.log('currentUser data: ', data))
    .catch(e => console.log('ERROR: ', e));

  User.insertOrUpdate({ data: { ...currentUser } });
  return currentUser;
}

And my nuxt.config.js looks like this:

export default {
  buildModules: [
    'nuxt-graphql-request',
    '@nuxtjs/eslint-module',
    '@nuxtjs/vuetify',
    '@nuxtjs/style-resources'
  ],
  graphql: {
    endpoint: process.env.NUXT_ENV_BACKEND_API_URL
  },
}

For some reason, all of my requests are just returning null. I know that data exists, and I can correctly return it in graphql-playground. I tried moving the entire service function back over to the main fetch call in the page, but it has the same results. Is there anything obvious I'm missing here?

works with nuxt fetch ?

Hello, this is a question not an issue ;-)
As I'm struggling with nuxt apollo module with full static, I saw your package as an alternative. The docs says that it works with asyncData but is it working with nuxt fetch (https://nuxtjs.org/docs/2.x/components-glossary/pages-fetch) so that I can fetch data from components too ?
Thank you.

Edit: It perfectly works in case this interest someone ;-)

typescript type

Is there any typescript type like what we have in @nuxt/axios?

import { NuxtAxiosInstance } from '@nuxtjs/axios'

suggest using buildModules

First of all nice work!

I think it would be nice if we suggest users installing as devDependency and adding to buildModules since module is only build time.

Var Interpolation

Any chance we can have ${ interpolation} instead of the more complex request(mutation, variables); ?

Example:

      const gqlRequest = gql`
          mutation {
            getItem( animalData: {
                id: ${itemID},
            }
            ){
              stats
            }
          }
        `

Would be rad

Returned Data is Inside Errors

I'm trying to handle errors on a mutation with variables and this is what I have:

async fetchSomething() {
  const mutation = gql`
    mutation AdminLogin($email: String!, $password: String!) {
      al(input: { email: $email, password: $password }) {
        token
        firstName
        lastName
        email
      }
    }
  `

  const variables = { email: this.form.email, password: this.form.password }

  try {
    const data = await this.$graphql.default.request(mutation, variables)
    // eslint-disable-next-line no-console
    console.log(JSON.stringify(data))
  } catch (error) {
    // eslint-disable-next-line no-console
    console.error(JSON.stringify(error))
  }
},

What's interesting is the mutation goes through fine and returns the data, except the data is inside of error so it always fails the try catch... It also has a status inside of error with the code being 200. Not sure what's happening to get my data inside of error but the same endpoint works with nuxt/apollo.

Example Response:

{"response":{"error":"{\"data\":{\"al\":{\"token\":\"REDACTED\",\"firstName\":\"REDACTED\",\"lastName\":\"REDACTED\",\"email\":\"REDACTED\"}}}","status":200},"request":{"query":"mutation AdminLogin($email: String!, $password: String!) {\n  al(input: {email: $email, password: $password}) {\n    token\n    firstName\n    lastName\n    email\n  }\n}\n","variables":{"email":"REDACTED","password":"REDACTED"}}}

How to get requests once with nuxtServerInit on nuxt generate

I know that cache is not handled by this project, but do anyone happen to have a suggestion on how this could be accomplished?

I fetch the data with nuxtServerInit in store/index.js but this will run every time i refresh the page, or many times when the command nuxt generate runs. This is apparently expected behavior for nuxtServerInit and there is extensions you could use to get around this if you use axios.

So is there any similar solution, or any other way that i could do this without fetching data multiply times?

Persisted query or compression (query exceeding 8192 bytes)

How would we implemented persisted query on your library or type of compression? As we are currently experience GraphQL exceeded query limit of 8kb. We already use another library to minify our GraphQL queries but it seems to be not a long term solution, and after a few days we hit the error again.

Here is the error: Query cannot be executed. The maximum allowed size for a query is 8192 bytes but it was 8604 bytes

Refresh Token

Hi,

First, thank you very much for this module!

Is there any current support for refresh tokens? My access token is not fixed, and should be refreshed (around) every 10 minutes.

When the access token is expired, the client should make a new authToken() request and get a new access token.
I'm trying to figure out if it's possible to handle such errors (token expired) on the project level (such as some kind of error interceptor)? Or is this module is made to deal differently with such cases?

My (relevant) nuxt.config.js

  buildModules: [
    // https://go.nuxtjs.dev/typescript
    '@nuxt/typescript-build',
    // https://go.nuxtjs.dev/vuetify
    '@nuxtjs/vuetify',
    // https://github.com/Gomah/nuxt-graphql-request
    'nuxt-graphql-request',
  ],

  graphql: {
    /**
     * Your GraphQL endpoint
     */
    endpoint: 'http://localhost:8000/graphql',

    /**
     * Options
     * See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
     */
    options: {},

    /**
     * Optional
     * default: true (this includes cross-fetch/polyfill before creating the graphql client)
     */
    useFetchPolyfill: true,

    /**
     * Optional
     * default: false (this includes graphql-tag for node_modules folder)
     */
    includeNodeModules: true,
  },

my project dependencies:

"dependencies": {
    "@nuxt/typescript-runtime": "^2.0.0",
    "@nuxtjs/axios": "^5.12.2",
    "@nuxtjs/pwa": "^3.0.2",
    "core-js": "^3.6.5",
    "graphql-tag": "^2.11.0",
    "nuxt": "^2.14.6",
    "vue-class-component": "^7.2.6",
    "vue-property-decorator": "^9.1.2",
    "vuex-class-component": "^2.3.5"
  },
  "devDependencies": {
    "@nuxt/types": "^2.14.6",
    "@nuxt/typescript-build": "^2.0.3",
    "@nuxtjs/eslint-config": "^3.1.0",
    "@nuxtjs/eslint-config-typescript": "^3.0.0",
    "@nuxtjs/eslint-module": "^2.0.0",
    "@nuxtjs/vuetify": "^1.11.2",
    "@wdio/cli": "^6.5.2",
    "@wdio/local-runner": "^6.5.2",
    "@wdio/mocha-framework": "^6.5.0",
    "@wdio/spec-reporter": "^6.4.7",
    "@wdio/sync": "^6.5.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^7.10.0",
    "eslint-config-prettier": "^6.12.0",
    "eslint-plugin-nuxt": "^1.0.0",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-wdio": "^6.0.12",
    "graphql": "^15.4.0",
    "nuxt-graphql-request": "^3.2.0",
    "prettier": "^2.1.2",
    "webdriverio": "^6.5.2"
  }

Error while building `'getSdk' is not exported by .nuxt/gql-sdk.ts, imported by node_modules/nuxt-graphql-client/dist/runtime/composables/index.mjs`

nuxt.config.ts

import { defineNuxtConfig } from 'nuxt'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
  css: ['vuetify/lib/styles/main.sass', 'mdi/css/materialdesignicons.min.css'],
  build: {
    transpile: ['vuetify', 'chart.js'],
  },
  meta: {...},
  publicRuntimeConfig: {
    lastfmApiKey: process.env.LASTFM_API_KEY,
    apiUrl: process.env.API_URL,
    GQL_HOST: `${process.env.API_URL}/graphql`,
  },
  buildModules: ['@pinia/nuxt'],
  modules: ['nuxt-graphql-client'],
  vite: {
    define: {
      'process.env.DEBUG': false,
    },
  },
  // https://github.com/nuxt/bridge/issues/50
  hooks: {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    'vite:extendConfig'(clientConfig: any, { isClient }: any) {
      if (isClient) {
        clientConfig.build.rollupOptions.output.manualChunks = {
          'vue-chartjs': ['vue-chartjs'],
        }
      }
    },
  },
})

dependencies

"nuxt-graphql-client": "^0.0.33",
"nuxt": "3.0.0-rc.3",

full nuxt build output

$ nuxt build
Nuxt CLI v3.0.0-rc.6                                                                        13:21:47

 ERROR  (node:36204) ExperimentalWarning: buffer.Blob is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)


 ERROR  'getSdk' is not exported by .nuxt/gql-sdk.ts, imported by node_modules/nuxt-graphql-client/dist/runtime/composables/index.mjs
file: /node_modules/nuxt-graphql-client/dist/runtime/composables/index.mjs:4:9
2: import { GraphQLClient } from "graphql-request";
3: import { deepmerge } from "../utils.mjs";
4: import { getSdk as gqlSdk } from "#build/gql-sdk";
            ^
5: import { ref, useNuxtApp, useRuntimeConfig, useRequestHeaders } from "#imports";
6: const DEFAULT_STATE = { proxyCookies: true };


 ERROR  'getSdk' is not exported by .nuxt/gql-sdk.ts, imported by node_modules/nuxt-graphql-client/dist/runtime/composables/index.mjs

  at error (node_modules/rollup/dist/shared/rollup.js:198:30)
  at Module.error (node_modules/rollup/dist/shared/rollup.js:12542:16)
  at Module.traceVariable (node_modules/rollup/dist/shared/rollup.js:12901:29)
  at ModuleScope.findVariable (node_modules/rollup/dist/shared/rollup.js:11553:39)
  at ReturnValueScope.findVariable (node_modules/rollup/dist/shared/rollup.js:6486:38)
  at ChildScope.findVariable (node_modules/rollup/dist/shared/rollup.js:6486:38)
  at Identifier.bind (node_modules/rollup/dist/shared/rollup.js:7553:40)
  at CallExpression.bind (node_modules/rollup/dist/shared/rollup.js:5383:23)
  at CallExpression.bind (node_modules/rollup/dist/shared/rollup.js:9049:15)
  at VariableDeclarator.bind (node_modules/rollup/dist/shared/rollup.js:5383:23)

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Best way to set Bearer token dynamically in nuxt.config.js?

Hey there,

Wondering what the best way is to set the Bearer token in nuxt.config.js?

I'm using another library called cookie-universal-nuxt to get/set cookies (where I'm storing the token). Here's what I currently have:

nuxt.config.js:

graphql: {
  endpoint: process.env.NUXT_ENV_BACKEND_API_URL,
  options: './apollo/config.js'
},

config.js:

export default ({ $cookies }) => {
  return {
      headers: {
        authorization: `Bearer: ${$cookies.get('gc_token')}`
      }
  };
};

This doesn't seem to be working at all though. Any ideas how to dynamically insert the token?

Use with pinia

Hello!

I was wondering if we can use this module to make requests inside pinia.
I saw the example for vuex but I was not able to make it work with pinia yet.

I can make calls from pages and component just fine as usual.
I have the following inside a store.js file:

// stores/customStore.js

import { defineStore } from 'pinia'
import customQuery from '~/graphql/queries/custom'

export const usecustomStore = defineStore('customStore', {
	state: () => ({
		data: [],
	}),
	actions: {
		async fetchcustom() {
			this.data = await this.$graphql.default.request(customQuery)
		},
	},
})

I get the following error when calling fetchcustom() inside a component: Cannot read properties of undefined (reading 'default') from this.$graphql.default

Any idea? Thanks!

Types not working

Type inference does not work when using the composition api. $graphql is not typed for example.

export default defineComponent({
  setup() {
    const { $graphql } = useContext()
    const data = useAsync(() =>
      $graphql.request(gql`
        query MyQuery {
        }
      `)
    )
    return { data }
  },
})

Access $graphql in fetch hook?

I looked at the other related ticket (#1 ) but didn't want to chain on a comment to a closed ticket.

I'm working to rip out vue-apollo from my app and instead use a combination of this library, normalizr to flatten my data and vuex. I'm attempting to run a simple fetch hook on page load of the login page to get started, however I'm unable to find the $graphql instance.

async fetch () {
    console.log(this.$nuxt.context);
    // this.authImages = await authService.fetchImages($graphql);
},

You'd mentioned in the other ticket that it should be available in context, and the Nuxt docs state "You can access the Nuxt context within the fetch hook using this.$nuxt.context".

Essentially I'm trying to pass along the $graphql instance to a service function in a separate file to keep my main .vue files clean. I'm sure it's something simple, but what am I missing here?

Nuxt bridge compatibility

Hi, I guess this module in not compatible with the new nuxt/bridge? In dev everything is working well, but in production I get this error:

> node .output/server/index.mjs
Listening on http://localhost:3000

Cannot find package '....path/.output/server/node_modules/ramda/' imported from /....path/.output/server/chunks/app/server.mjs
  at new NodeError (internal/errors.js:322:7)  
  at legacyMainResolve (internal/modules/esm/resolve.js:245:9)  
  at packageResolve (internal/modules/esm/resolve.js:680:14)  
  at moduleResolve (internal/modules/esm/resolve.js:728:18)  
  at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:842:11)  
  at Loader.resolve (internal/modules/esm/loader.js:89:40)  
  at Loader.getModuleJob (internal/modules/esm/loader.js:242:28)  
  at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:76:40)  
  at link (internal/modules/esm/module_job.js:75:36)

Does anyone know a workaround for this? ๐Ÿค”
Thanks!

Does nuxt-graphql-request support mutations?

Hey,

I'm currently looking for a more lightweight replacement for apollo. So I stumpled upon this library.
I'm wondering if we can do mutations too with it. Couldn't find anything in the docs about it.

Thank you!

Regards Kevin

Auth Integration

I think there most be a better way to integrate this plugin with nuxt-auth.
Setting the bearer anytime you to want to send a request isn't not realistic.

[unhandledRejection] serialize is not defined

I'm getting an issue with Nuxt 3 integration out of the box.

It's saying:

 ERROR  [unhandledRejection] serialize is not defined                                                                                                                                20:43:45

  at eval (eval at <anonymous> (node_modules/lodash.template/index.js:1550:12), <anonymous>:8:59)
  at compileTemplate (node_modules/@nuxt/kit/dist/index.mjs:511:45)
  at async node_modules/nuxt/dist/index.mjs:1562:22
  at async Promise.all (index 13)
  at async generateApp (node_modules/nuxt/dist/index.mjs:1561:3)
  at async _applyPromised (node_modules/perfect-debounce/dist/index.mjs:54:10)

Does this library support Nuxt 3?

useFetchPolyfill not needed?

The useFetchPolyfill is enabled by default but as far as I know (and it was confirmed by Nuxt developer), Nuxt already comes with a fetch polyfill itself so this option shouldn't be needed or enabled by default.

Do you know why specifically it was added? Maybe old Nuxt versions didn't provide a polyfill?

Can't set authorization header

I'm trying to add the authorization header to the nuxt.config.js like this:

export default {
  /*
  ** Nuxt.js modules
  */
  modules: [
    'nuxt-graphql-request',
  ],
  /*
  ** GraphQL client configuration
  */
  graphql: {
    /*
    ** Your GraphQL endpoint (required)
    */
    endpoint: 'MY_ENDPOINT',
    /*
    ** Options
    ** See: https://github.com/prisma-labs/graphql-request#passing-more-options-to-fetch
    */
    options: {
      headers: {
        authorization: 'Bearer MY_TOKEN'
      },
    },

    /**
     * Optional
     * default: false (this includes graphql-tag for node_modules folder)
     */
    includeNodeModules: true,
  },
}

But I am getting an error:

Headers is not defined

Call seems to be made, because when no options are provided, I get an unauthorized response.

includeNodeModules

Thanks for this module !
I'm wondering though why you set includeNodeModules to true in the example config, when you describe in the comment above the default is false. What is it used for ? Why activate it in the example config?

Authorization header visible in static generation

Hello,

I'm extremely grateful for your module, thanks a lot.

I'm using it with a headless CMS (directus) and nuxt generate for a full static website.
As I'm using nuxt generate, I thought a static header Bearer static_token with read only access would be enough.

While inspecting the generated code, I noticed that the graphql endpoint and all the conf is visible, including the authorization header.

I'm wondering if it's an expected behaviour or if I'm supposed to try and hide those informations, or if they should not be rendered at all as no communication is made between the website and the CMS (except during generate)โ€ฆ

Thanks!

Not compatible with runtime config

If using an env variable for the endpoint value, this value needs to be provided at built time and cannot be dynamically updated later. The nuxt Runtime Config aims to solve this problem, by giving you access to a $config object where the correct config variables are provided.

I have this working locally by updating the plugin.js to contain the following:

import { GraphQLClient } from 'graphql-request';

if (<%= options.useFetchPolyfill %>) {
  require('cross-fetch/polyfill');
}

export default (ctx, inject) => {
  const clientOptions = <%= serialize(options.options) %>;

  const client = new GraphQLClient(ctx.$config.API_URL || '<%= options.endpoint %>', clientOptions);

  // Inject the graphql client to the context as $graphql
  ctx.$graphql = client;
  inject('graphql', client);
};

Config variable can be updated to something else if required. Happy to PR my changes if they work for you.

Feature request: Retry request on fail

I know that the point of GQL request is to be very simple, so maybe this is not within scope... but man I'd love retry to be built into this module!

Something like this:

  graphql: {
    clients: {
      default: {
          retry: {
            attempts: 3,
            delay: 1000         
          }
      }
    }
}    

And when the request fails for any reason, it waits 1000 between each retry 3 times, before really failing.

The thing is, I actually really want these for some old Nuxt2 projects that fail SSG builds due to a slow-to-scale API.

Nuxt fetch() hook (2.12)

Does it work with Nuxt's fetch() hook? It's just like asyncData(), but can be used in every component for SSR.

Also, is it possible to use this package with Vue without Nuxt?

Any methods to get loading/pending state?

Does graphql-request expose anything like $graphql.pending or $graphql.loading? Would be great to have access to that in my templates to show things like a loading spinner when lazy-loading etc...

Session headers

Hi, this is more a question than an issue... is it possible to replicate this type of functionality from Apollo in nuxt-graphql-request?

import { HttpLink } from 'apollo-link-http'
import { ApolloLink } from 'apollo-link'

const httpLink = new HttpLink({
	uri: process.env.GQL_ENDPOINT,
})

// Middleware operation
// If we have a session token in localStorage, add it to the GraphQL request as a Session header.

export const middleware = new ApolloLink((operation, forward) => {
	const session = localStorage.getItem('woo-session')
	if (session && session.length > 0) {
		operation.setContext(({ headers = {} }) => ({
			headers: {
				'woocommerce-session': `Session ${session}`,
			},
		}))
	}
	return forward(operation)
})

// Afterware operation
// This catches the incoming session token and stores it in localStorage, for future GraphQL requests.

export const afterware = new ApolloLink((operation, forward) => {
	return forward(operation).map((response) => {
		const context = operation.getContext()
		const { response: { headers } } = context
		const session = headers.get('woocommerce-session')

		if (session) {
			if (localStorage.getItem('woo-session') !== session) {
				localStorage.setItem('woo-session', headers.get('woocommerce-session') )
			}
		}
		return response
	})
})

export default function () {
	return {
		// default 'apollo' definition
		defaultOptions: {
			$query: {
				loadingKey: 'loading',
				fetchPolicy: 'cache-and-network',
			},
		},
		defaultHttpLink: false,
		link: middleware.concat(afterware.concat(httpLink)),
		httpEndpoint: process.env.graphqlUrl,
		fetchOptions: {
			mode: 'cors',
		},
		httpLinkOptions: {
			credentials: 'include'
		},
	}
}

I'm asking because since I found this module I try to avoid using Apollo as much as possible, but in this case I'm not sure if this kind of request is doable with nuxt-graphql-request. ๐Ÿค”

Thanks in advance!

Graphql-tag loader breaks when using this module

I am trying to add this module to slowly replace the graphql-apollo client we have in our stack.

However I am getting stuck with the graphql-tag loader breaking when this module is added for some reason.

Webpack is configured to transpile graphql files

extend (config, { isClient }) {
    config.module.rules.push({
      test: /\.(graphql|gql)$/,
      exclude: /node_modules/,
      loader: 'graphql-tag/loader'
    })
}

If I only use graphql-request then everything works as expected I can use the query imported from a graphql file to make a request

when I try to add nuxt-graphql-request
I get the error:

Module build failed (from ./node_modules/graphql-tag/loader.js):
GraphQLError: Syntax Error: Unexpected Name "var".

This error is especially baffling because we don't even have 'var' basically anywhere in the code base, only in CSS

I tried all sorts of combos, using it as dev/prod dependency, registering as module instead of buildModule, nothing works.

Generate dynamic routes width payload for full static site

I would like to import .gql files into nuxt.config.js. How can I do that?

I get this error:
Screenshot 2021-10-15 at 09 46 12

This is my nuxt.config.js

import { request, gql } from 'graphql-request'
import PostsQuery from './queries/posts.gql'

export default {
  target: 'static',
  env: {
    baseUrl: process.env.BASE_URL || 'http://localhost:3000',
    graphql: process.env.WP_GQL_URL || 'https://wpress.test/graphql'
  },
  head: {
    title: 'title',
    htmlAttrs: {
      lang: 'en'
    },
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' },
      { name: 'format-detection', content: 'telephone=no' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },
  css: [
  ],
  plugins: [
  ],
  components: true,
  buildModules: [
    '@nuxtjs/eslint-module',
    '@nuxtjs/tailwindcss',
    'nuxt-graphql-request'
  ],
  eslint: {
    fix: true
  },
  modules: [
    // https://go.nuxtjs.dev/axios
    '@nuxtjs/axios',
    '@nuxtjs/i18n'
  ],
  graphql: {
    clients: {
      default: {
        endpoint: process.env.WP_GQL_URL,
        includeNodeModules: false
      }
    }
  },
  axios: {},

  i18n: {
    locales: [
      {
        code: 'en',
        name: 'English'
      },
      {
        code: 'pt',
        name: 'Portugese'
      }
    ],
    defaultLocale: 'en',
    vueI18n: {
      fallbackLocale: 'en',
    }
  },
  build: {
    loaders: {
      sass: {
        implementation: require('sass')
      },
      scss: {
        implementation: require('sass')
      }
    }
  },
  router: {
    prefetchLinks: false
  },
  generate: {
    fallback: true,
    routes () {
      return request(process.env.WP_GQL_URL, PostsQuery).then(
        (res) => {
          return res.posts.edges.map((post) => {
            return {
              route: `${post.node.language.slug != 'en' ? '/' + post.node.language.slug : ''}/blog/${post.node.slug}`,
              payload: post.node
            }
          })
        }
      )
    }
  }
}

JS error at index.ts 36:8 browser-ponyfill.js

Hi @Gomah, thanks so much porting this module to nuxt 3 !!!

I just installed it and I get a Syntax error with the browser-ponyfill.js lib.
I am using Node 18.18.0 and latest nuxt 3.7.4
Can you easily spot what the problem is here?

Uncaught SyntaxError: The requested module '/_nuxt/node_modules/graphql-request/node_modules/cross-fetch/dist/browser-ponyfill.js?v=9d888ccb' does not provide an export named 'default' (at index.ts:36:8)

This also seems to stop the developer tools from loading anything.

Generate Dynamic Routes

There's no example in the docs for this, so curious if it's an option.

Using Apollo I can do as suggested in this blog post: https://rosso.codes/blog/nuxt-generate-dynamic-routes-with-apollo-and-graphql/

... and create dynamic routes via GraphQL. Basically I need to go get a list of slugs from my CMS (Contentful) and generate the routes in nuxt.config.js using that list.

Any way to do so with this module? I like this module for fetching data for my pages and would like to use it here too if I can.

Using graphql request inside `generate` to request data for routes?

This is more of a question than an issue. We're currently using nuxt-graphql-request in our project and it's working great.

However, we're looking to make a graphQL request in the generate property of the Nuxt config in order to generate routes based on the query response, something similar is outlined in this post which uses Apollo:
https://rosso.codes/blog/nuxt-generate-dynamic-routes-with-apollo-and-graphql/

Wondering if there's a way to reference/access the graphql property created in the Nuxt config INSIDE another property in the config? Obviously we can't use this.$graphql inside the generate property.

Or perhaps there's a way to do this using middleware? Any thoughts welcome. Thanks!

Runtime config broken

Hi @Gomah

I've just tried to update to the latest version of the plugin, and it seems the runtime config is no longer working.

Looking at the code, it looks like the options are now being merged using mergeDeepRight from the ramda package.

This doesn't seem to be working correctly. I don't believe this function takes a 3rd parameter so the runtime config values are never being passed in. This can be seen using the following code on the ramda documentation website in the console:

R.mergeDeepRight({ "a": 1 }, { "b": 2 }, { "c": 3 })

The output is:

{
    "a": 1,
    "b": 2
}

This dependency was not found: graphql-request

image

I have a project that has been running just fine in dev and prod until 6th March 2023 the build failed in a Github Action and my investigations led me to the peer dependency error above on dev.

Also, find the GitHub Actions Build Error below.

ERROR in ./.nuxt/graphql-request.js
Module not found: Error: Can't resolve 'graphql-request' in '/usr/src/nuxt-app/.nuxt'
@ ./.nuxt/graphql-request.js 13:0-48 33:93-106
@ ./.nuxt/index.js
@ ./.nuxt/client.js
@ multi ./node_modules/@nuxt/components/lib/installComponents.js ./.nuxt/client.js

ERROR in ./node_modules/nuxt-graphql-request/lib/module.js
Module not found: Error: Can't resolve 'graphql-request' in '/usr/src/nuxt-app/node_modules/nuxt-graphql-request/lib'
@ ./node_modules/nuxt-graphql-request/lib/module.js 3:52-78
@ ./graphql/queries/order.js
@ ./node_modules/babel-loader/lib??ref--2-0!./node_modules/@nuxt/components/dist/loader.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./components/orders/staged/StagedOrdersPerCustomerTable.vue?vue&type=script&lang=js&
@ ./components/orders/staged/StagedOrdersPerCustomerTable.vue?vue&type=script&lang=js&
@ ./components/orders/staged/StagedOrdersPerCustomerTable.vue
@ ./.nuxt/components/index.js
@ ./.nuxt/components/plugin.js
@ ./.nuxt/index.js
@ ./.nuxt/client.js
@ multi ./node_modules/@nuxt/components/lib/installComponents.js ./.nuxt/client.js

ERROR in chunk app [initial]
f16b55e.js
/usr/src/nuxt-app/node_modules/babel-loader/lib/index.js??ref--2-0!/usr/src/nuxt-app/.nuxt/index.js f2f7a50d8a24731a8967cb340f489e2c
Unexpected token (34:129)
| var runtimeConfig = ctx.$config && ctx.$config.graphql && ctx.$config.graphql.clients && ctx.$config.graphql.clients[clientName] || {};
| var clientConfig = WEBPACK_MODULE_REFERENCE__82_6d65726765416c6c_call([baseOptions, config, runtimeConfig]);
| return _objectSpread(_objectSpread({}, clients), {}, WEBPACK_MODULE_REFERENCE__7_64656661756c74_call({}, clientName, new !(function webpackMissingModule() { var e = new Error("Cannot find module 'graphql-request'"); e.code = 'MODULE_NOT_FOUND'; throw e; }())(clientConfig.endpoint, clientConfig.options)));
| }, {});
| ctx.$graphql = graphClients;

FATAL Nuxt build error

at WebpackBundler.webpackCompile (node_modules/@nuxt/webpack/dist/webpack.js:1814:21)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async WebpackBundler.build (node_modules/@nuxt/webpack/dist/webpack.js:1779:5)
at async Builder.build (node_modules/@nuxt/builder/dist/builder.js:249:5)
at async Object.run (node_modules/@nuxt/cli/dist/cli-build.js:99:7)
at async NuxtCommand.run (node_modules/@nuxt/cli/dist/cli-index.js:356:7)

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ โ”‚
โ”‚ โœ– Nuxt Fatal Error โ”‚
โ”‚ โ”‚
โ”‚ Error: Nuxt build error โ”‚
โ”‚ โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
The command '/bin/sh -c yarn build' returned a non-zero code: 1
Error: Process completed with exit code 1.

ERROR Headers is not defined on nuxt generate

Using version 3.1.1.

If I I config the client like this:

    graphql: {
        AST: true,
        endpoint: process.env.DEFAULT_ENDPOINT,
        options: {
            credentials: "include",
            mode: "cors",
             headers: {
                 authorization: `Bearer ${process.env.BASIC_API_TOKEN || ""}`,
             },
        },
    },

And then run nuxt generate I'll get this warning on all routes as it generates.

 ERROR  Headers is not defined                                                                                             12:58:27

  at resolveHeaders (node_modules/graphql-request/dist/index.js:74:32)
  at GraphQLClient.<anonymous> (node_modules/graphql-request/dist/index.js:135:35)
  at step (node_modules/graphql-request/dist/index.js:44:23)
  at Object.next (node_modules/graphql-request/dist/index.js:25:53)
  at node_modules/graphql-request/dist/index.js:19:71

  at new Promise (<anonymous>)
  at __awaiter (node_modules/graphql-request/dist/index.js:15:12)
  at GraphQLClient.request (node_modules/graphql-request/dist/index.js:129:16)
  ...

Import gql Module '"nuxt-graphql-request"' has no exported member 'gql'.

Thank you for your library very easy to use however I am encountering an error when importing your library on TypeScript stated on the title: import gql Module '"nuxt-graphql-request"' has no exported member 'gql'.

Here is some of my code:

...
import {gql} from 'nuxt-graphql-request'

...

export default class MyPage extends Vue {
  async asyncData({$graphql}) {
   const query = ... // omitted
   const data = await $graphql.default.request(query)
   return {data}
  }
}

I was able to successfully query my data and display it on my website on JavaScript, however when switching to TypeScript I am encountering the said error.

Dev or production dependency?

The Readme states the the module should be installed as a dev-dependency.

But if one follows that then it's no longer possible to do either:

import { gql } from 'nuxt-graphql-request';

or

import { gql } from 'graphql-request';

in a Vue component with only production dependencies, while handling the SSR request since both of those imports are not installed and the server bundle doesn't include stuff from node_modules.

So it seems to me that the module is a bit confused about that.

Note that:

  • There is a separate issue with types that prevents the first import variant from working because gql is not exported from types. But that can be solved by using the second variant.

Get error when call fetchSomething in beforeMount when test with jest

<script>
import { gql } from 'nuxt-graphql-request';

export default {
beforeMount(){
  this.fetchSomething()
},
  methods: {
    async fetchSomething() {
      const query = gql`
        {
          Movie(title: "Inception") {
            releaseDate
            actors {
              fullname # "Cannot query field 'fullname' on type 'Actor'. Did you mean 'name'?"
            }
          }
        }
      `;

      try {
        const data = await this.$graphql.default.request(endpoint, query);
        console.log(JSON.stringify(data, undefined, 2));
      } catch (error) {
        console.error(JSON.stringify(error, undefined, 2));
        process.exit(1);
      }
    },
  },
};
</script>

image

hi there.. i just got this error when test using jest . my test just like below
image

the #graphql.default is not undefined in test mode ..but running di developer process. thanks for any feedback

Client options are overriding each other

So today I noticed that if you specify multiple clients, that the options for the second client become the options for all clients.

For example, here is the config I have:

/*
    graphql: {
        clients: {
            default: {
                endpoint: process.env.GQL_ENDPOINT,
                options: {
                    credentials: "include",
                    mode: "cors",
                },
            },
            shopify: {
                endpoint: process.env.SHOPIFY_ENDPOINT,
                options: {
                    credentials: "same-origin",
                    mode: "cors",
                    headers: {
                        "Content-Type": "application/json",
                        "X-Shopify-Storefront-Access-Token":
                            process.env.SHOPIFY_TOKEN,
                    },
                },
            },
        },
    },

The default client will actually send the headers that are defined in the Shopify client. Am I doing something wrong here? Or is this intended behavior?

I found this out because my default client is a CMS, and that server was complaining about the X-Shopify-Storefront-Access-Token being included in the request headers.

I noticed that if you change the order of the config, it's always the second one that overrides the first.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.