All Projects → awslabs → Aws Mobile Appsync Sdk Js

awslabs / Aws Mobile Appsync Sdk Js

Licence: apache-2.0
JavaScript library files for Offline, Sync, Sigv4. includes support for React Native

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects
js
455 projects

Projects that are alternatives of or similar to Aws Mobile Appsync Sdk Js

Aws Mobile Appsync Sdk Ios
iOS SDK for AWS AppSync.
Stars: ✭ 231 (-71.34%)
Mutual labels:  graphql, appsync, graphql-subscriptions, aws, graphql-client
Graphql Rxjs
fork of Graphql which adds Observable support
Stars: ✭ 78 (-90.32%)
Mutual labels:  graphql, graphql-js, graphql-subscriptions
Moviesapp
React Native Movies App: AWS Amplify, AWS AppSync, AWS Cognito, GraphQL, DynamoDB
Stars: ✭ 78 (-90.32%)
Mutual labels:  graphql, appsync, aws
Grial
A Node.js framework for creating GraphQL API servers easily and without a lot of boilerplate.
Stars: ✭ 194 (-75.93%)
Mutual labels:  graphql, graphql-js, graphql-subscriptions
Aws Mobile Appsync Chat Starter Angular
GraphQL starter progressive web application (PWA) with Realtime and Offline functionality using AWS AppSync
Stars: ✭ 449 (-44.29%)
Mutual labels:  graphql, appsync, aws
Appsync Resolvers Example
Example project for AppSync, GraphQL, and AWS Lambda resolvers using Go.
Stars: ✭ 50 (-93.8%)
Mutual labels:  graphql, appsync, aws
Aws Mobile Appsync Events Starter React Native
GraphQL starter application with Realtime and Offline functionality using AWS AppSync
Stars: ✭ 134 (-83.37%)
Mutual labels:  graphql, appsync, aws
Aws Serverless Appsync Loyalty
Unicorn Loyalty: E-Commerce Serverless GraphQL Loyalty Sample App
Stars: ✭ 110 (-86.35%)
Mutual labels:  graphql, appsync, aws
Morpheus Graphql
Haskell GraphQL Api, Client and Tools
Stars: ✭ 285 (-64.64%)
Mutual labels:  graphql, graphql-subscriptions, graphql-client
Altair
✨⚡️ A beautiful feature-rich GraphQL Client for all platforms.
Stars: ✭ 3,827 (+374.81%)
Mutual labels:  graphql, graphql-subscriptions, graphql-client
Graphql Auto Transformer
A custom transformer of the amplify-cli. It can control accessibility of auto generated fields.
Stars: ✭ 31 (-96.15%)
Mutual labels:  graphql, appsync, aws
Aws Mobile Appsync Events Starter React
GraphQL starter application with Realtime and Offline functionality using AWS AppSync
Stars: ✭ 337 (-58.19%)
Mutual labels:  graphql, appsync, aws
Kikstart Graphql Client
🚀 Small NodeJS Wrapper around apollo-client that provides easy access to running queries, mutations and subscriptions.
Stars: ✭ 27 (-96.65%)
Mutual labels:  graphql, graphql-subscriptions, graphql-client
Serverless
This is intended to be a repo containing all of the official AWS Serverless architecture patterns built with CDK for developers to use. All patterns come in Typescript and Python with the exported CloudFormation also included.
Stars: ✭ 1,048 (+30.02%)
Mutual labels:  graphql, appsync, aws
36 Graphql Concepts
📜 36 concepts every GraphQL developer should know.
Stars: ✭ 209 (-74.07%)
Mutual labels:  graphql, graphql-subscriptions, graphql-client
Aws Lambda Graphql
Use AWS Lambda + AWS API Gateway v2 for GraphQL subscriptions over WebSocket and AWS API Gateway v1 for HTTP
Stars: ✭ 313 (-61.17%)
Mutual labels:  graphql, graphql-subscriptions, aws
Aws Appsync Community
The AWS AppSync community
Stars: ✭ 356 (-55.83%)
Mutual labels:  graphql, appsync, aws
Aws Serverless Ecommerce Platform
Serverless Ecommerce Platform is a sample implementation of a serverless backend for an e-commerce website. This sample is not meant to be used as an e-commerce platform as-is, but as an inspiration on how to build event-driven serverless microservices on AWS.
Stars: ✭ 469 (-41.81%)
Mutual labels:  appsync, aws
Example Storefront
Example Storefront is Reaction Commerce’s headless ecommerce storefront - Next.js, GraphQL, React. Built using Apollo Client and the commerce-focused React UI components provided in the Storefront Component Library (reactioncommerce/reaction-component-library). It connects with Reaction backend with the GraphQL API.
Stars: ✭ 471 (-41.56%)
Mutual labels:  graphql, graphql-client
Webiny Js
Enterprise open-source serverless CMS. Includes a headless CMS, page builder, form builder and file manager. Easy to customize and expand. Deploys to AWS.
Stars: ✭ 4,869 (+504.09%)
Mutual labels:  graphql, aws

AWS AppSync

AWS AppSync JavaScript SDK

This SDK can be used with the Apollo JavaScript client found here. Please log questions for this client SDK in this repo and questions for the AppSync service in the official AWS AppSync forum.

lerna npm

package version
aws-appsync npm
aws-appsync-react npm

Installation

npm

npm install --save aws-appsync

yarn

yarn add aws-appsync

AWS AppSync Compatibility

For version <= 2.x.x, the selection set for the subscription will be the mutation selection set. For version >= 3.x.x, the subscription selection set will be the intersection between mutation and subscription selection sets. More info here

React Native Compatibility

When using this library with React Native, you need to ensure you are using the correct version of the library based on your version of React Native. Take a look at the table below to determine what version to use.

aws-appsync version Required React Native Version
2.x.x >= 0.60
1.x.x <= 0.59

If you are using React Native 0.60 and above, you also need to install @react-native-community/netinfo and @react-native-community/async-storage:

npm install --save @react-native-community/[email protected] @react-native-community/async-storage

or

yarn add @react-native-community/[email protected] @react-native-community/async-storage

If you are using React Native 0.60+ for iOS, run the following command as an additional step:

npx pod-install

Usage

Please visit the documentation with the Amplify Framework for detailed instructions.

React / React Native

Vue
Angular
Creating a new AWS AppSync API
License

React / React Native

For more documentation on graphql operations performed by React Apollo click here.

Creating a client

import AWSAppSyncClient from 'aws-appsync'
import AppSyncConfig from './aws-exports'
import { ApolloProvider } from 'react-apollo'
import { Rehydrated } from 'aws-appsync-react' // this needs to also be installed when working with React

import App from './App'

const client = new AWSAppSyncClient({
  url: AppSyncConfig.graphqlEndpoint,
  region: AppSyncConfig.region,
  auth: {
    type: AppSyncConfig.authenticationType,
    apiKey: AppSyncConfig.apiKey,
    // jwtToken: async () => token, // Required when you use Cognito UserPools OR OpenID Connect. token object is obtained previously
  }
})

const WithProvider = () => (
  <ApolloProvider client={client}>
    <Rehydrated>
      <App />
    </Rehydrated>
  </ApolloProvider>
)

export default WithProvider

Queries

import gql from 'graphql-tag'
import { graphql } from 'react-apollo'

const listPosts = gql`
  query listPosts {
    listPosts {
      items {
        id
        name
      }
    }
  }
`
class App extends Component {
  render() {
    return (
      <div>
        {
          this.props.posts.map((post, index) => (
            <h2 key={index}>{post.name}</h2>
          ))
        }
      </div>
    )
  }
}

export default graphql(listPosts, {
  options: {
    fetchPolicy: 'cache-and-network'
  },
  props: props => ({
    posts: props.data.listPosts ? props.data.listPosts.items : []
  })
})(App)

Mutations & optimistic UI (with graphqlMutation helper)

import gql from 'graphql-tag'
import { graphql, compose } from 'react-apollo'
import { graphqlMutation } from 'aws-appsync-react'

const CreatePost = gql`
  mutation createPost($name: String!) {
    createPost(input: {
      name: $name
    }) {
      name
    }
  }
`

class App extends Component {
  state = { name: '' }
  onChange = (e) => { this.setState({ name: e.target.value }) }
  addTodo = () => this.props.createPost({ name: this.state.name })
  render() {
    return (
      <div>
        <input onChange={this.onChange} placeholder='Todo name' />
        <button onClick={this.addTodo}>Add Todo</button>
        {
          this.props.posts.map((post, index) => (
            <h2 key={index}>{post.name}</h2>
          ))
        }
      </div>
    )
  }
}

export default compose(
  graphql(listPosts, {
    options: {
      fetchPolicy: 'cache-and-network'
    },
    props: props => ({
      posts: props.data.listPosts ? props.data.listPosts.items : []
    })
  }),
  graphqlMutation(CreatePost, listPosts, 'Post')
)(App)

Mutations & optimistic UI (without graphqlMutation helper)

import gql from 'graphql-tag'
import uuidV4 from 'uuid/v4'
import { graphql, compose } from 'react-apollo'

const CreatePost = gql`
  mutation createPost($name: String!) {
    createPost(input: {
      name: $name
    }) {
      name
    }
  }
`

class App extends Component {
  state = { name: '' }
  onChange = (e) => { this.setState({ name: e.target.value }) }
  addTodo = () => this.props.onAdd({ id: uuidV4(), name: this.state.name })
  render() {
    return (
      <div>
        <input onChange={this.onChange} placeholder='Todo name' />
        <button onClick={this.addTodo}>Add Todo</button>
        {
          this.props.posts.map((post, index) => (
            <h2 key={index}>{post.name}</h2>
          ))
        }
      </div>
    )
  }
}

export default compose(
  graphql(listPosts, {
    options: {
      fetchPolicy: 'cache-and-network'
    },
    props: props => ({
      posts: props.data.listPosts ? props.data.listPosts.items : []
    })
  }),
  graphql(CreatePost, {
    options: {
      update: (dataProxy, { data: { createPost } }) => {
        const query = listPosts
        const data = dataProxy.readQuery({ query })
        data.listPosts.items.push(createPost)
        dataProxy.writeQuery({ query, data })
      }
    },
    props: (props) => ({
      onAdd: (post) => {
        props.mutate({
          variables: post,
          optimisticResponse: () => ({
            createPost: { ...post, __typename: 'Post' }
          }),
        })
      }
    }),
  })
)(App)

Subscriptions (with buildSubscription helper)

import gql from 'graphql-tag'
import { graphql } from 'react-apollo'
import { buildSubscription } from 'aws-appsync'

const listPosts = gql`
  query listPosts {
    listPosts {
      items {
        id
        name
      }
    }
  }
`

const PostSubscription = gql`
  subscription postSubscription {
    onCreatePost {
      id
      name
    }
  } 
`

class App extends React.Component {
  componentDidMount() {
    this.props.data.subscribeToMore(
      buildSubscription(PostSubscription, listPosts)
    )
  }
  render() {
    return (
      <div>
        {
          this.props.posts.map((post, index) => (
            <h2 key={index}>{post.name}</h2>
          ))
        }
      </div>
    )
  }
}

export default graphql(listPosts, {
  options: {
    fetchPolicy: 'cache-and-network'
  },
  props: props => ({
    posts: props.data.listPosts ? props.data.listPosts.items : [],
    data: props.data
  })
})(App)

Subscriptions (without buildSubscription helper)

import gql from 'graphql-tag'
import { graphql } from 'react-apollo'

const listPosts = gql`
  query listPosts {
    listPosts {
      items {
        id
        name
      }
    }
  }
`

const PostSubscription = gql`
  subscription postSubscription {
    onCreatePost {
      id
      name
    }
  } 
`

class App extends React.Component {
  componentDidMount() {
    this.props.subscribeToNewPosts()
  }
  render() {
    return (
      <div>
        {
          this.props.posts.map((post, index) => (
            <h2 key={index}>{post.name}</h2>
          ))
        }
      </div>
    )
  }
}

export default graphql(listPosts, {
  options: {
    fetchPolicy: 'cache-and-network'
  },
  props: props => ({
    posts: props.data.listPosts ? props.data.listPosts.items : [],
    subscribeToNewPosts: params => {
      props.data.subscribeToMore({
        document: PostSubscription,
        updateQuery: (prev, { subscriptionData: { data : { onCreatePost } } }) => ({
          ...prev,
          listPosts: { __typename: 'PostConnection', items: [onCreatePost, ...prev.listPosts.items.filter(post => post.id !== onCreatePost.id)] }
        })
      })
    },
  })
})(App)

Offline configuration

When using the AWS AppSync SDK offline capabilities (e.g. disableOffline: false), you can provide configurations for the following:

  • Error handling
  • Custom storage engine

Error handling

If a mutation is done while the app was offline, it gets persisted to the platform storage engine. When coming back online, it is sent to the GraphQL endpoint. When a response is returned by the API, the SDK will notify you of the success or error using the callback provided in the offlineConfig param as follows:

const client = new AWSAppSyncClient({
  url: appSyncConfig.graphqlEndpoint,
  region: appSyncConfig.region,
  auth: {
    type: appSyncConfig.authenticationType,
    apiKey: appSyncConfig.apiKey,
  },
  offlineConfig: {
    callback: (err, succ) => {
      if(err) {
        const { mutation, variables } = err;

        console.warn(`ERROR for ${mutation}`, err);
      } else {
        const { mutation, variables } = succ;

        console.info(`SUCCESS for ${mutation}`, succ);
      }
    },
  },
});

Custom storage engine

You can use any custom storage engine from the redux-persist supported engines list.

Configuration is done as follows: (localForage shown in the example)

import * as localForage from "localforage";

const client = new AWSAppSyncClient({
  url: appSyncConfig.graphqlEndpoint,
  region: appSyncConfig.region,
  auth: {
    type: appSyncConfig.authenticationType,
    apiKey: appSyncConfig.apiKey,
  },
  offlineConfig: {
    storage: localForage,
  },
});

Offline helpers

For detailed documentation about the offline helpers, look at the API Definition.

Vue

For more documentation on Vue Apollo click here.

main.js

import Vue from 'vue'
import App from './App'
import router from './router'

import AWSAppSyncClient from 'aws-appsync'
import VueApollo from 'vue-apollo'
import AppSyncConfig from './aws-exports'

const config = {
  url: AppSyncConfig.graphqlEndpoint,
  region: AppSyncConfig.region,
  auth: {
    type: AppSyncConfig.authType,
    apiKey: AppSyncConfig.apiKey,
  }
}
const options = {
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network',
    }
  }
}

const client = new AWSAppSyncClient(config, options)

const appsyncProvider = new VueApollo({
  defaultClient: client
})

Vue.use(VueApollo)

new Vue({
  el: '#app',
  router,
  components: { App },
  provide: appsyncProvider.provide(),
  template: '<App/>'
})

App.vue

<template>
  <div id="app" v-if="hydrated">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App',
  data: () => ({ hydrated: false }),
  async mounted() {
    await this.$apollo.provider.defaultClient.hydrated()
    this.hydrated = true
  },
}
</script>

connected component

import gql from 'graphql-tag'
import uuidV4 from 'uuid/v4'

const CreateTask = gql`
  mutation createTask($id: ID!, $name: String!, $completed: Boolean!) {
    createTask(
      input: {
        id: $id, name: $name, completed: $completed
      }
    ) {
      id
      name
      completed
    }
  }
`

const DeleteTask = gql`
  mutation deleteTask($id: ID!) {
    deleteTask(
      input: {
        id: $id
      }
    ) {
      id
    }
  }
`

const ListTasks = gql`
  query listTasks {
    listTasks {
      items {
        id
        name
        completed
      }
    }
  }
`

const UpdateTask = gql`
  mutation updateTask($id: ID!, $name: String!, $completed: Boolean!) {
    updateTask(
      input: {
        id: $id
        name: $name
        completed: $completed
      }
    ) {
      id
      name
      completed
    }
  }
`

// In your component (Examples of queries & mutations)
export default {
  name: 'Tasks',
  methods: {
    toggleComplete(task) {
      const updatedTask = {
        ...task,
        completed: !task.completed
      }
      this.$apollo.mutate({
        mutation: UpdateTask,
        variables: updatedTask,
        update: (store, { data: { updateTask } }) => {
          const data = store.readQuery({ query: ListTasks })
          const index = data.listTasks.items.findIndex(item => item.id === updateTask.id)
          data.listTasks.items[index] = updateTask
          store.writeQuery({ query: ListTasks, data })
        },
        optimisticResponse: {
          __typename: 'Mutation',
          updateTask: {
            __typename: 'Task',
            ...updatedTask
          }
        },
      })
      .then(data => console.log(data))
      .catch(error => console.error(error))
    },
    deleteTask(task) {
      this.$apollo.mutate({
        mutation: DeleteTask,
        variables: {
          id: task.id
        },
        update: (store, { data: { deleteTask } }) => {
          const data = store.readQuery({ query: ListTasks })
          data.listTasks.items = data.listTasks.items.filter(task => task.id !== deleteTask.id)
          store.writeQuery({ query: ListTasks, data })
        },
        optimisticResponse: {
          __typename: 'Mutation',
          deleteTask: {
            __typename: 'Task',
            ...task
          }
        },
      })
      .then(data => console.log(data))
      .catch(error => console.error(error))
    },
    createTask() {
      const taskname = this.taskname
      if ((taskname) === '') {
        alert('please create a task')
        return
      }
      this.taskname = ''
      const id = uuidV4()
      const task = {
        name: taskname,
        id,
        completed: false
      }
      this.$apollo.mutate({
        mutation: CreateTask,
        variables: task,
        update: (store, { data: { createTask } }) => {
          const data = store.readQuery({ query: ListTasks })
          data.listTasks.items.push(createTask)
          store.writeQuery({ query: ListTasks, data })
        },
        optimisticResponse: {
          __typename: 'Mutation',
          createTask: {
            __typename: 'Task',
            ...task
          }
        },
      })
      .then(data => console.log(data))
      .catch(error => console.error("error!!!: ", error))
    },
  },
  data () {
    return {
      taskname: '',
      tasks: []
    }
  },
  apollo: {
    tasks: {
      query: () => ListTasks,
      update: data => data.listTasks.items
    }
  },
}

Using Authorization and Subscription links with Apollo Client (No offline support)

For versions of the Apollo client newer than 2.4.6 you can use custom links for Authorization and Subscriptions. Offline support is not available for these newer versions. The packages available are aws-appsync-auth-link and aws-appsync-subscription-link. Below is a sample code snippet that shows how to use it.

import { createAuthLink } from 'aws-appsync-auth-link';
import { createSubscriptionHandshakeLink } from 'aws-appsync-subscription-link';

import { ApolloLink } from 'apollo-link';
import { createHttpLink } from 'apollo-link-http';
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';

import appSyncConfig from "./aws-exports";

const url = appSyncConfig.aws_appsync_graphqlEndpoint;
const region = appSyncConfig.aws_appsync_region;
const auth = {
  type: appSyncConfig.aws_appsync_authenticationType,
  apiKey: appSyncConfig.aws_appsync_apiKey,
};

const httpLink = createHttpLink({ uri: url });

const link = ApolloLink.from([
  createAuthLink({ url, region, auth }),
  createSubscriptionHandshakeLink(url, httpLink)
]);

const client = new ApolloClient({
  link,
  cache: new InMemoryCache()
})

For version 3+, the createSubscriptionHandshakeLink can also be configured the same as createAuthLink. This will have the same behavior as mentioned here for version 3+ Please see the example below:

// Previous code snippets above work the same.
// ...
const link = ApolloLink.from([
  createAuthLink({ url, region, auth }),
  createSubscriptionHandshakeLink({ url, region, auth })
]);
// ...

Creating an AppSync Project

To create a new AppSync project, go to https://aws.amazon.com/appsync/.

License

This library is licensed under the Apache License 2.0.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].