skip to Main Content

In my NextJS v14 project I would like to create a Dynamo db record every time a user signs up. So, I followed this official AWS tutorial, but I stumbled upon few hiccups, like:

  1. When I run amplify update function in order to allow the Mutation operation to my function, at the end, I only get:

    You can access the following resource attributes as environment variables from your Lambda function:
     API_<MY_API_NAME>_GRAPHQLAPIENDPOINTOUTPUT
     API_<MY_API_NAME>_GRAPHQLAPIIDOUTPUT
    

    Meanwhile I would expect to also get API_<MY_API_NAME>_GRAPHQLAPIKEYOUTPUT to use it later in my lambda function (like shown in the guide)

  2. Now, here’s my custom.js file:

    const GRAPHQL_ENDPOINT = process.env.API_<MY_API_NAME>_GRAPHQLAPIENDPOINTOUTPUT;
    const GRAPHQL_API_KEY = process.env.API_<MY_API_NAME>_GRAPHQLAPIIDOUTPUT;
    
    const query = /* GraphQL */ `
        mutation CREATE_USER($input: CreateUserInput!) {
            createUser(input: $input) {
                username
                email
                mobilePhoneNumber
            }
        }
    `;
    
    /**
     * @type {import('@types/aws-lambda').APIGatewayProxyHandler}
     */
    export const handler = async (event, context) => {
        const variables = {
            input: {
                username: event.userName,
                email: event.request.userAttributes.email,
                mobilePhoneNumber: event.request.userAttributes.phone_number,
            },
        };
    
        const options = {
            method: "POST",
            headers: {
                "x-api-key": GRAPHQL_API_KEY,
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ query, variables }),
        };
    
        const response = {};
    
        try {
            const res = await fetch(GRAPHQL_ENDPOINT, options);
            response.data = await res.json();
            if (response.data.errors) response.statusCode = 400;
        } catch (error) {
            response.statusCode = 400;
            response.body = {
                errors: [
                    {
                        message: error.message,
                        stack: error.stack,
                    },
                ],
            };
        }
    
        return {
            ...response,
            body: JSON.stringify(response.body),
        };
    };
    

    The only difference from the tutorial is that I’m not using the node-fetch module, but rather the native fetch function since I’m using Node v18 (like suggested in this official AWS Amplify documentation and confirmed by the line "Runtime": "nodejs18.x" inside the /amplify/backend/function/<my_function_name>/...-cloudformation-template.json)

    But when this lambda function gets called, I get this error:

    {
        "errorType": "ReferenceError",
        "errorMessage": "require is not defined in ES module scope, you can use import insteadnThis file is being treated as an ES module because it has a '.js' file extension and '/var/task/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension."
    }
    

    Now, as you saw, I’m not using any require import, but I discovered that the auto-generated index.js file (inside: /amplify/backend/function/<my_function_name>/src/index.js) has this line:

    /**
    * The array of imported modules.
    */
    const modules = moduleNames.map((name) => require(`./${name}`));
    

    And I’m not quite sure – also because I’m kinda new to AWS – if I’m allowed to manually edit this file in order to make it ESM compatible or not.

Just for completeness, here’s my package.json of the lambda function:

{
    "name": "...",
    "type": "module",
    "version": "2.0.0",
    "description": "Lambda function generated by Amplify",
    "main": "index.js",
    "license": "Apache-2.0",
    "devDependencies": {
        "@types/aws-lambda": "^8.10.92"
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    Just to collect all the info on how to resolve these problems in case someone else is facing the same issues.


    1. To resolve the first problem, i.e. not able to generate the API_<MY_API_NAME>_GRAPHQLAPIKEYOUTPUT, you just need to have the API key enabled as auth mode on the GraophQL API, basically run amplify update api and picked these options:

      ...
      ? Choose the default authorization type for the API: Amazon Cognito User Pool
      ? Configure additional auth types? Yes
      ? Choose the additional authorization types you want to configure for the API: API key
      ...
      

      Then re-run amplify update function and you will have also the GRAPHQLAPIKEYOUTPUT

    2. For the second problem, as suggested here, I've change the lambda function to use CommonJS by simply removing the "type": "module" (inside the package.json file). On top of that I've also updated the function as such:

      /* global fetch */
      
      // ...
      
      exports.handler = async (event, context) => {
          // ...
      }
      

      Just to clarify, the first comment - i.e. /* global fetch */ - is needed in order to not get this fetch error: fetch is not defined, please fix or add global fetch


  2. In your package.json change "type": "module", to "type": "commonjs",

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search