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

How to solve the resolveInput hook inconsistency? #2707

Closed
Vultraz opened this issue Apr 10, 2020 · 3 comments
Closed

How to solve the resolveInput hook inconsistency? #2707

Vultraz opened this issue Apr 10, 2020 · 3 comments
Assignees

Comments

@Vultraz
Copy link
Contributor

Vultraz commented Apr 10, 2020

There have been several issues now (#2186, #2503, and #2508 at least) mentioning the unexpected behavior with field-level resolveInput hooks. Essentially, instead of the return value from field-level hooks matching the structure of the resolvedData input, you need to return a specific value resolvedData.name, for example).

I did some digging, and I figured out why this happens. In List._resolveInput, there's this block:

    // Run the schema-level field hooks, passing in the results from the field
    // type hooks
    resolvedData = {
      ...resolvedData,
      ...(await this._mapToFields(
        this.fields.filter(field => field.hooks.resolveInput),
        field => field.hooks.resolveInput({ ...args, resolvedData })
      )),
    };

The problem with this is, since _mapToFields uses arrayToObject, if the hook here returns an object such as { name: 'newNameValue' }, resolvedData from here on out will end up looking like this:

{ name: { name: 'Test8' } }

This happens since arrayToObject returns an object with each field's path as the key, and the value the result of the hook - in this case, an object. If the hook simply returns a value, everything maps as expected.

I'm not sure how best to solve this, but it's definitely unexpected behavior. Couple options:

  • Keep the current behavior and simply add a doc note explaining you need to return a value from field-level resolveInput hooks. This would conceptually make sense. Since it's a field hook, you're returning the new value for that field.
  • Make the resolvedData argument for field hooks simply be the value for that hook. This way, the "output should match the structure of the input" design would hold. However, this would mean the resolved data for other fields no longer gets passed in to the field hook, like it currently does - if that's an issue. For example, if you have a field-level hook on a name field in a User list, and change both the name and email fields, the resolvedData input for the hook will be, for instance:
{ name: 'Test9', email: 'test@keystone.js.foo' }
  • Automatically pick the value out of the returned object by field path in the _mapToFields callback above. This could be combined with a check on the returned value's type.

There's also field type resolveInput hooks to consider. Looking at these, it seems they actually already simply return the value for that field, so changing the behavior for the field level hooks seems reasonable.

🤔

@MadeByMike
Copy link
Contributor

I might be too close to it but I don't understand the confusion. I had to do this yesterday and I initially made a mistake of returning an object but immediately realised I ended up with something like { name: { name: 'Mike' } } so, I returned the value.

I think the only option is:

"Keep the current behavior and simply add a doc note explaining you need to return a value from field-level resolveInput hooks. This would conceptually make sense. Since it's a field hook, you're returning the new value for that field."

Anything else is a large breaking change to something pretty highly used.

Do you think the confusion comes from here: https://www.keystonejs.com/api/hooks#resolveinput

@MadeByMike MadeByMike self-assigned this Jun 5, 2020
@gautamsi
Copy link
Member

that doc portion seems to be causing confusion. It should be saying returning value for the field.

@bladey
Copy link
Contributor

bladey commented Apr 8, 2021

Keystone 5 has officially moved into active maintenance mode as we push towards the next major new version Keystone Next, you can find out more information about this transition here.

In an effort to sustain the project going forward, we're cleaning up and closing old issues such as this one. If you feel this issue is still relevant for Keystone Next, please let us know.

@bladey bladey closed this as completed Apr 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants