0.3.0 • Published 3 years ago

@moirei/agile-graphql v0.3.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

agile-graphql

A GraphQL client wrapper for the frontend. This package provides a fluent query builder and a Prisma.js schema delegation style CRUD for a more intuitive queries.

:green_heart: Features

  • Predefine models once and perform crud queries without repeating yourself
  • Dynamic curd and query operations
  • Query Mapping for Vue Components

Installation

npm i @moirei/agile-graphql

Configuration

Although optional, but recommended. If no configuration provided, query fields must be passed as the last argument to every query/mutation.

See full configuration.

const config = {
  defaults: {
    keyField: 'id',
    query: {
      findUnique: ['id', 'name'], // default query fields for all models
    },
  },
  // Only needed for CRUD operations
  crud: {
    users: {
      query: ['id', 'name', 'email'], // default query fields
      fetchPolicy: 'no-cache',
    },
    orders: {
      query: ['reference', 'total', 'items{ id quantity }'],
      keyField: 'reference',
      fetchPolicy: {
        findUnique: 'network-only',
      },
    },
  },
}

Usage

import { Graph } from '@moirei/agile-graphql'
import { ApolloClient } from 'apollo-client'

const apollo = new ApolloClient({
  uri: 'https://graphql.example.com'
})

// config is optional
const graph = new Graph(apollo, config)

Query Builder

The query builder is based on gql-query-builder.

Operations:

NameDescription
queryFor Query operations
mutationFor Mutation operations
subscriptionFor Subscriptions
rawBuild and get the raw query without performing the request. Access this value then access the above

Example query

const user = await graph.query.user(['id', 'name'], {
    where: {
        value: { id: '1' },
        type: 'UserWhereUniqueInput',
        required: true,
    },
})

const users = await graph.query.users('id name reviews{ rating }')

Example mutation

const data = { name: 'James Bomd' }
const user = await graph.mutation.createOneUser(
  ['id', 'name'],
  {
    data: {
      type: 'UserCreateInput',
      value: data,
      required: true
    }
  }
)

Nested Queries

// order
const users = await this.$graph.query.users([
    'id', 'name', 'email',
    (q) => {
        q.orders([
          'id', 'total',
          (q) => {
            q.items([
              'id', 'quantity',
            ])
          }
        ])
        q.reviews('rating', {
            limit: 100
        })
    }
])

The above performs the following query

{
  "query": "query ($limit: Int) { users  { id, name, email, orders  { id, total, items  { id, quantity } }, reviews (limit: $limit) { rating } } }",
  "variables": {
    "limit": 100
  }
}

Raw Queries

Resolve your query without performing the request.

Does not return a promise.

const raw = this.$graph.raw.query.users([
  'id',
  'name',
  (q) => {
    q.reviews('rating', { limit: 100 })
  },
])

CRUD

Accessing anything other than query, mutation, subscription, raw is regarded as a crud operation.

Assumes your backend is Prisma.js CRUD style.

// use default fields
const user = await graph.users.findUnique(where)

// or specify fields
const user = await graph.users.findUnique(where, ['id', 'name'])
// or
const user = await graph.users.findUnique(where, `
  id name
  orders{ id total }
`)

// query reviews dynamically
const reviews = await graph.reviews.findMany(['id', 'rating']);

Methods

NameTypeDescription
findUnique(where, fields, options)queryGet a unique model data
findFirst(where, fields, options)queryGet first matched model data
findMany(fields, options)queryGet all data for model
create(data, fields, options)mutationCreate a data entry for model
update(where, data, fields, options)mutationUpdate a data entry for model
upsert(where, { create, update }, fields, options)mutationUpdate or create a data entry for model
updateMany(where, data, fields, options)mutationUpdate many data entries for model
delete(where, fields, options)mutationDelete a data entry
deleteMany(where, fields, options)mutationDelete many matching data entry

The above queries/mutations are called dynamically when using this package. They must be implemented server-side.

Custom methods and overrides

import { Graph as Base } from '@moirei/agile-graphql'

class Graph extends Base{
    // override `findUnique` for `users`
    async usersFindUnique(where){
        ...
        return user
    }

    // add new methods
    async usersAdmins(where){
        ...
        return admins
    }
}

...
const graph = new Graph(apollo)

const active_admins = await graph.users.admins({ activated: true })

Use with Vue Plugin

import Vue from 'vue'
import { VuePlugin } from '@moirei/agile-graphql'

// config is optional
Vue.use(VuePlugin, config)

....
  methods: {
    async getUsers() {
      const users = await this.$graph.users.findMany()
      console.log('run', users)
      return users
    },
  },
...

Use Query Mapper (Vue)

First install Vue Apollo and the Plugin.

import { mapQueries } from '@moirei/agile-graphql'

...
data: () => ({
    where: {
        // id: 'da15d87e-ae72-11eb-8529-0242ac130003',
        email: 'augustusokoye@moirei.com',
    },
    query: ['id', 'created_at', 'name', 'email'],
}),
computed: {
    ...mapQueries({
      users: {
        default: [], // optional
        params: ['query'], // Optional. Pass local variables to query
        query: 'users.findMany',
      },
      user: {
        params: ['where', 'query'],
        query: 'users.findUnique',
      },
      reviews: 'reviews.findMany', // default fields must be specified in config
    }),
  },
...

Dependencies

Credits

License

MIT