Not able to to update context in Before Create hook

Feature(s) impacted

Before Update Hook

Observed behavior

I am intercepting the Create request from the forest admin using the Before Create hook when I add an image to my database. I am extracting the image file and then uploading it to my server and then replacing the image file with the URL of the image I get from my server. But since the context for this is read-only I am not able to modify the URL.

Expected behavior

I should be able to modify the context data before Creating the record

Context

  • Project name: Tastet
  • Team name: Kapi
  • Environment name: Nestjs
  • Agent (forest package) name & version: “@forestadmin/agent”: “^1.8.8”,
  • Database type: MongoDB
  • Recent changes made on your end if any: N/A

Hey @Gagandeep_Singh, and welcome to our community :wave:

  • We provide a plugin to deal with this kind of code on S3: AWS S3 plugin documentation, which can inspire you if you are not dealing with S3 file upload.
  • Maybe overriding the write operation on a specific field (Documentation) could be helpful in your case.
  • Finally, Before Create is not “really” read-only. You should be able to update the context manually via code. We strongly discourage this usage as this may potentially lead to unwanted behavior, but that should still be possible.

If you have any code to share that may help us understand better your use-case, I’ll be more that happy to provide a more in-depth example.

Let me know if that helps.

2 Likes

Hi Jeff, thanks for the response. I have created this loom video to better explain the issue: Loom | Free Screen & Video Recording Software | Loom

Here is the code snippet:

collection.addHook('Before', 'Create', async (context) => {
    await Promise.all(
      context.data.map(async (item, i) => {
        try {
          const galleryResponse = await uploadImage(
            item.parentId,
            item.url,
            item.url[item.url.length - 1],
            item['alt@@@en'],
            i,
          );
          item.url = galleryResponse.data.gallery[0].url;
          context.data[i].url = item.url;
          console.log('context after edit ==>', context);
          return item;
        } catch (e) {
          console.log(e);
        }
      }),
    );
  });

The modified context has the edited url value but ultimately the request which goes has the original blob Image.

I am using a similar approach when updating the image in a Before Update hook and it works fine. Here is the code snippet for that:

collection.addHook('Before', 'Update', async (context) => {
    if (context.patch['url']) {
      const idArray = context.filter.conditionTree['value'].split('.');
      const index = idArray[idArray.length - 1];
      const url = context.patch['url'];
      const urlArray = url.split('/');
      const name = urlArray[urlArray.length - 1];
      try {
        const galleryResponse = await uploadImage(
          idArray[0],
          url,
          name,
          name,
          index,
        );
        context.patch.url = galleryResponse.data.gallery[0].url;
      } catch (e) {
        console.log(e);
      }
    }
  });

After some looking around in the source code I found that patch is not read-only while data is read-only hence I thought it might be that I can’t change the context:


If I understood your use-case correct, I would suggest to use the replaceFieldWriting method to handle this case, as visible in the S3 plugin example.

The API should be easier to use than dealing with Hooks.

Let me know if that helps.

Hi Jeff,

Thanks for the clarification. I tried using replaceFieldWriting but still had no luck.
Here is the code I added, I just wanted to change the value of url:

collection.replaceFieldWriting('url', async (value, context) => {
    if (context.action === 'create') {
      const patch = { url: 'goooo' };
      console.log(patch);

      return patch;
    }
  });

Still, I am not able to change the response:

Hey @Gagandeep_Singh,

I’m not sure to understand: what is this response you shared?

replaceFieldWriting is made to change the actual value that will be written in database, thus retrieving the record should contains the correct URL in the url field.

Could you share the complete stack trace of the error (If you encounter any ?)