Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

actions.getCollection always returns undefined in plugin #1342

Closed
mklueh opened this issue Sep 13, 2020 · 8 comments
Closed

actions.getCollection always returns undefined in plugin #1342

mklueh opened this issue Sep 13, 2020 · 8 comments
Labels
question Unsure if I am doing it right

Comments

@mklueh
Copy link

mklueh commented Sep 13, 2020

Description

I need to iterate through a collection after it is created and modify some nodes based on information of other nodes.

My idea was to use actions.getCollection()

    api.loadSource(async actions => {
      console.info(actions.getCollection("posts"));
      console.info(actions.getCollection("Posts"));
      console.info(actions.getCollection("post"));
      console.info(actions.getCollection("Post"));
    });

However, there is never a collection returned and I get undefined instead on all calls.

It´s not clear to me what is wrong with that code, because I´m just following the docs, but I´m assuming the callback is executed before the collections are created.

Appreciate any hints and tips on how to get collections after they are created to be able to modify them before the pages are created.

@noxify
Copy link
Contributor

noxify commented Sep 13, 2020

modify some nodes based on information of other nodes

Is onCreateNode not better for this?
--> https://gridsome.org/docs/server-api/#apioncreatenodefn

Anyway.. i have tested it with source-filesystem and it seems to work.

//gridsome.config.js
module.exports = {
  siteName: 'Gridsome',
  plugins: [
    {
      use: '@gridsome/source-filesystem',
      options: {
        typeName: 'BlogPost',
        path: './content/*.md',
      }
    }
  ]
}

I got a response with and without async

  api.loadSource(actions => {
    console.log(actions.getCollection('BlogPost'));
  })

    api.loadSource(async actions => {
    console.log(actions.getCollection('BlogPost'));
  })

Result is something like this:

Initializing plugins...
Collection {
  typeName: 'BlogPost',
  options: {
    typeName: 'BlogPost',
    route: undefined,
    resolveAbsolutePaths: false,
    _indices: [ 'path' ],
    _unique: [ 'path' ]
  },
  //...

I assume you're using a remote source - it's possible that the collection doesn't exists at the moment.
We had this problem in the past with the image downloader plugin.

We solved the problem with the remote sources after moving the logic into the onBootstrap.
--> https://github.com/jammeryhq/gridsome-plugin-remote-images/blob/master/gridsome.server.js#L49

@noxify noxify added the question Unsure if I am doing it right label Sep 13, 2020
@mklueh
Copy link
Author

mklueh commented Sep 13, 2020

@noxify Thanks for the fast response.

I´m using the source-filesystem as well as my only file source besides https://gridsome.org/plugins/gridsome-source-static-meta (which is not what I´m trying to access). No remote source.

Sync and async produce the same result, however I´ve now tried to fetch the collection once in my plugin I´m trying to develop and once in the application itself:

Logs:

collection (plugin) undefined
collection (application) Collection {
  typeName: 'Post',
  options: {
    typeName: 'Post',
    route: undefined,
    resolveAbsolutePaths: false,
    _indices: [ 'path' ],
    _unique: [ 'path' ]
  },

It works as expected in the application (or actual site) but not in the plugin project.

This is all I´m doing in my gridsome-server.js of the plugin

module.exports = function (api) {
    api.loadSource(actions => {
        console.log("collection (plugin)",actions.getCollection("Post"));
    })
}

Which is included in my project using yarn link

Thanks, I´ll look into onCreateNode. Do you think it´s the right hook if you need to build relations between nodes?

@mklueh mklueh changed the title actions.getCollection always returns undefined actions.getCollection always returns undefined in plugin Sep 13, 2020
mklueh added a commit to mklueh/gridsome-plugin-recommender that referenced this issue Sep 13, 2020
@noxify
Copy link
Contributor

noxify commented Sep 13, 2020

Do you think it´s the right hook if you need to build relations between nodes?

This depends of what you want to do :)

We use the onCreateNode currently in some basic use cases ( e.g. transforming the tags inside a blog post )
In this cases we have the relation defined in the source definition ( BlogPost --> Tag ).

Example:

It works as expected in the application (or actual site) but not in the plugin project.

I will give it a try, to see if I can reproduce your problem.

@noxify
Copy link
Contributor

noxify commented Sep 13, 2020

Ok...

created shortly a local package with the following contents:
( files are stored inside the gridsome project in packages/gridsome-test-plugin )

// packages/gridsome-test-plugin/package.json
{
  "name": "gridsome-test-plugin",
  "version": "1.0.0",
  "main": "gridsome.server.js",
  "license": "MIT",
  "private": true
}

// packages/gridsome-test-plugin/gridsome.server.js
module.exports = function (api) {
    api.loadSource(async actions => {
        console.log(actions.getCollection('BlogPost'));
    })
}

Then I ran yarn install inside the package directory.
After installing, I have ran yarn link.

Moved to the gridsome project root and ran yarn link gridsome-test-plugin.

Inside the gridsome.config.js, I have the following config:

// gridsome.config.js

module.exports = {
  siteName: 'Gridsome',
  plugins: [
    {
      use: '@gridsome/source-filesystem',
      options: {
        typeName: 'BlogPost',
        path: './content/*.md',
      }
    },
    {
      use: 'gridsome-test-plugin'
    }
  ]
}

I have currently only one md file inside the content directory - but after calling gridsome develop I was able to see the console.log with the collection.

BUT, if I use the following plugin config inside the gridsome.config.js, I was able to reproduce your problem:

plugins: [
    {
      use: 'gridsome-test-plugin'
    },
    {
      use: '@gridsome/source-filesystem',
      options: {
        typeName: 'BlogPost',
        path: './content/*.md',
      }
    }
  ],

Possible solution:
I would make sure, that the plugin is loaded after the source definition and if this doesn't solve the problem, i would use onCreateNode or onBootstrap.

@mklueh
Copy link
Author

mklueh commented Sep 13, 2020

@noxify Oh dear, you are right. I didn´t know the plugin order matters.

Is this behaviour intentional or just a side effect?

Thank you for your effort :)

mklueh added a commit to mklueh/gridsome-plugin-recommender that referenced this issue Sep 13, 2020
@noxify
Copy link
Contributor

noxify commented Sep 13, 2020

I didn´t know the plugin order matters.

I have checked the code and there is no "load order" or something implemented.
Everything will be called via Promise.
If you have a remote source, the console.log is shown, before the remote source is done.

Question: Does this solve your problem for now?

@mklueh
Copy link
Author

mklueh commented Sep 13, 2020

@noxify I´ve added a hint to the readme for now and an example where the source-filesystem plugin is above mine https://github.com/mklueh/gridsome-plugin-recommender

Thank you very much for your help

@noxify
Copy link
Contributor

noxify commented Sep 13, 2020

You're welcome :)

BTW. Will check if I can integrate your plugin into our starters and replace the Tag based related posts.

I will close this issue since we solved the problem :)

@noxify noxify closed this as completed Sep 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Unsure if I am doing it right
Projects
None yet
Development

No branches or pull requests

2 participants