
Research
/Security News
Weaponizing Discord for Command and Control Across npm, PyPI, and RubyGems.org
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
@piggly/ddd-toolkit
Advanced tools
A bunch of tools to use Model-Driven Design and Domain-Driven Design architecture in a back-end application.
An ESM/CommonJS toolkit providing comprehensive Domain-Driven Design patterns and building blocks for NodeJS applications. This library offers a complete implementation of DDD tactical patterns including Entities, Value Objects, Attributes, Domain Events, Repositories with Unit of Work, and more.
npm install @piggly/ddd-toolkit
import { Entity, UUIDEntityId } from '@piggly/ddd-toolkit';
interface UserProps {
name: string;
email: string;
}
class User extends Entity<UserProps, UUIDEntityId> {
public static create(props: UserProps): User {
const id = UUIDEntityId.generate();
return new User(props, id);
}
get name(): string {
return this.props.name;
}
get email(): string {
return this.props.email;
}
}
import { ValueObject } from '@piggly/ddd-toolkit';
interface EmailProps {
value: string;
}
class EmailValueObject extends ValueObject<EmailProps> {
public static create(email: string): Result<Email> {
if (!this.isValid(email)) {
return Result.fail(new Error('Invalid email'));
}
return Result.ok(new Email({ value: email }));
}
private static isValid(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
get value(): string {
return this.props.value;
}
}
import { Attribute } from '@piggly/ddd-toolkit';
interface EmailProps {
value: string;
}
class EmailAttribute extends Attribute<EmailProps> {
public static create(email: string): Result<Email> {
if (!this.isValid(email)) {
return Result.fail(new Error('Invalid email'));
}
return Result.ok(new Email({ value: email }));
}
private static isValid(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
public change(email: string): Result<Email> {
if (!this.isValid(email)) {
return Result.fail(new Error('Invalid email'));
}
this.props.value = email;
this.markAsModified();
return Result.ok(this);
}
get value(): string {
return this.props.value;
}
}
import {
AbstractRelationalRepository,
IUnitOfWork,
RepositoryProvider
} from '@piggly/ddd-toolkit';
class UserRepository extends AbstractRelationalRepository<User> {
async findByEmail(email: string): Promise<User | undefined> {
// Implementation
}
}
// Using with Unit of Work
const provider = new RepositoryProvider();
provider.register('users', UserRepository);
await provider.transaction(async (uow: IUnitOfWork) => {
const userRepo = uow.getRepository<UserRepository>('users');
const user = await userRepo.findById(id);
// Operations within transaction
});
import { Result } from '@piggly/ddd-toolkit';
const result = await Result.ok({ id: 1, name: 'John' })
.map(user => ({ ...user, processed: true }))
.chain(async user => validateUser(user))
.tap(user => console.log('User processed:', user))
.mapError(error => new CustomError(error));
if (result.isFailure()) {
console.error('Error:', result.error);
} else {
console.log('Success:', result.value());
}
import { DomainEvent, EventEmitter } from '@piggly/ddd-toolkit';
interface UserCreatedPayload {
userId: string;
email: string;
}
class UserCreatedEvent extends DomainEvent<UserCreatedPayload> {
constructor(payload: UserCreatedPayload) {
super('UserCreated', payload);
}
}
// In your entity
class User extends Entity<UserProps, UUIDEntityId> {
public static create(props: UserProps): User {
const user = new User(props, UUIDEntityId.generate());
user.emit(new UserCreatedEvent({
userId: user.id.value,
email: props.email
}));
return user;
}
}
The library provides three types of entity IDs:
UUIDEntityId
- UUID v4 based identifiers;StringEntityId
- String-based identifiers;NumberEntityId
- Numeric identifiers.Specialized collection classes for managing domain objects:
CollectionOfEntity
- Manages entity collections;CollectionOfValueObjects
- Manages value object collections;CollectionOfAttributes
- Manages attribute collections.Different service types for proper separation of concerns:
Service
- Base service class;DomainService
- Domain layer services;ApplicationService
- Application layer services;InfraService
- Infrastructure layer services.Comprehensive error system with domain-specific errors:
DomainError
- Base domain error;BusinessRuleViolationError
- Business rule violations;RuntimeError
- Runtime errors;ApplicationError
- Application layer errors.This library uses Jest for testing. Run tests with:
# Run tests once
npm run test:once
# Run tests in watch mode
npm run test
# Run tests with coverage
npm run test:coverage
# Full build
npm run build
# Type checking
npm run check
# Linting
npm run lint
# Format code
npm run format
src/
├── core/
│ ├── entities/ # Entity classes and collections
│ ├── vos/ # Value objects and collections
│ ├── repositories/ # Repository pattern implementation
│ ├── services/ # Service layer classes
│ ├── application/ # Application layer components
│ ├── errors/ # Error classes
│ └── deprecated/ # Deprecated features
├── utils/ # Utility functions
└── index.ts # Main exports
Version 5.0 introduces breaking changes. Key migration points:
Entity
and Attribute
;StringEntityId
, NumberEntityId
, UUIDEntityId
);Set
internally instead of Map
.See CHANGELOG.md for detailed migration notes.
See the CHANGELOG file for information about all code changes.
See the CONTRIBUTING file for information before submitting your contribution.
MIT License (MIT). See LICENSE.
5.1.2 at 2025-09-24
get
method of RelationalRepositoryBundle
now has a flag to allow get repository without checking if the UoW is active.FAQs
A bunch of tools to use Model-Driven Design and Domain-Driven Design architecture in a back-end application.
The npm package @piggly/ddd-toolkit receives a total of 48 weekly downloads. As such, @piggly/ddd-toolkit popularity was classified as not popular.
We found that @piggly/ddd-toolkit demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
Security News
Socket now integrates with Bun 1.3’s Security Scanner API to block risky packages at install time and enforce your organization’s policies in local dev and CI.
Research
The Socket Threat Research Team is tracking weekly intrusions into the npm registry that follow a repeatable adversarial playbook used by North Korean state-sponsored actors.