Migration to `@forestadmin/agent` - The new agent tries to load fields / smart fields for relationships that are not defined in the record details page

We’re migrating from forest-express-sequelize to @forestadmin/agent.

The new agent tries to load fields / smart fields for relationships that are not defined in the record details page.

While navigating on the list view nothing happens, but if I navigate to the record details view (clicking on a single record) the agent tries to load smart fields even if the linked relationship is not defined.

In the list view the getValues is not called at all in the smart fields of the undefined relationship’s collection, but in the details view it is called passing [ {} ] as value for the records parameter, which causes many problems.

e.g. In the list view everything works, in the details view the record without the boat defined returns the error.

image (42)

As a workaround we’ve had to add this check to every getValues .

image (44)

How to make this work correctly, without having to check it on our side?!?

Here is the “meta” section of the forest admin schema file:

  {
    "liana": "forest-nodejs-agent",
    "liana_version": "1.41.7",
    "liana_features": null,
    "stack": {"engine": "nodejs", "engine_version": "20.11.1"}
  }

and from package.json:

"sequelize": "^6.28.0"

cc @julien.jolles

Thank you
Matteo

Hello @Matteo ,

Can you share a bit more of your agent’s code ?
I cannot reproduce your issue and don’t understand where could the blank records come from.

This is the expected behavior - Even on null relation, we’ll try to compute the potential list of smart fields on an empty record.
This behavior was backported from v1 as some existing users are using it - but we may be lacking a bit of documentation on this one - I’ll file a ticket right away.

The general rule of thumbs regarding field computation is that dependencies will not always be provided - and this needs to be manually checked on your end.

A potential solution we use to deal with this is the following:

function areDependenciesDefined(deps: string[], record: Record<string, any>): Boolean {
  return deps.every(dep => {
    if (dep.includes(':')) {
      const v = dep.split(':').reduce((acc, d) => { if(!acc) return; return acc[d]; }, record);
      return !!v;
    } else {
      return !!record[dep];
    }
  });
}

const myFieldDependencies = ['field1', 'field2'];

// ...
dependencies: myFieldDependencies
getValues: (records, context) => {
    return records.map(record => {
        if(areDependenciesDefined(myActionDependencies, record)) return null;
        // Do your actual dependency computation
    });
  }
}

Obvious it can be a bit more complex than this, especially when dealing with an API where you would not be able to iterate over the records, but the general idea is the same.

To give a bit more context:

  • It works on the table view most likely because your referenceField is able to be computed on null value - And the associated record embed a projection asking only for this referenceField.
  • It doesn’t in the record details because no projection is sent - Thus the full record needs to be recovered just in case the referenceField is actually a computed one.

Let me know if that helps :pray:

1 Like

Thank you @jeffladiray
If this is the intended behaviour of the new agent we’re ok in managing this case on our side :+1: as you suggest.

Thank you very much.
Matteo

1 Like