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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sisques-labs/core

v1.1.0

Published

Core library with common interfaces, DTOs, and domain patterns

Readme

@sisques-labs/core

A framework-agnostic TypeScript library providing common domain patterns, interfaces, and utilities for building microservices following Domain-Driven Design (DDD) principles.

What is this?

@sisques-labs/core is a foundational library designed to standardize development patterns across microservices. It provides a comprehensive set of abstractions, interfaces, and base classes that enable consistent implementation of domain-driven design patterns without coupling your code to any specific framework (like NestJS, Express, etc.).

Purpose

This library serves as the shared foundation for all microservices, providing:

  • Consistency: Standardized patterns and interfaces across all services
  • Flexibility: Framework-agnostic design allows you to use any backend framework
  • Reusability: Common domain patterns, value objects, and utilities
  • Type Safety: Full TypeScript support with comprehensive type definitions
  • Maintainability: Centralized core logic that can be updated across all services

Key Features

🏗️ Domain Layer

Interfaces & Patterns

  • Builder patterns (IBuilder, IReadBuilder, IWriteBuilder)
  • Factory patterns (IReadFactory, IWriteFactory)
  • Repository patterns (IBaseReadRepository, IBaseWriteRepository)
  • DTOs for aggregates and view models

Event System

  • Domain events (IDomainEvent) for within bounded context communication
  • Integration events (BaseEvent) for cross-bounded context communication
  • Event publishers with abstraction for different transport mechanisms

Value Objects

  • Common value objects: UuidValueObject, DateValueObject, EmailValueObject, PhoneValueObject, etc.
  • Type-safe validation and encapsulation
  • Comprehensive exception handling

Domain Entities

  • Criteria for complex queries with filters, sorting, and pagination
  • PaginatedResult for paginated responses

🎯 Application Layer

Services

  • IBaseService interface for application services
  • PublishIntegrationEventsService for publishing integration events
  • PublishDomainEventsService for publishing domain events

Command Handlers

  • IBaseCommandHandler interface
  • BaseUpdateCommandHandler with utilities for extracting update data

Sagas

  • IBaseSaga interface for orchestrating distributed transactions
  • ISagaStepConfig for saga step configuration

DTOs

  • Command DTOs like IBaseFieldChangedCommandDto

🔧 Infrastructure Layer

Repositories

  • BaseDatabaseRepository with common utilities (pagination calculation, etc.)

Exceptions

  • Layered exception hierarchy (Domain, Application, Infrastructure)

Installation

# Using pnpm (recommended)
pnpm add @sisques-labs/core

# Using npm
npm install @sisques-labs/core

# Using yarn
yarn add @sisques-labs/core

Usage Examples

Value Objects

import {
	UuidValueObject,
	DateValueObject,
	EmailValueObject,
} from '@sisques-labs/core';

// Create a UUID
const userId = new UuidValueObject();
const existingId = new UuidValueObject('123e4567-e89b-12d3-a456-426614174000');

// Create a date
const createdAt = new DateValueObject();
const specificDate = new DateValueObject(new Date('2024-01-01'));

// Create an email with validation
const email = new EmailValueObject('[email protected]');

Builders

import { IReadBuilder, IWriteBuilder } from '@sisques-labs/core';

// Read Builder for View Models
class UserViewModelBuilder implements IReadBuilder<
	UserViewModel,
	UserPrimitives
> {
	private viewModel: Partial<UserViewModel> = {};

	withId(id: string): this {
		this.viewModel.id = id;
		return this;
	}

	withName(name: string): this {
		this.viewModel.name = name;
		return this;
	}

	fromPrimitives(primitives: UserPrimitives): this {
		this.viewModel = { ...primitives };
		return this;
	}

	build(): UserViewModel {
		return this.viewModel as UserViewModel;
	}

	reset(): this {
		this.viewModel = {};
		return this;
	}
}

// Write Builder for Aggregates
class UserAggregateBuilder implements IWriteBuilder<
	UserAggregate,
	UserPrimitives
> {
	// Similar implementation for domain aggregates
}

Repositories

import {
	IBaseReadRepository,
	IBaseWriteRepository,
	Criteria,
	PaginatedResult,
} from '@sisques-labs/core';

// Read Repository
class UserReadRepository implements IBaseReadRepository<UserViewModel> {
	async findById(id: string): Promise<UserViewModel | null> {
		// Implementation
	}

	async findByCriteria(
		criteria: Criteria,
	): Promise<PaginatedResult<UserViewModel>> {
		// Implementation with filters, sorting, pagination
	}

	async save(viewModel: UserViewModel): Promise<void> {
		// Implementation
	}

	async delete(id: string): Promise<void> {
		// Implementation
	}
}

// Write Repository
class UserWriteRepository implements IBaseWriteRepository<UserAggregate> {
	async findById(id: string): Promise<UserAggregate | null> {
		// Implementation
	}

	async save(entity: UserAggregate): Promise<UserAggregate> {
		// Implementation
	}

	async delete(id: string): Promise<void> {
		// Implementation
	}
}

Events

import {
	BaseEvent,
	IDomainEvent,
	IEventMetadata,
	IBaseEventData,
	IIntegrationEventPublisher,
} from '@sisques-labs/core';

// Integration Event (cross-bounded context)
interface UserCreatedEventData extends IBaseEventData {
	userId: string;
	userName: string;
	email: string;
}

class UserCreatedEvent extends BaseEvent<UserCreatedEventData> {
	constructor(metadata: IEventMetadata, data: UserCreatedEventData) {
		super(metadata, data);
	}
}

// Domain Event (within bounded context)
const userRegisteredEvent: IDomainEvent<{ userId: string }> = {
	eventType: 'UserRegistered',
	data: { userId: '123' },
	occurredOn: new Date(),
};

Application Services

import {
	IBaseService,
	PublishIntegrationEventsService,
} from '@sisques-labs/core';

// Implement a service
class CreateUserService implements IBaseService<CreateUserCommand, User> {
	constructor(
		private userRepository: IBaseWriteRepository<User>,
		private eventPublisher: PublishIntegrationEventsService,
	) {}

	async execute(command: CreateUserCommand): Promise<User> {
		const user = User.create(command);
		await this.userRepository.save(user);

		// Publish integration event
		const event = new UserCreatedEvent(metadata, eventData);
		await this.eventPublisher.execute(event);

		return user;
	}
}

Command Handlers

import { BaseUpdateCommandHandler } from '@sisques-labs/core';

class UpdateUserHandler extends BaseUpdateCommandHandler<
	UpdateUserCommand,
	UserUpdateDto
> {
	async handle(command: UpdateUserCommand) {
		// Extract update data, excluding 'id' field
		const updateData = this.extractUpdateData(command, ['id']);

		// Or with transformation
		const transformedData = this.extractUpdateDataWithTransform(
			command,
			(data) => ({ ...data, updatedAt: new Date() }),
			['id'],
		);

		// Use updateData to update the entity
	}
}

Database Repositories

import { BaseDatabaseRepository, Criteria } from '@sisques-labs/core';

class UserRepository extends BaseDatabaseRepository {
	async findByCriteria(criteria: Criteria) {
		// Use built-in pagination utility
		const { page, limit, skip } = this.calculatePagination(criteria);

		// Apply filters, sorting, and pagination
		// Implementation with your database client
	}
}

Querying with Criteria

import {
	Criteria,
	FilterOperator,
	SortDirection,
} from '@sisques-labs/core';

const criteria = new Criteria(
	[
		{
			field: 'email',
			operator: FilterOperator.EQUALS,
			value: '[email protected]',
		},
		{ field: 'age', operator: FilterOperator.GREATER_THAN, value: 18 },
	],
	[{ field: 'createdAt', direction: SortDirection.DESC }],
	{ page: 1, perPage: 20 },
);

const result = await userRepository.findByCriteria(criteria);
// result.items - array of users
// result.total - total count
// result.page - current page
// result.perPage - items per page
// result.totalPages - calculated total pages

Architecture

This library follows Domain-Driven Design (DDD) principles with a clear separation of concerns:

src/
├── domain/              # Domain Layer - Business Logic
│   ├── interfaces/       # Domain contracts and interfaces
│   ├── entities/         # Domain entities (Criteria, PaginatedResult)
│   ├── events/          # Event classes (BaseEvent)
│   ├── enums/           # Domain enumerations
│   ├── exceptions/      # Domain-specific exceptions
│   └── value-objects/   # Value objects with validation
│
├── application/         # Application Layer - Use Cases
│   ├── interfaces/      # Service and handler interfaces
│   ├── services/        # Application services
│   ├── commands/        # Command handlers
│   ├── sagas/           # Saga orchestration
│   ├── dtos/            # Data transfer objects
│   └── exceptions/      # Application exceptions
│
├── infrastructure/      # Infrastructure Layer - Technical Details
│   ├── database/        # Database abstractions
│   └── exceptions/      # Infrastructure exceptions
│
└── index.ts             # Main export file

Framework Agnostic

This library is designed to work with any backend framework:

  • ✅ NestJS
  • ✅ Express
  • ✅ Fastify
  • ✅ Koa
  • ✅ Custom frameworks

The interfaces and abstractions allow you to implement the patterns using your preferred framework while maintaining consistency across all services.

TypeScript Support

Full TypeScript support with:

  • Comprehensive type definitions
  • Generic types for flexibility
  • Strict type checking
  • IntelliSense support

Development

# Install dependencies
pnpm install

# Build the library
pnpm build

# Watch mode for development
pnpm build:watch

# Run linter
pnpm lint

# Fix linting issues automatically
pnpm lint:fix

# Format code with Prettier
pnpm format

# Check code formatting
pnpm format:check

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Run tests with coverage
pnpm test:coverage

# Clean build artifacts
pnpm clean

Code Quality

This project uses ESLint and Prettier to maintain code quality and consistency.

Linting

# Check for linting issues
pnpm lint

# Automatically fix linting issues
pnpm lint:fix

The project uses ESLint with TypeScript support and Prettier integration. Configuration can be found in eslint.config.mjs.

Formatting

# Format all code
pnpm format

# Check if code is formatted correctly
pnpm format:check

Prettier configuration is defined in .prettierrc and follows the project's coding standards.

Testing

This library uses Jest for unit testing. All value objects, entities, and core classes have comprehensive test coverage.

# Run all tests
pnpm test

# Run tests in watch mode (useful during development)
pnpm test:watch

# Generate coverage report
pnpm test:coverage

Test files follow the naming convention *.spec.ts and are located alongside the source files.

Git Hooks

This project uses Husky to run Git hooks that ensure code quality before commits.

Pre-commit Hook

Before each commit, the following checks are automatically performed:

  1. Linting & Formatting: All staged files are automatically linted and formatted using ESLint and Prettier
  2. Tests: All unit tests are executed to ensure nothing is broken

If any of these checks fail, the commit will be aborted. This ensures that only properly formatted and tested code enters the repository.

Bypassing Hooks (Not Recommended)

If you need to bypass the hooks in an emergency (not recommended), you can use:

git commit --no-verify

However, this should only be used in exceptional circumstances.

Versioning and Releases

This project uses Semantic Release for automated versioning and publishing. The version is automatically determined based on commit messages following the Conventional Commits specification.

Commit Message Format

Commit messages must follow the Conventional Commits format:

<type>(<scope>): <subject>

<body>

<footer>

Types:

  • feat: A new feature (triggers a minor version bump)
  • fix: A bug fix (triggers a patch version bump)
  • docs: Documentation only changes
  • style: Code style changes (formatting, etc.)
  • refactor: Code refactoring
  • perf: Performance improvements
  • test: Adding or updating tests
  • chore: Maintenance tasks
  • BREAKING CHANGE: Breaking changes (triggers a major version bump)

Examples:

feat: add new value object for phone numbers
fix: correct UUID validation regex
feat(domain): add new repository interface

BREAKING CHANGE: change API signature for builders

Release Process

  1. Automatic Release: When code is pushed to the main branch, semantic-release:

    • Analyzes commits since the last release
    • Determines the next version number
    • Generates release notes
    • Updates CHANGELOG.md
    • Creates a Git tag
    • Publishes to npm (if configured)
    • Creates a GitHub release
  2. Manual Release: You can also run semantic-release manually:

    pnpm release

Configuration

Semantic-release configuration is in .releaserc.json. The release process requires:

  • GITHUB_TOKEN: Automatically provided by GitHub Actions
  • NPM_TOKEN: Required for publishing to npm (set in repository secrets)

Contributing

This is an internal library. For contributions, please follow the project's contribution guidelines.

Important: When contributing, ensure your commit messages follow the Conventional Commits format to enable proper automatic versioning.

License

MIT © Sisques Labs