grin-api-sdk
TypeScript icon, indicating that this package has built-in type declarations

1.9.1 • Public • Published

grin-api-sdk

Grin's typescript sdk, containing apis for our services and common enums, methods and utilities.

Installing

First you need to login to npmjs registery using our rnd account.
Get the password from the password manager / somebody in the team, then run

$ npm login

and follow the steps.
After logging in, you can install the package.

Using npm:

$ npm install @grin-rnd/grin-api-sdk

Using yarn:

yarn add @grin-rnd/grin-api-sdk

Usage examples

AppSync Communication

Here is a short example of how to set up an access to AppSync using the Graph module.
This example will work mostly on lambda functions, where the credentials exist on the environment variables.

Initialization

const { Graph } = require('@grin-rnd/grin-api-sdk')
const graphOperations = require('./graphql')

Graph.init('https://<UrlToYourAppsync>', {
  graphOperations,
  verbose: true
})

Running queries and mutations

const patient1 = await Graph.api.fetchItem('getPatient', { id: 'zdibi' })

const patient2 = await Graph.api.fetchItem('patientByUsername', { username: 'zdibi' }) // fetchItem will fetch the head of the items list

const allPatients = await Graph.api.fetchAll('listPatients')

const grinDocs = await Graph.api.search('searchDoctors', {
  filter: {
    email: {
      match: '@get-grin'
    }
  }
})
console.log(grinDocs) // { items, nextToken, total } or whatever is on the query

const docEmailOnly = await Graph.api.query('getDoctor', { id: 'zdibi' }, data => data.getDoctor.email)

const updatedDoctor = await Graph.api.mutateItem('updateDoctor', {
  id: 'zdibi',
   _version: 1
})

Dynamic operations

The GraphAPI class uses gql-query-builder library to generate dynamic queries without the need to include them in the operations json passed to the GraphAPI instance.

Access the dynamic property on your GraphAPI instance to use this feature.
Example:

Graph.api.dynamic.fetchItem({
    operation: 'doctorByEmail',
    variables: {
      email: 'ido@get-grin.com'
    },
    fields: [
      'id',
      '_version',
      {
        user: [ 'id', 'username' ]
      },
      {
        patients: [
          {
            items: ['id']
          }
        ]
      }
    ]
})

Check out the library's docs for more examples.

Graph Mocks

If your tests require complicated mocked Graph API responses, you can now use the Graph Mock module to simplify the process.

jest.mock('@grin-rnd/grin-api-sdk', () => ({
  __esModule: true,
  ...jest.requireActual('@grin-rnd/grin-api-sdk'),
  Graph: {
    api: {
      query: jest.fn().mockImplementation(
        Graph.mockBuilder()
          .mock('getPatient, 'testPatient2', { id: 'testPatient2', username: 'aaa' })
          .mock('getPatient', { id: 'genericTestPatient' }) // Fallback for getPatient
          .mock('doctorByEmail' (queryName, variables) => ({ // accepts also callbacks
              items: [
                  doctorsByUsername[variables.username]
              ]
          })
          .getMockImplementation()
      )
    }
  }
}))

Then, when your module runs getPatient, it would get the predefined value from above:

Graph.api.fetchItem('getPatient', { id: 'testPatient2' }) // will be resolved to: { id: 'testPatient2', username: 'aaa' }

The idea is that query is the base method that being invoked by all other methods such as fetchItem, fetchAll, and dynamic.
With the mock builder you define which values should be returned by query and even by specific ids.

NOTE: using this feature might change the way you mock the Graph api in general. For example, instead of replacing the entire api with a custom object, you set a spy on the methods:

beforeEach(() => {
  Graph.init('https://something.test', {
    graphOperations: {}
  })

  jest.spyOn(Graph.api.dynamic, 'mutateItem').mockImplementation((mutationName, input) => {
    return Promise.resolve({ id: input?.id })
  })

  jest
    .spyOn(Graph.api, 'query')
    .mockImplementation(
      Graph.mockBuilder().mock('listStatuss', { items: statusesData.statusesList }).getMockImplementation()
    )
})

Creating a GraphAPI instance

This is an example of how to create a GraphAPI instane, which is the class used for communication with AppSync under the hood in the Graph module.

const { GraphAPI } = require('@grin-rnd/grin-api-sdk')
const graphOperations = require('./graphql')

const graph = new GraphAPI('https://<UrlToYourAppsync>', {
  graphOperations,
  verbose: true
})

// now you can call the same methods as shown in the previous section, such as fetchItem, query, mutateItem and so on.

LambdaAPI

This module wraps common types of lambda invocations.
It's capable of sending fake http requests to express lambad functions, or simply invoke the lambda with a payload.
NOTE: fake http requests DO NOT go through the API Gateway. It's simply invoke the lambda with an event structed as a http request.

const { LambdaAPI } = require('@grin-rnd/grin-api-sdk')

const lambda = new LambdaAPI(YOUR_FUNCTION_NAME_HERE)

// This will mock a post method: the first parameter is the endpoint path, and the second is the request body.
const postResponse = await lambda.post('/path/to/somewhere', {
  hello: 'world'
})

// This will mock a get method, using the first parameter as the path. You can also add query parameters.
const getResponse = await lambda.get('/path/to/somewhere?hello=world')

// You can also create your own http request if the existing methods do not suite your needs:
const response = await lambda.mockHttpRequest(
  'PATCH',
  '/path/to/somewhere',
  { 'hello': 'world' },  // body
  { 'content-type': 'application/json' } // headers
)

// This will invoke the lambda. The object argument will be passed as the event.
const invokeResponse = await lambda.invoke({ hello: 'world' })

GrinAxios

This is just a wrapper for axios package that implements retries mechanism using exponential backoff.

Just import GrinAxios and use it as a regular axios package:

const { GrinAxios } = require('@grin-rnd/grin-api-sdk')

const res = await GrinAxios({
  method, // GET, POST, PUT, DELETE, ...
  url,
  data: req.body,
  headers: req.headers
})

LambdaUtils

recordParser

Use recordParser to parse a lambda trigger DyanmoDB record to json.

const { recordParser } require('@grin-rnd/grin-api-sdk)

const record = event.Records[0]
const newImage = recordParser(record.dynamodb.NewImage)
// use newImage as a standard json

Test with SDK Test project

  1. remove the @get-grin from the package.json of the sdk project (just for your testing)
  2. npm run make_link
  3. go to the grin api sdk test project --> npm i
  4. for every change in the sdk --> npm run make_link --> remove node_modules in test project --> npm i

Readme

Keywords

none

Package Sidebar

Install

npm i grin-api-sdk

Weekly Downloads

0

Version

1.9.1

License

ISC

Unpacked Size

420 kB

Total Files

179

Last publish

Collaborators

  • grin-rnd