Search code examples
typescriptes6-modulescommonjsaws-sdk-nodejsnpm-package

TypeError: AWS.S3 is not a constructor


I am trying to create a NPM package but before I do that, I am testing it using the

yarn link command and then importing the node_module into another project.

This is what my package.json for the NPM package looks like

{
  "name": "qa-data-tool",
  "version": "1.0.0",
  "description": "AWS uploads to S3 to support testing of invoicing PYCMA accounts",
  "main": "dist/cjs/index",
  "types": "dist/cjs/index.d.ts",
  "type": "module",
  "exports": {
    ".": {
      "require": "./dist/cjs/index.js",
      "import": "./dist/esm/index.js"
    }
  },
  "files": [
    "/dist"
  ],
  "scripts": {
    "tsc": "tsc",
    "test": "jest",
    "test typescript": "tsc ./src/testing.ts && node ./src/testing.js",
    "build": "rm -rf dist/ && prettier --write src/ && npm run build:esm && npm run build:cjs",
    "build:esm": "tsc",
    "build:cjs": "tsc --module CommonJS --outDir dist/cjs"
  },
  "keywords": [],
  "author": "",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": ""
  },
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@babel/preset-env": "^7.18.10",
    "@babel/preset-typescript": "^7.18.6",
    "@types/jest": "^28.1.7",
    "@typescript-eslint/eslint-plugin": "^5.17.0",
    "@typescript-eslint/parser": "^5.17.0",
    "babel-jest": "^28.1.3",
    "esbuild": "^0.14.54",
    "eslint": "^8.12.0",
    "eslint-config-airbnb": "^19.0.4",
    "eslint-config-airbnb-typescript": "^17.0.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-import-resolver-typescript": "^2.7.0",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-json": "^3.1.0",
    "eslint-plugin-jsx-a11y": "^6.5.1",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-react": "^7.29.4",
    "jest": "^28.1.3",
    "prettier": "^2.6.1",
    "ts-node": "^10.9.1",
    "typedoc": "^0.22.13",
    "typescript": "^4.7.4"
  },
  "dependencies": {
    "@types/json2csv": "^5.0.3",
    "aws-sdk": "^2.1200.0",
    "csv": "^6.2.0",
    "csv-parser": "^3.0.0",
    "dayjs": "^1.11.5",
    "dotenv": "^16.0.1",
    "json2csv": "^5.0.7"
  },
  "jest": {
    "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts)$",
    "moduleFileExtensions": [
      "ts",
      "js"
    ]
  }
}

This is the folder sturcture of my project:

enter image description here

I am initializing the S3 bucket like so:

import * as dotenv from 'dotenv'; 
import * as path from 'path';
import * as fs from 'fs';
import * as util from 'util';
import * as AWS from 'aws-sdk';

dotenv.config({ path: path.resolve('.env') });
const readFile = util.promisify(fs.readFile); 

const s3 = new AWS.S3({
  region: process.env.REGION,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
});

/**
 * Uploads a file to the specified S3 bucket
 * @param filePath - relative path of the file you would like to upload e.g src/uploads/filename.txt
 * @param bucketName - the name of the bucket you would like to upload to e.g aspiration-galileo-staging-sftp-all/2023/09/
 */
export async function s3Upload(
  filePath: string,
  bucketName: string,
): Promise<void> {
  const fileData = await readFile(filePath);
  let extractFileName = filePath.split('/');
  const uploadFile = s3
    .putObject({
      Bucket: bucketName, //bucket name to upload your file too
      Key: extractFileName[extractFileName.length - 1], //name of the file will be the last element in the array
      Body: fileData,
    })
    .promise(); 
  uploadFile
    .then((data) => {
      console.log(`File uploaded to s3 bucket: ${bucketName} successfully`);
    })
    .catch((err) => {
      console.log(err);
    });
}

Now when I try to use these modules in my simple node.js package I get the following error:

const s3 = new AWS.S3({
           ^

TypeError: AWS.S3 is not a constructor

can someone point me in the right direction on how to solve this error message?


Solution

  • had to change my code to

    import * as dotenv from 'dotenv';
    import * as path from 'path';
    import * as fs from 'fs';
    import * as util from 'util';
    import S3 from 'aws-sdk/clients/s3.js'; 
    
    dotenv.config({ path: path.resolve('.env') });
    const readFile = util.promisify(fs.readFile);
    
    const s3 = new S3({
      region: process.env.REGION,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
      accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    });
    
    /**
     * Uploads a file to the specified S3 bucket
     * @param filePath - relative path of the file you would like to upload e.g src/uploads/filename.txt
     * @param bucketName - the name of the bucket you would like to upload to e.g aspiration-galileo-staging-sftp-all/2023/09/
     */
    export async function s3Upload(
      filePath: string,
      bucketName: string,
    ): Promise<void> {
      const fileData = await readFile(filePath);
      let extractFileName = filePath.split('/');
    
      s3.upload(
        {
          Bucket: bucketName, //bucket name to upload your file too
          Key: extractFileName[extractFileName.length - 1], //name of the file will be the last element in the array
          Body: fileData,
        },
        (err, data) => {
          if (err) {
            console.log('There was an error uploading your file: ', err);
          }
          console.log('Successfully uploaded file.', data);
        },
      );
    }