npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@june24/core-aws

v1.1.5

Published

A comprehensive AWS development toolkit for DynamoDB, S3, and serverless applications with TypeScript support.

Downloads

173

Readme

@june24/core-aws

A comprehensive AWS development toolkit for DynamoDB, S3, and serverless applications with TypeScript support.

🚀 Quick Start

Installation

npm install @june24/core-aws

📋 CLI Commands

The package includes powerful CLI tools for project creation and table configuration management.

🏗️ Create New Project

Generate a complete project structure based on the examples folder:

# Create new project
npx @june24/core-aws create-project --name my-new-project

# Create project in specific folder
npx @june24/core-aws create-project --name my-project --output-folder ./projects

Generated Structure:

my-new-project/
├── src/
│   ├── controllers/          # API controllers with factory pattern
│   │   ├── controller.factory.ts
│   │   ├── user.controller.ts
│   │   └── index.ts
│   ├── services/            # Business logic with factory pattern
│   │   ├── service.factory.ts
│   │   ├── user.service/
│   │   │   ├── user.service.ts
│   │   │   ├── user.service.interface.ts
│   │   │   └── index.ts
│   │   └── index.ts
│   ├── repositories/        # Data access with factory pattern
│   │   ├── repository.factory.ts
│   │   ├── dynamodb.repo/
│   │   │   ├── user.repo.ts
│   │   │   ├── user.repo.interface.ts
│   │   │   └── index.ts
│   │   └── index.ts
│   ├── validation/          # Validation rules with factory pattern
│   │   ├── validation.factory.ts
│   │   ├── user.validation.ts
│   │   └── index.ts
│   ├── handlers/            # Lambda handlers
│   │   ├── crud/
│   │   │   └── user.crud/
│   │   │       ├── index.ts
│   │   │       └── serverless.yml
│   │   ├── trigger/
│   │   │   └── user.trigger/
│   │   │       ├── index.ts
│   │   │       └── serverless.yml
│   │   ├── streamer/
│   │   │   └── user.streamer/
│   │   │       ├── index.ts
│   │   │       └── serverless.yml
│   │   └── schedule/
│   │       └── user.schedule/
│   │           ├── index.ts
│   │           └── serverless.yml
│   └── types/              # TypeScript types
│       └── user.model.ts
├── configs/                 # Table configurations
│   └── user.config.ts
├── serverless/             # Serverless resources
│   ├── dynamodb/
│   │   └── users.yml
│   ├── cognito.yml
│   ├── s3.yml
│   ├── sns.yml
│   ├── sqs.yml
│   ├── ses.yml
│   ├── kms.yml
│   ├── http-api-gateway.yml
│   └── ws-api-gateway.yml
├── package.json            # Project configuration
├── tsconfig.json           # TypeScript configuration
├── serverless.yml          # Serverless configuration
└── README.md               # Project documentation

➕ Add Table Configuration

Add new table with complete structure (controllers, services, repositories, validation, handlers, types):

# Add new table configuration
npx @june24/core-aws add --config ./configs/product.config.ts --name product

# Add with replace option (overwrites existing files)
npx @june24/core-aws add --config ./configs/product.config.ts --name product --replace

# Skip specific components
npx @june24/core-aws add --config ./configs/product.config.ts --name product --skip-validation --skip-handlers

Generated Components:

  • Types: src/types/product.model.ts
  • Validation: src/validation/product.validation.ts
  • Repository: src/repositories/dynamodb.repo/product.repo/
  • Service: src/services/product.service/
  • Controller: src/controllers/product.controller.ts
  • Handlers: src/handlers/crud/product.crud/
  • DynamoDB Config: serverless/dynamodb/product.yml

🎯 Complete Usage Guide

Step 1: Create New Project

# Create new project
npx @june24/core-aws create-project --name my-awesome-project

# Navigate to project
cd my-awesome-project

# Install dependencies
npm install

Step 2: Create Table Configuration

Create a table configuration file in configs/ folder:

// configs/product.config.ts
import { TableConfig } from "@june24/core-aws";

const productTableConfig = new TableConfig();

// Define indexes
productTableConfig.set("By_Category", {
  partitionKeyField: "category",
  sourceFields: ["category"],
  sortKeyField: "createdDate",
});

productTableConfig.set("By_Status", {
  partitionKeyField: "status",
  sourceFields: ["status"],
  sortKeyField: "createdDate",
});

productTableConfig.set("By_Category_Status", {
  partitionKeyField: "category_status",
  sourceFields: ["category", "status"],
  compositeSeparator: "_",
  sortKeyField: "createdDate",
});

// Configure table
productTableConfig.setConfig({
  partitionKey: "id",
  tableName: `Products-${process.env.ENV || "dev"}`,
  deletionPolicy: "Retain",
  billingMode: "PAY_PER_REQUEST",
  streamSpecification: {
    streamViewType: "NEW_AND_OLD_IMAGES",
  },
  pointInTimeRecovery: true,
  tags: {
    Environment: process.env.ENV || "dev",
    Service: "my-service",
    TableType: "products",
  },
});

export default productTableConfig;

Step 3: Add Table to Project

# Add product table with complete structure
npx @june24/core-aws add --config ./configs/product.config.ts --name product

Step 4: Customize Generated Files

Update Type Definition

// src/types/product.model.ts
import { BaseEntity } from "@june24/core-aws";

export interface IProduct extends BaseEntity {
  name: string;
  description?: string;
  price: number;
  category: string;
  status: "active" | "inactive" | "draft";
  stockQuantity: number;
  tags?: string[];
}

Update Validation Rules

// src/validation/product.validation.ts
import { ValidationRule, commonValidations } from "@june24/core-aws";

export class ProductValidation {
  static getCreateValidationRules(): ValidationRule[] {
    return [
      commonValidations.required("id"),
      commonValidations.required("name"),
      commonValidations.required("price"),
      commonValidations.required("category"),
      commonValidations.required("status"),

      {
        field: "name",
        type: "string",
        minLength: 2,
        maxLength: 100,
        required: true,
      },
      {
        field: "price",
        type: "number",
        min: 0,
        required: true,
      },
      {
        field: "status",
        type: "string",
        custom: (value) => {
          const validStatuses = ["active", "inactive", "draft"];
          if (!validStatuses.includes(value)) {
            return `Status must be one of: ${validStatuses.join(", ")}`;
          }
          return true;
        },
      },
    ];
  }

  static getUpdateValidationRules(): ValidationRule[] {
    return [
      {
        field: "name",
        type: "string",
        minLength: 2,
        maxLength: 100,
      },
      {
        field: "price",
        type: "number",
        min: 0,
      },
    ];
  }

  static getSearchValidationRules(): ValidationRule[] {
    return [
      {
        field: "category",
        type: "string",
      },
      {
        field: "status",
        type: "string",
      },
    ];
  }
}

Update Controller Logic

// src/controllers/product.controller.ts
import { BaseController } from "@june24/core-aws";
import { IProduct } from "@/types/product.model";
import { IProductService } from "@/services/product.service/product.service.interface";
import { ServiceFactory } from "@/services/service.factory";

export class ProductController extends BaseController<IProductService> {
  constructor() {
    super(ServiceFactory.createProductService());
  }

  protected processCrudRequest(): Promise<any> {
    if (this.endpoint === "POST /product") {
      // Add custom validation
      this.validateRequiredFields(["name", "price", "category"], this.request?.body);
      return this.service.create(this.userId, this.request?.body);
    }
    if (this.endpoint === "GET /products") {
      return this.service.listItemsDB(this.request.filter);
    }
    if (this.endpoint === "GET /product/{id}") {
      return this.service.get(this.request.pathParameters?.id);
    }
    if (this.endpoint === "PUT /product/{id}") {
      return this.service.update(this.userId, this.request.pathParameters?.id, this.request?.body);
    }
    if (this.endpoint === "DELETE /product/{id}") {
      return this.service.delete(this.request.pathParameters?.id);
    }
    throw new Error("Method not implemented.");
  }

  protected processTriggerEvent(): Promise<any> {
    // Handle Cognito trigger events
    const event = this.request as any;

    switch (event.triggerSource) {
      case "PreSignUp_AdminCreateUser":
        return this.service.handlePreSignUp(event);
      case "PostConfirmation_ConfirmSignUp":
        return this.service.handlePostConfirmation(event);
      default:
        throw new Error(`Unsupported trigger source: ${event.triggerSource}`);
    }
  }
}

Step 5: Deploy

# Deploy to development
npm run deploy

# Deploy to production
npm run deploy:prod

# Run locally for development
npm run dev

🏭 Factory Pattern Usage

The framework uses factory patterns with caching for efficient instance management:

Repository Factory

import { RepositoryFactory } from "@/repositories/repository.factory";

// Get cached repository instance
const userRepo = RepositoryFactory.createUserRepo();
const productRepo = RepositoryFactory.createProductRepo();

// Check if repository exists in cache
if (RepositoryFactory.hasRepository("userRepo")) {
  console.log("User repository is cached");
}

// Clear cache
RepositoryFactory.clearCache();

Service Factory

import { ServiceFactory } from "@/services/service.factory";

// Get cached service instance
const userService = ServiceFactory.createUserService();
const productService = ServiceFactory.createProductService();

// Check if service exists in cache
if (ServiceFactory.hasService("userService")) {
  console.log("User service is cached");
}

Validation Factory

import { ValidationFactory } from "@/validation/validation.factory";

// Get validation for different operations
const createValidator = ValidationFactory.createUserCreateValidator();
const updateValidator = ValidationFactory.createUserUpdateValidator();
const searchValidator = ValidationFactory.createUserSearchValidator();

// Operation-based approach
const validator = ValidationFactory.getValidatorByOperation("create", "user");

Controller Factory

import { ControllerFactory } from "@/controllers/controller.factory";

// Get cached controller instance
const userController = ControllerFactory.createUserController();
const productController = ControllerFactory.createProductController();

// Entity-based approach
const controller = ControllerFactory.getControllerByEntity("user");

📋 TableConfig Configuration

Basic Setup

// configs/user.config.ts
import { TableConfig } from "@june24/core-aws";

const userTableConfig = new TableConfig();

// Configure table settings
userTableConfig.setConfig({
  partitionKey: "id",
  tableName: `Users-${process.env.ENV || "dev"}`,
  deletionPolicy: "Retain",
  billingMode: "PAY_PER_REQUEST",
  streamSpecification: {
    streamViewType: "NEW_AND_OLD_IMAGES",
  },
  pointInTimeRecovery: true,
  tags: {
    Environment: process.env.ENV || "dev",
    Service: "my-service",
    TableType: "users",
  },
});

// Add Global Secondary Indexes
userTableConfig.set("By_email", {
  partitionKeyField: "email",
  sourceFields: ["email"],
  sortKeyField: "createdAt",
});

userTableConfig.set("By_status", {
  partitionKeyField: "status",
  sourceFields: ["status"],
  sortKeyField: "updatedAt",
});

export default userTableConfig;

Advanced Configuration

// configs/product.config.ts
const productTableConfig = new TableConfig();

productTableConfig.setConfig({
  partitionKey: "id",
  tableName: `Products-${process.env.ENV || "dev"}`,
  deletionPolicy: "Retain",
  billingMode: "PROVISIONED", // For high-traffic tables
  streamSpecification: {
    streamViewType: "NEW_AND_OLD_IMAGES",
  },
  pointInTimeRecovery: true,
  tags: {
    Environment: process.env.ENV || "dev",
    Service: "my-service",
    TableType: "products",
  },
});

// Composite indexes
productTableConfig.set("By_Category_Status", {
  partitionKeyField: "category_status",
  sourceFields: ["category", "status"],
  compositeSeparator: "_",
  sortKeyField: "createdDate",
});

// Multiple sort keys
productTableConfig.set("By_Price_Range", {
  partitionKeyField: "priceRange",
  sourceFields: ["priceRange"],
  sortKeyField: "createdDate",
});

export default productTableConfig;

🔧 CLI Options

Create Project Options

npx @june24/core-aws create-project [options]

Options:
  --name <name>                    Project name (required)
  --output-folder <path>           Output folder (default: ./)
  --skip-repositories              Skip repository generation
  --skip-services                  Skip service generation
  --skip-controllers               Skip controller generation
  --skip-validation                Skip validation generation
  --skip-handlers                  Skip handler generation
  --skip-types                     Skip type generation
  --help, -h                       Show help

Add Table Options

npx @june24/core-aws add [options]

Options:
  --config <file>                  Table config file path (required)
  --name <name>                    Table name (required)
  --output-folder <path>           Output folder (default: ./)
  --replace                        Replace existing files
  --skip-repositories              Skip repository generation
  --skip-services                  Skip service generation
  --skip-controllers               Skip controller generation
  --skip-validation                Skip validation generation
  --skip-handlers                  Skip handler generation
  --skip-types                     Skip type generation
  --help, -h                       Show help

🚀 Examples

Complete Project Setup

# 1. Create new project
npx @june24/core-aws create-project --name ecommerce-api

# 2. Navigate to project
cd ecommerce-api

# 3. Install dependencies
npm install

# 4. Create table configs
# Create configs/user.config.ts, configs/product.config.ts, etc.

# 5. Add tables to project
npx @june24/core-aws add --config ./configs/user.config.ts --name user
npx @june24/core-aws add --config ./configs/product.config.ts --name product
npx @june24/core-aws add --config ./configs/order.config.ts --name order

# 6. Customize generated files
# Edit types, validation, controllers as needed

# 7. Deploy
npm run deploy

Custom Validation Example

// src/validation/user.validation.ts
import { ValidationRule, commonValidations } from "@june24/core-aws";

export class UserValidation {
  static getCreateValidationRules(): ValidationRule[] {
    return [
      commonValidations.required("id"),
      commonValidations.required("email"),
      commonValidations.email("email"),

      {
        field: "password",
        type: "string",
        minLength: 8,
        maxLength: 128,
        required: true,
        pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/,
      },

      {
        field: "age",
        type: "number",
        min: 13,
        max: 120,
        custom: (value) => {
          if (value && value < 13) {
            return "User must be at least 13 years old";
          }
          return true;
        },
      },
    ];
  }

  static getUpdateValidationRules(): ValidationRule[] {
    return [
      {
        field: "email",
        type: "string",
        email: true,
      },
      {
        field: "age",
        type: "number",
        min: 13,
        max: 120,
      },
    ];
  }

  static getSearchValidationRules(): ValidationRule[] {
    return [
      {
        field: "email",
        type: "string",
      },
      {
        field: "status",
        type: "string",
      },
    ];
  }
}

Custom Service Methods

// src/services/user.service/user.service.ts
import { BaseServiceImpl } from "@june24/core-aws";
import { IUser } from "@/types/user.model";
import { IUserRepoDB } from "@/repositories/dynamodb.repo/user.repo/user.repo.interface";
import { IUserService } from "./user.service.interface";
import { RepositoryFactory } from "@/repositories/repository.factory";

export class UserServiceImpl extends BaseServiceImpl<IUser, IUserRepoDB> implements IUserService {
  constructor() {
    super(RepositoryFactory.createUserRepo());
  }

  // Custom method
  async findByEmail(email: string): Promise<IUser | null> {
    const filter = { indexName: "By_email", indexValue: email };
    const result = await this.listItemsDB(filter);
    return result.items.length > 0 ? result.items[0] : null;
  }

  // Custom business logic
  async createUser(userData: Partial<IUser>): Promise<IUser> {
    // Add custom validation
    if (userData.email) {
      const existingUser = await this.findByEmail(userData.email);
      if (existingUser) {
        throw new Error("User with this email already exists");
      }
    }

    return await this.create(userData.createdBy || "system", userData);
  }

  // Handle Cognito triggers
  async handlePreSignUp(event: any): Promise<any> {
    // Custom pre-signup logic
    return { allow: true };
  }

  async handlePostConfirmation(event: any): Promise<any> {
    // Custom post-confirmation logic
    const userData = {
      id: event.request.userAttributes.sub,
      email: event.request.userAttributes.email,
      status: "active",
      createdBy: "cognito",
    };

    return await this.create("cognito", userData);
  }
}

Handler Examples

CRUD Handler

// src/handlers/crud/user.crud/index.ts
import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
import { ControllerFactory } from "@/controllers/controller.factory";

export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
  const controller = ControllerFactory.createUserController();
  return await controller.handleRequest(event);
};

Trigger Handler

// src/handlers/trigger/user.trigger/index.ts
import { PreSignUpTriggerEvent, PostConfirmationTriggerEvent } from "aws-lambda";
import { ControllerFactory } from "@/controllers/controller.factory";

export const handler = async (event: PreSignUpTriggerEvent | PostConfirmationTriggerEvent): Promise<any> => {
  const controller = ControllerFactory.createUserController();
  return await controller.handleTriggerEvent(event);
};

Stream Handler

// src/handlers/streamer/user.streamer/index.ts
import { DynamoDBStreamEvent } from "aws-lambda";
import { ControllerFactory } from "@/controllers/controller.factory";

export const handler = async (event: DynamoDBStreamEvent): Promise<void> => {
  const controller = ControllerFactory.createUserController();
  return await controller.handleStreamEvent(event);
};

📚 API Reference

Core Classes

  • BaseController<T, S> - Base controller with common functionality
  • BaseServiceImpl<T, D, S> - Base service with repository management
  • BaseRepoDBImpl<T> - DynamoDB repository implementation
  • ValidationUtil - Comprehensive validation system
  • TableConfig - DynamoDB table configuration

Factory Classes

  • RepositoryFactory - Repository instance management with caching
  • ServiceFactory - Service instance management with caching
  • ValidationFactory - Validation instance management with caching
  • ControllerFactory - Controller instance management with caching

CLI Commands

  • create-project - Create new project from examples
  • add - Add table configuration with complete structure
  • init - Initialize project from table configs (legacy)
  • generate - Generate serverless configurations (legacy)

🤝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🆘 Support

For support and questions: