Code Monkey home page Code Monkey logo

gatsby-source-apiserver's Introduction

gatsby-source-apiserver

A gatsby source plugin for pulling in third party api data.

Features

  • Pulls data from configured api url
  • Uses custom name to allow for multiple instances of plugin
  • Option to download the json data to a configurable path
  • Option to only download the json data, and skip inserting it into GraphQL
  • Supports simple authentication through axios

Install

npm install --save gatsby-source-apiserver

Migrate for Gatsby-v2 release:

Please checkout version 2.0.0 or next

npm install --save gatsby-source-apiserver@next

Change logs

  • 2.1.6:
    • Support pagination for recurring fetch big amount of data from server. See calculateNextPage in example configuration
  • 2.1.5:
    • Allow caching for slow API servers. See example configuration
    // enable disk caching
    allowCache: false,
    // if allowCache is true, then the cache will be purged after the
    // specified amount of time
    maxCacheDurationSeconds: 60 * 60 * 24,
    
  • 2.1.3:
    • Add ability to refresh node in development by ENABLE_GATSBY_REFRESH_ENDPOINT env. See more
  • 2.1.2:
    • Upgrade axios to 0.19.0 to fix DoS vulnerability
    • Fix BoundActionCreators depracation warning
  • 2.1.1:
    • Support multiple entities for multiple api servers, pls take a look at attribute entitiesArray
    • Add request params
    • Support Auth0
  • 2.0.0: Support gatsby-v2

How to use

// Place configuration options in your gatsby-config.js

plugins: [
  {
    resolve: "gatsby-source-apiserver",
    options: {
      // Type prefix of entities from server
      typePrefix: "internal__",

      // The url, this should be the endpoint you are attempting to pull data from
      url: `http://yourapi.com/api/v1/posts`,

      method: "post",

      headers: {
        "Content-Type": "application/json"
      },

      // Request body
      data: {},

      // Name of the data to be downloaded.  Will show in graphQL or be saved to a file
      // using this name. i.e. posts.json
      name: `posts`,

      // Nested level of entities in response object, example: `data.posts`
      entityLevel: `data.posts`,

      // Define schemaType to normalize blank values
      // example:
      // const postType = {
      //   id: 1,
      //   name: 'String',
      //   published: true,
      //   object: {a: 1, b: '2', c: false},
      //   array: [{a: 1, b: '2', c: false}]
      // }
      schemaType: postType,

      // Request parameters
      // Only available from version 2.1.0
      params: {
        per_page: 1
      },

      // Simple authentication, optional
      auth: {
        username: "myusername",
        password: "supersecretpassword1234"
      },
      // enable disk caching
      allowCache: false,
      // if allowCache is true, then the cache will be purged after the
      // specified amount of time
      maxCacheDurationSeconds: 60 * 60 * 24,

      // Advanced authentication for Auth0
      // Only available from version 2.1.0
      auth0Config: {
        method: "POST",
        url: "https://MyAuth0Domain/oauth/token",
        headers: { "content-type": "application/json" },
        data: {
          grant_type: "password",
          username: "myusername",
          password: "PassAWordHere",
          audience: "Auth0APIAudience",
          scope: "openid",
          client_id: "AUTH0_CLIENT_ID",
          client_secret: "AUTH0_SECRET"
        },
        json: true
      },

      // Optional payload key name if your api returns your payload in a different key
      // Default will use the full response from the http request of the url
      payloadKey: `body`,

      // Optionally save the JSON data to a file locally
      // Default is false
      localSave: false,

      //  Required folder path where the data should be saved if using localSave option
      //  This folder must already exist
      path: `${__dirname}/src/data/auth/`,

      // Optionally include some output when building
      // Default is false
      verboseOutput: true, // For debugging purposes

      // Optionally skip creating nodes in graphQL.  Use this if you only want
      // The data to be saved locally
      // Default is false
      skipCreateNode: false, // skip import to graphQL, only use if localSave is all you want

      // Optionally re-source data when it changes and
      // `gatsby develop` is running.
      // Requires `ENABLE_GATSBY_REFRESH_ENDPOINT=true`.
      // See https://www.gatsbyjs.org/docs/environment-variables/#reserved-environment-variables
      // Default is false
      enableDevRefresh: true,

      // Optionally override key used to re-source data
      // when `gatsby develop` is running.
      // Requires `enableDevRefresh: true`.
      // See setting directly above this one.
      // See also https://github.com/gatsbyjs/gatsby/issues/14653
      // Default is `id`
      refreshId: `id`,

      // Pass an array containing any number of the entity configuration properties (except verbose, auth0Config),
      // any not specified are defaulted to the general properties that are specified
      // Only available from version 2.1.0
      entitiesArray: [
        {
          url: `http://yourapi.com/api/v1/posts`,
          method: "post",
          headers: {
            "Content-Type": "application/json"
          },
          name: `posts`,
          // optional paging
          calculateNextPage: (curUrl, response, context) => {
            let page = 2
            if (context.page) {
              page = context.page + 1
            }
            context.page = page
            const url = `http://yourapi.com/api/v1/posts?page=${page}`
            const hasNext = response.data.length >= 100
            return { url, hasNext }
          }   
        }
      ]
    }
  }
];

How to query

Data will be available at the following points in GraphQL.

all<TypePrefix><Name> or <TypePrefix><Name> where TypePrefix and Name is replaced by the name entered in the configuration options.

Dummy Node

This plugin will automatically add a dummy node to initialize Gatsby Graphql Schema, in order to avoid GraphQL errors when some fields are missing.

The dummy node will have id: 'dummy' and you will probably want to exclude it from createPage():

<ul>
  {data.allPosts.edges
    .filter(({ node }) => node.id !== "dummy")
    .map(({ node }, index) => (
      <li key={index}>{node.name}</li>
    ))}
</ul>

or filter it out from your GraphQL query:

query {
    internalAllPosts(filter: {id: {ne: "dummy"}}) {
        // ...
    }
}

Note: make sure you pass option schemaType to make dummy node works.

Conflicting keys

Some of the returned keys may be transformed if they conflict with restricted keys used for GraphQL such as the following ['id', 'children', 'parent', 'fields', 'internal']

These conflicting keys will now show up as alternative_id

gatsby-source-apiserver's People

Contributors

abonventre avatar dependabot[bot] avatar garytube avatar gouravsood avatar lukeschlangen avatar machour avatar michlipski avatar moshie avatar rburgstaller avatar thinhle-agilityio avatar thisishuey avatar zackphilipps 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

gatsby-source-apiserver's Issues

TypeError: Cannot read property 'data' of undefined

Encountering the following error with Gatsby v2

error Plugin gatsby-source-apiserver returned an error


  TypeError: Cannot read property 'data' of undefined

  - fetch.js:31
    [frontend]/[gatsby-source-apiserver]/fetch.js:31:78

  - Generator.next

  - fetch.js:64 step
    [frontend]/[gatsby-source-apiserver]/fetch.js:64:191

  - fetch.js:64
    [frontend]/[gatsby-source-apiserver]/fetch.js:64:437

  - debuggability.js:303 Promise._execute
    [frontend]/[bluebird]/js/release/debuggability.js:303:9

  - promise.js:483 Promise._resolveFromExecutor
    [frontend]/[bluebird]/js/release/promise.js:483:18

  - promise.js:79 new Promise
    [frontend]/[bluebird]/js/release/promise.js:79:10

  - fetch.js:64
    [frontend]/[gatsby-source-apiserver]/fetch.js:64:99

  - fetch.js:60 fetch
    [frontend]/[gatsby-source-apiserver]/fetch.js:60:17

  - gatsby-node.js:45 Object.<anonymous>
    [frontend]/[gatsby-source-apiserver]/gatsby-node.js:45:26

  - Generator.next

  - gatsby-node.js:1 step
    [frontend]/[gatsby-source-apiserver]/gatsby-node.js:1:253

  - gatsby-node.js:1
    [frontend]/[gatsby-source-apiserver]/gatsby-node.js:1:499

  - debuggability.js:303 Promise._execute
    [frontend]/[bluebird]/js/release/debuggability.js:303:9

  - promise.js:483 Promise._resolveFromExecutor
    [frontend]/[bluebird]/js/release/promise.js:483:18

  - promise.js:79 new Promise
    [frontend]/[bluebird]/js/release/promise.js:79:10

Here's my gatsby-config.js:

{
    resolve: "gatsby-source-apiserver",
    options: {
        url: config.GREENHOUSE_JOBS_API,
        name: "greenhouse",
    },
}

I've also tried this with no avail:

{
    resolve: "gatsby-source-apiserver",
    options: {
        url: config.GREENHOUSE_JOBS_API,
        name: "greenhouse",
        auth: null,
        data: {}
    },
}

Minimal example

Can you please provide a minimal example of the options object? I know this is simple but I'm having hard time figuring this out.

Also would 2.x.x version of this plugin work with gatsby v1?

Thank you!!

Just wanted to say thanks for upgrading this plugin to be used with Gatsby v2 ... you just saved us a lot of work!!

[error] Cannot read property 'map' of undefined

I get en error during "gatsby build". It's hard for debugging because i got below error only when i deal with 10000+ records from api (with the same API records limited to 5000 i do not get en error - probalby there is some problem with some record between 5000 and 10000). How can i debug it?

I use lates version of "gatsby-source-apiserver"

ERROR #11321 PLUGIN

"gatsby-source-apiserver" threw an error while running the sourceNodes lifecycle:

Cannot read property 'map' of undefined

TypeError: Cannot read property 'map' of undefined

  • normalize.js:138 standardizeKeys
    [system_last]/[gatsby-source-apiserver]/normalize.js:138:46

  • normalize.js:29 Object.exports.createNodesFromEntities
    [system_last]/[gatsby-source-apiserver]/normalize.js:29:14

  • gatsby-node.js:115
    [system_last]/[gatsby-source-apiserver]/gatsby-node.js:115:19

  • Generator.next

  • gatsby-node.js:1 step
    [system_last]/[gatsby-source-apiserver]/gatsby-node.js:1:253

  • gatsby-node.js:1
    [system_last]/[gatsby-source-apiserver]/gatsby-node.js:1:423

  • runMicrotasks

  • task_queues.js:93 processTicksAndRejections
    internal/process/task_queues.js:93:5

Recover from API server error

Is there a recommend way to recover from a failing API server?

My server is currently throwing error 400 Bad Request.
I have a JSON file from the last request (using localSave) that I could use as a fallback.

Or, at least, a way to catch the error and act on it in gatsby-node.

verboseOutput config option does not appear to work

When I set the verboseOuput option to true, it doesn't seem to output the verbose log statements (reporter.verbose) that are in the fetch.js file. Specifically, I was looking for proof that the call to my api was made. I also tried with the --verbose option. Not a big issue, but thought I'd report it.

TypeError: Cannot read property 'data' of undefined

Summary

Error when running gatsby develop with a fresh new gatsby project.

 ERROR #11321  PLUGIN

"gatsby-source-apiserver" threw an error while running the sourceNodes lifecycle:

Cannot read property 'data' of undefined



  TypeError: Cannot read property 'data' of undefined
  
  - fetch.js:91 
    [gatsby-incremental-builds]/[gatsby-source-apiserver]/fetch.js:91:80
  
  - Generator.throw
  
  - fetch.js:127 step
    [gatsby-incremental-builds]/[gatsby-source-apiserver]/fetch.js:127:191
  
  - fetch.js:127 
    [gatsby-incremental-builds]/[gatsby-source-apiserver]/fetch.js:127:402
  
  - next_tick.js:68 process._tickCallback
    internal/process/next_tick.js:68:7
  
  - From previous event:
  
  - api-runner-node.js:261 runAPI
    [gatsby-incremental-builds]/[gatsby]/dist/utils/api-runner-node.js:261:22
  
  - api-runner-node.js:378 resolve
    [gatsby-incremental-builds]/[gatsby]/dist/utils/api-runner-node.js:378:15
  
  - From previous event:
  
  - api-runner-node.js:377 Promise.mapSeries.plugin
    [gatsby-incremental-builds]/[gatsby]/dist/utils/api-runner-node.js:377:12
  
  - From previous event:
  
  - api-runner-node.js:371 resolve
    [gatsby-incremental-builds]/[gatsby]/dist/utils/api-runner-node.js:371:11
  
  - From previous event:
  
  - api-runner-node.js:278 module.exports
    [gatsby-incremental-builds]/[gatsby]/dist/utils/api-runner-node.js:278:12
  
  - source-nodes.js:88 _default
    [gatsby-incremental-builds]/[gatsby]/dist/utils/source-nodes.js:88:36
  
  - source-nodes.js:29 sourceNodes
    [gatsby-incremental-builds]/[gatsby]/dist/services/source-nodes.js:29:34
  
  - index.js:29 bootstrap
    [gatsby-incremental-builds]/[gatsby]/dist/bootstrap/index.js:29:35
  

warn The gatsby-source-apiserver plugin has generated no Gatsby nodes. Do you need it?

Steps to reproduce

gatsby new test-project
npm i -S -E gatsby-source-apiserver
// update gatsby-config.js to match the one below
gatsby develop

Relevant Info

gatsby-config.js

module.exports = {
  siteMetadata: {
    title: `...`,
    description: `...`,
    author: `@gatsbyjs`,
  },
  plugins: [
    {
      resolve: "gatsby-source-apiserver",
      options: {
        typePrefix: "internal__",
        url: `https://jsonplaceholder.typicode.com/todos/1`,
        name: `todods`,
      },
    },
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
  ],
}

package.json

{
  "name": "gatsby-starter-default",
  "private": true,
  "description": "A simple starter to get up and developing quickly with Gatsby",
  "version": "0.1.0",
  "author": "Kyle Mathews <[email protected]>",
  "dependencies": {
    "gatsby": "^2.23.12",
    "gatsby-image": "^2.4.9",
    "gatsby-plugin-manifest": "^2.4.14",
    "gatsby-plugin-offline": "^3.2.13",
    "gatsby-plugin-react-helmet": "^3.3.6",
    "gatsby-plugin-sharp": "^2.6.14",
    "gatsby-source-apiserver": "2.1.6",
    "gatsby-source-filesystem": "^2.3.14",
    "gatsby-transformer-sharp": "^2.5.7",
    "prop-types": "^15.7.2",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-helmet": "^6.1.0"
  },
  "devDependencies": {
    "prettier": "2.0.5"
  },
  "keywords": [
    "gatsby"
  ],
  "license": "0BSD",
  "scripts": {
    "build": "gatsby build",
    "develop": "gatsby develop",
    "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
    "start": "npm run develop",
    "serve": "gatsby serve",
    "clean": "gatsby clean",
    "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/gatsbyjs/gatsby-starter-default"
  },
  "bugs": {
    "url": "https://github.com/gatsbyjs/gatsby/issues"
  }
}

Conflict with `gatsby-transformer-json`

Hi, I get an error when my project depends on both this plugin and gatsby-transformer-json. The error is thrown during the build process:

"gatsby-transformer-json" threw an error while running the onCreateNode lifecycle:

Could not find function loadNodeContent for plugin gatsby-source-apiserver

While development mode still works, it fails during the production build and never run till the end.

I reproduced this error in https://codesandbox.io/s/sad-wilbur-xwugm - just restart the sandbox to see errors in the terminal.

Thank you for any ideas!

Cannot query data

For some reason, I cannot query the data. The json file is saved under src/data/posts.json. Howeverwhen I use GraphiQL to create a query, it doesnt work. Nothings comes up when I use

{
internal___post {
}
}

what am I doing wrong?

Bug: `typePrefix` should default to ''

If typePrefix is omitted, it’ll be stringified to undefined. E.g., if my config states:

  name: 'products',

then this plugin will name it undefinedProducts. Perhaps the default should be an empty string to account for this? I’m happy to open a PR if required.

Oauth2 Permission Denied

Hi

I was hoping someone might be able to point me in the right direction in implementing the auth0config for OAuth2. I'm getting "401 not authorised" every time. Here's my code (client_secret redacted):

module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-apiserver",
      options: {
        typePrefix: 'internal__',
        url: `https://api.ochre.io/v1/stores/`,
        method: 'get',
        headers: {
          "Content-Type": "application/json"
        },
        name: `posts`,
        auth0Config: {
          method: "GET",
          url: "https://auth.ochre.io/oauth2/token",
          headers: {
            "content-type": "application/json"
          },
          data: {
            grant_type: "client_credentials",
            scope: "CMS RETAIL MUSIC",
            client_id: "9939492",
            client_secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
          },
          json: true
        },
        params: {
          results: 100
        },
        verboseOutput: true,
    }
    },
  ],
}

Has anyone used gatsby-source-apiserve for Oauth2, is it possible?

Pager creates multiple nested arrays

I can't seem to get the pager to work correctly I get the following error

TypeError: Cannot read property 'map' of undefined

Adding console log here

        if (entityLevel) {
          console.log(entities)
          entities = objectRef(entities, entityLevel);
        }

outputs the following, so it looks like rather than rows being added into a single array it creates multiple row arrays and so the objectRef function fails and just sets the entities array to null.

[
    {
      rows: [
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object]
      ],
      pager: {
        current_page: 0,
        total_items: '720',
        total_pages: 72,
        items_per_page: 10
      }
    }
    {
      rows: [
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object],
        [Object], [Object]
      ],
      pager: {
        current_page: 1,
        total_items: '720',
        total_pages: 72,
        items_per_page: 10
      }
    },
]

My gatsby config is as follows

{
  resolve: "gatsby-source-apiserver",
  options: {
    typePrefix: "internal__",
    data: {},
    auth: {
      username: process.env.BASIC_AUTH_USERNAME,
      password: process.env.BASIC_AUTH_PASSWORD
    },
    allowCache: false,
    localSave: false,
    verboseOutput: true, // For debugging purposes
    skipCreateNode: false,
    entitiesArray: [
      {
        url: process.env.URL + `cat/` + process.env.CATALOGUE_ID +'/lines',
        method: "get",
        headers: {
          "Content-Type": "application/json"
        },
        schemaType: lineType,
        entityLevel: `rows`,
        name: `lines`,
        // optional paging
        calculateNextPage: (curUrl, response, context) => {
          let page = 0
          if (context.page !== undefined) {
            page = context.page + 1
          }
          context.page = page
          const url = process.env.URL + `cat/` + process.env.CATALOGUE_ID + `/lines?page=${page}`
          const hasNext = (response.data.pager.current_page + 1) < (response.data.pager.total_pages -1)
          return { url, hasNext }
        }   
      },  
    ]
  }
},

TypeError: Cannot read property 'data' of undefined

I was having a lot of issues with this plugin and decided to start debugging the source.

My error:

 ERROR #11321  PLUGIN
"gatsby-source-apiserver" threw an error while running the sourceNodes lifecycle:
Cannot read property 'data' of undefined
TypeError: Cannot read property 'data' of undefined

If I change line 27 in fetch.js:
completeResult.push(...routeData);
to
completeResult.push(routeData);

It works as expected.

Graph does not see some fields and does not generate the scheme correctly

Hello, I have categories in the project. I need to get all fields from an endpoint in graphql. But the schema does not generate correctly, the children field at my endpoint always returns an empty array when I make a request

data from server

[
    {
        "id": 1,
        "nameI18nId": 238,
        "slug": "test",
        "name": {
            "id": 238,
            "en": "Test",
            "ru": "Тест"
        },
        "children": [
            {
                "id": 10,
                "nameI18nId": 548,
                "slug": "product-category-name",
                "name": {
                    "id": 548,
                    "en": "product category name",
                    "ru": "категория продукта"
                },
        ]
]

gatsby config file

{
      resolve: `gatsby-source-apiserver`,
      options: {
        url: process.env.PAYFORM_API_URL,
        method: 'get',
        typePrefix: 'internal__',
        name: 'payform',
        headers: {
          'Content-Type': 'application/json',
        },
        verboseOutput: true,
        entitiesArray: [
          {
            url: `${process.env.PAYFORM_API_URL}product`,
            method: 'get',
            headers: {
              'Content-Type': 'application/json',
            },
            typePrefix: 'internal__',
            name: `products`,
          },
          {
            url: `${process.env.PAYFORM_API_URL}product-category`,
            method: 'get',
            headers: {
              'Content-Type': 'application/json',
            },
            typePrefix: 'internal__',
            name: `categories`,
          },
        ],
      },

How can I get data in the children field? If you have any ideas, please let me know how I can fix this. thanks

a vulnerability CVE-2020-28469 is introduced in gatsby-source-apiserver

Hi, a vulnerability CVE-2020-28469 is introduced in gatsby-source-apiserver via:
[email protected][email protected][email protected][email protected]

babel-cli is a legacy package. It has not been maintained for about 4 years, and is not likely to be updated.
Is it possible to migrate babel-cli to other package to remediate this vulnerability?

I noticed several migration records for babel-cli in other js repos, such as

  1. in AlNuN/learn-webpack, Migrate from babel-cli to webpack + babel-core via commit
  2. in tsub/serverless-plugin-subscription-filter, Migrate babel-cli to @babel/cli via commit

Are there any efforts planned that would remediate this vulnerability or migrate babel-cli?

Thanks
; )

Configuration for plain response object

Hey,

first thank you for that source plugin!

Having some trouble setting up the configuration for my use case. I use npms.io to fetch multiple packages at once. The API responds with following structure in Postman when trying to get react and lodash packages:

{
  "react": Object,
  "lodash": Object,
}

But in GraphQL, the nodes are as follows:

{
  "data": {
    "allNpmsPackages": {
      "edges": [
        {
          "node": {
            "react": {
              ...
            },
            "lodash": {
              ...
            }
          }
        },
        {
          "node": {
            "react": null,
            "lodash": null
          }
        }
      ]
    }
  }
}

Each package should have its own node. I tried using an empty entityLevel and setting it to data only, but the latter returns an error.

gatsby-config.js

    {
      resolve: `gatsby-source-apiserver`,
      options: {
        typePrefix: `npms__`,
        url: `https://api.npms.io/v2/package/mget`,
        method: `post`,
        headers: {
          Accept: `application/json`,
          'Content-Type': `application/json`,
        },
        data: [`react`, `lodash`],
        name: `Packages`,
        entityLevel: ``,
        verboseOutput: true,
      },
    },

Could you tell me what to configure in this scenario?

Option to refetch data and create updated nodes

Hi!
First of all, thank you for this plugin, it's really great.
I was wondering, is there a way to make another call to the API periodically with setTimeout or by calling it with another function within the deployed gatsby site?

I am using it to fetch data from a Shopify orders API.
As the data updates every time someone makes an order, I need to be able to fetch fresh data every time that happens or just have it make a call every couple of minutes.

Had no luck finding a workaround my self, I would really appreciate it if anyone has an idea.

Thank you again,

Query parameters don’t work

Hi there. It appears that you’re using the Axios library to formulate your requests. When I follow your readme doc to add request parameters to the API query, I don’t get the expected response and it’s as though the parameters weren’t appended at all.

Here’s the doc

params: {
        requestParameters: ['some', 'request', 'parameters']
      },

Here’s my API: https://api.dc-hsda.ml/organizations/
Query parameter is: per_page=1

Expected output: an array with one item
Actual output: an array with all 50+ items

Question: how often does the external API get called?

Is it after a certain time interval? Is it every time a user requests the page? Unless caching is enabled ofc. And in case of it being every time a user requests the page, how does this work? From what I can see the plugin sends a request using axios whenever i start a development build. But after that I dont see any new logs in my API server. Its a news API so its relatively important that the newest articles are pulled whenever a user requests the page, not whenever i build and deploy a new instance.

Thanks!

Question: does this plugin make XHR requests?

Hey @thinhle-agilityio I have a few questions about how this plugin works internally:

  1. does it perform an XHR request from the client? which would require the api server to support CORS, if you make the request from a different origin.

  2. if you don't store the JSON locally, what does this plugin do differently than making the request directly from the React Component?

Thank you so much

Possible to query entries?

Got this plugin up and running, and I can grab all things from an endpoint just great 🎉! However, I’m wondering if there’s a way to query entries.

Example:
I hook up this plugin to https://swapi.co like so:

    {
      resolve: 'gatsby-source-apiserver',
      options: {
        name: 'people',
        method: 'get',
        url: 'https://swapi.co/api/people/',
        auth: false,
        entityLevel: 'results',
        typePrefix: '', // must be empty string so it’s not “undefinedPeople”
      },
    },

The following works great:

export const PeopleQuery = graphql`
  {
    allProducts {
      name
    }
  }
`;

However, I need to be able to do query the endpoint like so:

export const PeopleQuery = graphql`
  {
    people(path: "1") {
      name
    }
  }
`;

And it pings https://swapi.co/api/people/1 as the full URL to get the result I want (similar to how apollo-link-rest works).

I realize that auto-mapping schema to URL params would be pretty hard (in this example, I wouldn’t expect this plugin to know how to process people(id: "1") because I haven’t told it how id modifies the REST response). But would a “dumb” URL suffix solution like this be possible somehow?

Pagination json file

Hello there,

I'm playing with this plugin and it's working for my APIs. But I'm not able to figure out how to download all files with dynamic pagination.

Supose,

API URL: https://spreadsheets.google.com/feeds?page=1

what if I want to download the all page JSON data into my folder.

please let me know.

Accessing dynamic object in response

Hey there,

I'm trying to entityLevel setting correct when I have a response that sets it's own internal id as the object, for example, the response:

"list": {
    "2214462582": {
      …
    },
    "2286786905": {
…    
}
  },

etc. So at the moment I have entityLevel: list``, but this results in a GraphQL query of:

{
allTypeposts{
  edges{
  node{
    alternative_2214462582{
      resolved_title
    }
  }
  }
}
}

etc, And I'm not 100% sure if that will cause issues elsewhere in Gatsby? For example, what query do I now use to show a list of all items?

Sorry, bit new to Gatsby, so maybe this is a really dumb question.

Is it possible to define relationships

I'm consuming form three endpoints but they're all related to each other but I'm not sure how to declare the types and relationships with this plugin.

Thanks Dan

Not showing up in GraphQL Playground

Hi, I have this configruation. Yet it is not showing up in the GraphQL Playground. Therefore I am not able to see and query.
The file is being downloaded to local and the JSON is valid. Don't see what I'm doing wrong here. Need some advise. TIA!

module.exports = {
  plugins: [
    "gatsby-plugin-sass",
    {
      resolve: "gatsby-source-apiserver",
      options: {
        typePrefix: "internal__",
        url: `https://example.com`,
        method: "GET",
        headers: {
          "Content-Type": "application/json",
        },
        name: `apiData`,
        allowCache: false,
        localSave: true,
        path: `${__dirname}/src/data/`,
        verboseOutput: true,
        skipCreateNode: false,
        enableDevRefresh: true,
      },
    },
  ],
}

Help: getting error when gatsby build

Hi,
First of all thanks for this plugin, I am new to gatsby / react and maybe I am doing something wrong here but facing below issues:

  1. gatsby develop (this runs smoothly and fetching my APi Data and showing into the page
  2. gatsby build (when this command runs I am getting error
    "gatsby-source-apiserver" threw an error while running the sourceNodes lifecycle:
    TypeError: Cannot read property 'data' of undefined

Surely this is not plugin issue but require your help on correcting mine below implementation.

my gatsby.config.js

module.exports = {
  siteMetadata: {
    title: Gatsby Default Starter,
    description: Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.,
    author: @gatsbyjs,
  },
  plugins: [
    {
      resolve: "gatsby-source-apiserver",
      options: {
        entitiesArray: [
          {
            url: ${process.env.GATSBY_API_ARTICLE},
            method: "GET",
            headers: {
              apikey: ${process.env.GATSBY_APIGEE_API_KEY},
            },
            name: "articleData",
          },
        ],
      },
    },
],
}

article.js

export default class article extends Component {
  // constructor(props) {
  //   super(props)
  // }

  render() {
    const { data } = this.props
    const articleData = data.allArticleData.nodes[0]
    const { id, slug } = articleData
    return (
      <Layout>
        <SEO title="Article Page" />
        <h1>This is single article page</h1>
        <h2>id : {id}</h2>
        <h2>slug: {slug}</h2>
        <pre>
          <code>{JSON.stringify(articleData, null, 2)}</code>
        </pre>
      </Layout>
    )
  }
}

export const queryArticle = graphql"
  {
    allArticleData(filter: { id: { ne: "dummy" } }) {
      nodes {
        seoTitle
        slug
        title
        updatedAt
        body {
          contentType
          alternative_fields {
            quizTitle
            richTextBlock
            riddleEmbedCode
            riddleId
          }
        }
      }
    }
  }
"

Error: The new node didn't pass validation

Just started getting this error, have yet to determine the source.

error The new node didn't pass validation: child "internal" fails because [child "type" fails because ["type" is required]]

Failing node:

{
    "id": "56282d79-b263-5c92-b7db-c78f86453ace",
    "parent": null,
    "children": [],
    "internal": {
        "mediaType": "application/json",
        "contentDigest": "99914b932bd37a50b983c5e7c90ae93b",
        "counter": 26408,
        "owner": "gatsby-source-apiserver"
    }
}

Note: there might be more nodes that failed validation. Output is limited to one node per type of validation failure to limit terminal spam.

  649 |         if (exec) {
  650 |             try {
> 651 |                 return exec(context, _event.data, {
      |                        ^
  652 |                     action: action,
  653 |                     state: this.state,
  654 |                     _event: _event

our configuration looks like this:

{
      resolve: "gatsby-source-apiserver",
      options: {
        entitiesArray: [
          {
            typePrefix: "Neto",
            localSave: true,
            url: `${process.env.FIREBASE_FUNCTIONS_ENDPOINT}/getfeed?filename=feed`,
            method: "GET",
            headers: {
              "Content-Type": "application/json",
              account: `${process.env.FIREBASE_SERVICE_ACCOUNT}`
            },
            name: `Product`,
            schemaType: productType,
            allowCache: false,
            maxCacheDurationSeconds: 60 * 60 * 24,
            localSave: true,
            path: `${__dirname}/src/data/`,
            verboseOutput: true
          },
          {
            typePrefix: "Neto",
            localSave: true,
            url: `${process.env.FIREBASE_FUNCTIONS_ENDPOINT}/getfeed?filename=specials`,
            method: "GET",
            headers: {
              "Content-Type": "application/json",
              account: `${process.env.FIREBASE_SERVICE_ACCOUNT}`
            },
            name: `Special`,
            schemaType: productType,
            allowCache: false,
            maxCacheDurationSeconds: 60 * 60 * 24,
            localSave: true,
            path: `${__dirname}/src/data/`,
            verboseOutput: true
          },
          {
            typePrefix: "Neto",
            localSave: true,
            url: `${process.env.NETOAPI_DOMAIN}/do/WS/NetoAPI`,
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              NETOAPI_ACTION: "GetWarehouse",
              NETOAPI_USERNAME: process.env.NETOAPI_USERNAME,
              NETOAPI_KEY: process.env.NETOAPI_KEY
            },
            data: {
              Filter: {
                OutputSelector: [
                  "ID",
                  "WarehouseID",
                  "IsPrimary",
                  "IsActive",
                  "ShowQuantity",
                  "WarehouseReference",
                  "WarehouseName",
                  "WarehouseStreet1",
                  "WarehouseStreet2",
                  "WarehouseCity",
                  "WarehouseState",
                  "WarehousePostcode",
                  "WarehouseCountry",
                  "WarehouseContact",
                  "WarehousePhone"
                ]
              }
            },
            name: `Warehouse`,
            entityLevel: `Warehouse`,
            allowCache: false,
            maxCacheDurationSeconds: 60 * 60 * 24,
            localSave: true,
            path: `${__dirname}/src/data/`,
            verboseOutput: true
          }
        ]
      }
    },

Media type field not following Gatsby convention

I noticed that a type created by this plugin contained the field mediaType which is not in my data. Having written my own Gatsby plugin I know that the Node interface has a specific place where it expects this field.

id: String,
children: Array[String],
parent: String,
fields: Object,
internal: {
  contentDigest: String,
  mediaType: String,
  type: String,
  owner: String,
  fieldOwners: Object,
  content: String,
}
# ... other fields specific to this type of node

Source: Gatsby docs on Node Interface

Notice that mediaType is a child of internal, not field on the first level of the node. When trying to query for the internal media type, null is returned because this plugin adds the field outside of the internal object.

{
  "data": {
    "myType": {
      "internal": {
        "mediaType": null
      },
      "mediaType": "application/json"
    }
  }
}

Following the convention ensures that other plugins know how to handle the nodes created by your plugin, which contributes to the ecosystem of loosely coupled plugins that are the backbone of Gatsby.

In this case, it also keeps metadata out of the way of the user, since most people don't open up that internal object too often.

Please consider moving the mediaType field to the internal object.

entitiesArray doesn't work

entitiesArray doesn't work

Hello! First of all thank you for this great Gatsby plugin. I am currently trying to use it in a project of mine and I am having troubles with entitiesArray prop. This is the gatsby-config I use for the plugin:

    {
      resolve: `gatsby-source-apiserver`,
      options: {
        typePrefix: `Example`,
        payloadKey: `data`,
        url: `http://example.com/api/v1/item_category/list.php`,
        name: `ItemCategories`,
        method: `get`,
        entitiesArray: [
          {
            url: `http://example.com/api/v1/item_type/list.php`,
            name: `ItemTypes`,
            method: `get`
          }
        ]
      }
    }

When I do this I get data for ItemCategories in the graphQL, but I can't seem to get ANY data f for ItemTypes. If I move ItemTypes out of entitiesArray & replace with ItemCategories, I only get data for ItemTypes. If I move both URLs in entitiesArray I got an error.

It feels like entitesArray is totally ignored.

I am using Gatsby version 2.15.28 & gatsby-source-apiserver version 2.1.3

Thank you in advance for the help!

Error when defining Schema Type

When I uncomment the postType schema as below I get an error in gatsby, not sure what I'm doing wrong, am I missing a step somewhere?

Error: S:\gatsbyninox\gatsby-config.js:58
const postType = {
^^^^^^^^
SyntaxError: Unexpected identifier

// Nested level of entities in response object, example: data.posts
// entityLevel: data.portfolio,

    // Define schemaType to normalize blank values
    // example:


    const postType = {
      id: 1,
      sequence: 2
     },
    schemaType: postType,

    // Request parameters
    // Only available from version 2.1.0
    // params: {
    //   per_page: 1
    // },

Cannot read post of undefined

My config to the issue stated in the title:

`{
resolve: 'gatsby-source-apiserver',
options: {
// Type prefix of entities from server
typePrefix: 'internal__',

    // The url, this should be the endpoint you are attempting to pull data from
    url: 'http://localhost:8010/proxy/companies',

    method: 'POST',

    headers: {
      Accept: 'application/json',
      'user-key': 'cc9c2b79c9b903c7e5c5dd721c77fb17',
    },

    // Request body
    data: { 'fields name,published.name,published.cover.url,published.slug;where id = 51;' },

    // Name of the data to be downloaded.  Will show in graphQL or be saved to a file
    // using this name. i.e. posts.json
    name: 'posts',

    // Nested level of entities in response object, example: `data.posts`
    entityLevel: 'data.posts',

    // Define schemaType to normalize blank values
    // example:
    // const postType = {
    //   id: 1,
    //   name: 'String',
    //   published: true,
    //   object: {a: 1, b: '2', c: false},
    //   array: [{a: 1, b: '2', c: false}]
    // }
    // schemaType: postType,

    // Simple authentication, if optional, set it null
    auth: {
      username: null,
      password: null,
    },

    // Optionally save the JSON data to a file locally
    // Default is false
    localSave: true,

    //  Required folder path where the data should be saved if using localSave option
    //  This folder must already exist
    path: `${__dirname}/src/data/`,

    // Optionally include some output when building
    // Default is false
    verboseOutput: true, // For debugging purposes

    // Optionally skip creating nodes in graphQL.  Use this if you only want
    // The data to be saved locally
    // Default is false
    skipCreateNode: false, // skip import to graphQL, only use if localSave is all you want
  },
},`

`TypeError: Cannot read property 'posts' of undefined

  • helpers.js:6 exports.objectRef
    [gddb]/[gatsby-source-apiserver]/helpers.js:6:14

  • gatsby-node.js:90
    [gddb]/[gatsby-source-apiserver]/gatsby-node.js:90:22

  • Generator.next

  • gatsby-node.js:1 step
    [gddb]/[gatsby-source-apiserver]/gatsby-node.js:1:253

  • gatsby-node.js:1
    [gddb]/[gatsby-source-apiserver]/gatsby-node.js:1:423

  • task_queues.js:89 processTicksAndRejections
    internal/process/task_queues.js:89:5`

Obviously missing a puzzle piece here or not having a wrong config, any hint would be appreciated. Cheers

Getting 400 BadRequest from Google API

I'm attempting to use the plugin to generate GraphQL from a public calendar via Google API. I can get a JSON response by going to the following URL:

https://www.googleapis.com/calendar/v3/calendars/<calendarId>/events?key=<apiKey>

Works great, I get everything I need. But I can't seem to get that same format to work using the plugin. Here's what I have right now:

{
      resolve: "gatsby-source-apiserver",
      options: {
        url: `https://www.googleapis.com/calendar/v3/calendars/<myCalendarId>/events`,
        method: 'get',
        data: {
        },
        headers: {
          "Content-Type": "application/json",
        },
        auth: false,
        params: {
          key: "myApiKey",
        },
        name: `items`,
        verboseOutput: true,
        enableDevRefresh: true,
      },
    },

I've tried a variety of ways of getting the key to work. Every time I run gatsby develop I get a 400 Error indicating a bad request and Google API says: Your client has issued a malformed or illegal request.

I could give a dump of the entire response but it is.. a lot.

The URL actually looks fine but for some reason it's not responding like I'd think.

Refresh existing pages using ENABLE_GATSBY_REFRESH_ENDPOINT

👋 Hello @thinhle-agilityio! Thanks for your work on this plugin; it's working really well for us.

I'm using ENABLE_GATSBY_REFRESH_ENDPOINT with gatsby develop locally and have had success when nodes are added. However, when changing one of the fields on the node, or deleting a node, it doesn't look like the source data is successfully refreshed. In addition, when adding a node after either one of those changes, the preceding changes are not refreshed.

See gatsbyjs/gatsby#14653 for more details.

@freiksenet thinks it's because this plugin is generating new IDs with each fetch. Do you think there's a way to make ENABLE_GATSBY_REFRESH_ENDPOINT work as advertised? I'm happy to work on a PR if you can get me pointed in the right direction.

P.S. My use case is this: I would like to have a staging site set up on a Heroku server or something similar that is constantly running gatsby develop and resourcing data when it changes. Just for previewing purposes while we have a team editing content.

Filter argument is not working

When using the filter argument in GraphQL explorer, it is not working. I'm passing the following query

  allHerculesData(filter: {result: {pages: {elemMatch: {type: {eq: "page"}}}}}) {
    edges {
      node {
        result {
          pages {
            title
            type
          }
        }
      }
    }
  }
}

The result is a list of pages of any type. Am I doing something wrong with the query or is it that it's not possible to filter queries converted from JSON?

Security vulnerability in dependency

I'm using this plugin. NPM is complaining about a vulnerability in one of the dependencies of this package.

  Low             Regular Expression Denial of Service

  Package         braces

  Patched in      >=2.3.1

  Dependency of   gatsby-source-apiserver

Nested queries?

Does this tool allow for making "nested" queries, based on the response from previous queries?

The use case I'm thinking of is a relatively typical one. There's an index-style GET URL that returns high-level information (including IDs) for a list of objects, but if you want the full in-depth info, you have to query for each object (eg /resources/:id) independently, after having pulled the list of IDs.

Does this tool support that somehow? If not, any suggestions? (Sorry if this has already been asked. Couldn't find a similar issue).

How Does it work with incremental builds?

How would this work if we want to take advantage of incremental builds? For instance using your example:

entitiesArray: [
        {
          url: `http://yourapi.com/api/v1/posts`,
          method: "post",
          headers: {
            "Content-Type": "application/json"
          },
          name: `posts`,
          
          ...
          ...

What happens when posts change on http://yourapi.com/api/v1/posts If I understood correctly running gatsby build will rebuild the whole site from scratch every single time right? There is no possibility to fetch only updated content when there is a build already in place?

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.