🚀 Optimising Code Reusability: Creating a Private NPM Package for Shared AWS Services & Common Utilities

Shivam  AgrawalShivam Agrawal
4 min read

Introduction

When working with multiple repositories, maintaining shared logic across each project can lead to code duplication, inconsistencies, and increased maintenance overhead.

A better approach is to create a private NPM package that consolidates reusable logic into a single repository. This aligns with the DRY (Don't Repeat Yourself) principle, making your codebase more scalable, maintainable, and efficient.

In this blog, we’ll explore:
✅ Different ways to publish an NPM package
✅ The benefits of using a private package
✅ A step-by-step guide to creating and using a private NPM package
Other reusable components that can be converted into an NPM package


⚡ Why Use an NPM Package for Shared Code?

Developers often duplicate logic across multiple repositories, making maintenance difficult. Instead of writing and updating the same code in different projects, we can extract commonly used code into a single NPM package and reuse it across repositories.

Some common examples of reusable code include:

AWS Service Wrappers

  • S3 (Storage)

  • SQS (Message Queue)

  • SNS (Notifications)

  • Secrets Manager (Credential Storage)

  • AppConfig (Configuration Management)

  • EventBridge (Event-driven Communication)

  • CloudWatch (Monitoring & Logs)

Common Utilities & Helpers

  • Masking sensitive data

  • Logging utilities

  • Exception handlers

  • Custom decorators (for authorization, validation, etc.)

  • Database query builders

NestJS-Specific Reusable Components

  • Guards (Authentication, Role-based access control)

  • Filters (Global exception handling)

  • Interceptors (Logging, Request transformation)

  • Custom decorators

  • 3rd-party service integrations (like Stripe, Twilio, etc.)


📦 How to Publish an NPM Package?

There are three main ways to publish an NPM package:

1️⃣ Public NPM Package

  • If the code is generic and doesn’t contain sensitive information, publish it as a public package on the NPM registry.

  • Example: axios, lodash, etc.

2️⃣ Private NPM Package (Enterprise Registry)

  • If the package contains internal logic or proprietary code, a private package is a better option.

  • Requires a paid NPM Enterprise account (or services like GitHub Packages, AWS CodeArtifact, or Verdaccio).

  • If you don’t want to pay for an Enterprise NPM account, host the package in a private GitHub/GitLab repo.

  • Install it in projects using:

      npm install git+ssh://git@github.com:your-org/your-private-package.git
    
  • You can configure scoped access to limit usage within your organization.


🔨 Step-by-Step: Creating a Private NPM Package

1️⃣ Initialize Your NPM Package

Create a new folder and initialize an NPM package:

mkdir shared-utils && cd shared-utils
npm init -y

This will generate a package.json file.


2️⃣ Install Required Dependencies

npm install aws-sdk dotenv winston

3️⃣ Write AWS Service Wrappers

Example: S3 Service Utility

Create src/s3Service.ts:

import AWS from 'aws-sdk';

export class S3Service {
  private s3: AWS.S3;

  constructor() {
    this.s3 = new AWS.S3();
  }

  async uploadFile(bucket: string, key: string, file: Buffer) {
    const params = { Bucket: bucket, Key: key, Body: file };
    return this.s3.upload(params).promise();
  }
}

Example: SQS Service Utility

Create src/sqsService.ts:

import AWS from 'aws-sdk';

export class SQSService {
  private sqs: AWS.SQS;

  constructor() {
    this.sqs = new AWS.SQS();
  }

  async sendMessage(queueUrl: string, message: string) {
    const params = { QueueUrl: queueUrl, MessageBody: message };
    return this.sqs.sendMessage(params).promise();
  }
}

4️⃣ Add Common Utilities & Helpers

Example: Masking Sensitive Data

Create src/maskFields.ts:

export function maskFields(obj: Record<string, any>, fieldsToMask: string[]) {
  return Object.fromEntries(
    Object.entries(obj).map(([key, value]) => [
      key,
      fieldsToMask.includes(key) ? '****' : value
    ])
  );
}

Example: Logger Utility

Create src/logger.ts:

import winston from 'winston';

export const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'app.log' })
  ]
});

5️⃣ Export Services from index.ts

Create src/index.ts:

export { S3Service } from './s3Service';
export { SQSService } from './sqsService';
export { maskFields } from './maskFields';
export { logger } from './logger';

6️⃣ Compile the Package (If Using TypeScript)

If you’re using TypeScript, add a tsconfig.json:

{
  "compilerOptions": {
    "outDir": "dist",
    "module": "CommonJS",
    "target": "ES6",
    "declaration": true
  }
}

Then compile:

tsc

7️⃣ Publish the Package

A) Publishing to NPM (Public/Private Registry)

  1. Login to NPM:

     npm login
    
  2. Publish the package:

     npm publish --access=public
    

    If private:

     npm publish --access=restricted
    

B) Publishing to GitHub (Alternative Method)

If you want to use a private GitHub repo, push the package:

git init
git add .
git commit -m "Initial commit"
git remote add origin git@github.com:your-org/shared-utils.git
git push origin main

Then, install it in your projects using:

npm install git+ssh://git@github.com:your-org/shared-utils.git

🚀 Using the Package in Another Project

Now that the package is published, install and use it in another repository:

npm install @your-org/shared-utils

Example usage:

import { S3Service, SQSService, maskFields, logger } from '@your-org/shared-utils';

const s3 = new S3Service();
await s3.uploadFile('my-bucket', 'test.txt', Buffer.from('Hello World'));

const maskedData = maskFields({ password: 'secret123' }, ['password']);
console.log(maskedData); // { password: '****' }

logger.info('Application started');

🎯 Conclusion

By creating a private NPM package for AWS services and common utilities, you can eliminate redundancy, improve maintainability, and simplify collaboration across multiple repositories.

💡 If your project has shared code, consider modularising it into an NPM package today! 🚀

🔗 Follow me for more tech insights! 🚀



2
Subscribe to my newsletter

Read articles from Shivam Agrawal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Shivam  Agrawal
Shivam Agrawal