Lambda Layers Nodejs and Typescript

47 views Asked by At

I have the following class I am trying to make into a Lambda Layer in Nodejs.

import { Athena } from "aws-sdk";

export class AthenaHelper {
  private athena = new Athena();

  public queryAthena = async (
    databaseParams: Athena.StartQueryExecutionInput
  ) => {
    const { QueryExecutionId: queryExecutionId } =
      (await this.athena.startQueryExecution(databaseParams).promise()) ?? {};

    if (!queryExecutionId) {
      throw new Error("No query execution ID");
    }

    const params = {
      QueryExecutionId: queryExecutionId,
    };

    // Wait for the query to complete
    await this.waitForQueryCompletion(queryExecutionId);

    // Retrieve the results from Athena in JSON format
    const results = await this.getQueryResultsInJsonFormat(params);

    return results;
  };

  private waitForQueryCompletion = async (
    queryExecutionId: string | undefined
  ) => {
    try {
      if (!queryExecutionId) {
        throw new Error("No query execution ID");
      }
      let state: string | null | undefined = null;
      while (
        state !== "SUCCEEDED" &&
        state !== "FAILED" &&
        state !== "CANCELLED"
      ) {
        await new Promise((res) => setTimeout(res, 1000));

        const { QueryExecution } = await this.athena
          .getQueryExecution({
            QueryExecutionId: queryExecutionId,
          })
          .promise();

        state = QueryExecution?.Status?.State;
      }
      return state;
    } catch (error) {
      throw error;
    }
  };

  private getQueryResultsInJsonFormat = async (
    params: Athena.GetQueryResultsInput
  ): Promise<Record<string, string | null>[]> => {
    const result: Athena.GetQueryResultsOutput = await this.athena
      .getQueryResults(params)
      .promise();

    const columnInfo: Athena.ColumnInfo[] =
      result.ResultSet?.ResultSetMetadata?.ColumnInfo || [];

    const rows =
      // The column names are returned in the first result set, this strips them out
      result.ResultSet?.Rows?.slice(1).map((row) => {
        const rowData: Record<string, string | null> = {};
        row.Data?.forEach((data, index) => {
          rowData[columnInfo[index].Name] = data?.VarCharValue || null;
        });
        return rowData;
      }) || [];
    return rows;
  };
  public helloWorld() {
    console.log("Hello World");
  }
}

I use the tsc command to compile it to vanilla Javascript and I uploaded it to Lambda Layers.

I than run my lambda function that looks as follows:

exports.handler = async (event, context) => {
  try {
  
  const AthenaHelper = require('/opt/nodejs/AthenaHelper');
  
  const athenaHelper = new AthenaHelper()
  
  athenaHelper.helloWorld()
    return {
        statusCode: 200,
        body: 'Hello, World!'
    };
  } catch (error) {
    console.log('error', JSON.stringify(error))
  }
};

upon running the code I get the following error:

{
  "errorType": "ReferenceError",
  "errorMessage": "exports is not defined in ES module scope",
}

Any suggestions here? Has anyone made a custom class in Typescript and tried to export it to a Lambda Layer? Any advice would be appreciated.

TS Config

{   "compilerOptions": {     "lib": ["es2018", "dom"]   } } 

0

There are 0 answers