bamboots
v1.1.0
Published
Lombok-like decorators for TypeScript - reduce boilerplate code with @Data, @Builder, @Getter, @Setter and more
Downloads
14
Maintainers
Readme
Bamboots
Bamboots is a Lombok-inspired library for TypeScript that eliminates boilerplate code using decorators. Reduce repetitive code patterns and boost productivity with minimal effort.
Installation
npm install bambootsFeatures
- @Getter / @Setter - Automatic getter and setter generation
- @Data - All-in-one decorator combining getters, setters, toString, equals, and hashCode
- @Value - Immutable data classes with getters only
- @ToString - Human-readable string representation
- @EqualsAndHashCode - Object comparison and hashing
- @Builder - Fluent builder pattern implementation
- @AllArgsConstructor / @NoArgsConstructor - Factory methods for object creation
- @Accessors - Customizable accessor methods with fluent mode
Quick Start
import { Data, Builder, asDataInstance, withBuilderStatic } from 'bamboots';
@Data()
@Builder()
class User {
name: string = '';
age: number = 0;
email: string = '';
}
// Using the builder pattern (typed)
const UserWithBuilder = withBuilderStatic(User);
const user = asDataInstance(
UserWithBuilder.builder()
.name('John Doe')
.age(30)
.email('[email protected]')
.build()
);
// Using generated methods
console.log(user.getName()); // 'John Doe'
console.log(user.toString()); // 'User(name="John Doe", age=30, email="[email protected]")'
// Fluent setters with method chaining
user.setName('Jane').setAge(25);Decorators
@Getter
Generates a getter method for a property.
import { Getter, asGetterInstance } from 'bamboots';
class User {
@Getter
private _name: string = 'John';
}
const user = asGetterInstance(new User());
console.log(user.getName()); // 'John'@Setter
Generates a setter method for a property with method chaining support.
import { Setter, asSetterInstance } from 'bamboots';
class User {
@Setter
private _name: string = '';
@Setter
private _age: number = 0;
}
const user = asSetterInstance(new User());
user.setName('John').setAge(30); // Method chaining@Data
The ultimate convenience decorator - combines @Getter, @Setter, @ToString, and @EqualsAndHashCode.
import { Data, asDataInstance } from 'bamboots';
@Data()
class User {
name: string = '';
age: number = 0;
}
const user1 = asDataInstance(new User());
user1.setName('John').setAge(30);
const user2 = asDataInstance(new User());
user2.setName('John').setAge(30);
console.log(user1.equals(user2)); // true
console.log(user1.hashCode() === user2.hashCode()); // true
console.log(user1.toString()); // 'User(name="John", age=30)'Options:
@Data({
toStringOptions: { exclude: ['password'] },
equalsAndHashCode: { exclude: ['timestamp'] },
getters: true,
setters: true
})
class User {
name: string = '';
password: string = '';
timestamp: number = Date.now();
}@Value
Creates an immutable data class (getters only, no setters).
import { Value, asValueInstance } from 'bamboots';
@Value()
class Point {
x: number = 0;
y: number = 0;
}
const point = asValueInstance(new Point());
console.log(point.getX()); // Works
// point.setX(5); // Error - no setter available@ToString
Generates a toString() method for human-readable output.
import { ToString } from 'bamboots';
@ToString()
class User {
name: string = 'John';
age: number = 30;
}
const user = new User();
console.log(user.toString()); // 'User(name="John", age=30)'Options:
@ToString({
includeClassName: false, // Omit class name
exclude: ['password'], // Exclude specific properties
include: ['name', 'email'], // Only include specific properties
separator: ' | ' // Custom separator
})@EqualsAndHashCode
Generates equals() and hashCode() methods for object comparison.
import { EqualsAndHashCode, asEqualityInstance } from 'bamboots';
@EqualsAndHashCode()
class User {
name: string = 'John';
age: number = 30;
}
const user1 = asEqualityInstance(new User());
const user2 = asEqualityInstance(new User());
console.log(user1.equals(user2)); // true
console.log(user1.hashCode() === user2.hashCode()); // trueOptions:
@EqualsAndHashCode({
exclude: ['timestamp'], // Exclude from comparison
include: ['id'], // Only compare these fields
callSuper: true // Include parent class in comparison
})@Builder
Implements the builder pattern for fluent object construction.
import { Builder, withBuilderStatic } from 'bamboots';
@Builder()
class User {
name: string = '';
age: number = 0;
email: string = '';
}
const UserWithBuilder = withBuilderStatic(User);
const user = UserWithBuilder.builder()
.name('John')
.age(30)
.email('[email protected]')
.build();Options:
@Builder({
builderMethodName: 'create', // Custom static method name
buildMethodName: 'make', // Custom build method name
setterPrefix: 'with' // Add prefix to setter methods
})
// Usage: User.create().withName('John').make();@AllArgsConstructor
Adds a static of() method that accepts all properties as arguments.
import { AllArgsConstructor, withOfStatic } from 'bamboots';
@AllArgsConstructor()
class User {
name: string = '';
age: number = 0;
}
const user = withOfStatic(User).of('John', 30);
console.log(user.name); // 'John'
console.log(user.age); // 30@NoArgsConstructor
Adds a static create() method for creating instances.
import { NoArgsConstructor, withCreateStatic } from 'bamboots';
@NoArgsConstructor()
class User {
name: string = 'Guest';
age: number = 0;
}
const user = withCreateStatic(User).create();
console.log(user.name); // 'Guest'@Accessors
Customizable accessor methods with fluent mode support.
import { Accessors, asFluentAccessorsInstance, asPrefixedAccessorsInstance } from 'bamboots';
// Traditional mode with custom prefixes
@Accessors({ getterPrefix: 'fetch', setterPrefix: 'update' })
class User {
name: string = 'John';
}
const user = asPrefixedAccessorsInstance(new User(), 'fetch', 'update');
console.log(user.fetchName()); // 'John'
user.updateName('Jane');
// Fluent mode - single method acts as both getter and setter
@Accessors({ fluent: true, chain: true })
class Point {
x: number = 0;
y: number = 0;
}
const point = asFluentAccessorsInstance(new Point());
point.x(10).y(20); // Setter with chaining
console.log(point.x()); // 10 - Getter (no args)Utility Functions
createBuilder
Create a builder for any class without using a decorator.
import { createBuilder } from 'bamboots';
class User {
name: string = '';
age: number = 0;
}
const user = createBuilder(User)
.name('John')
.age(30)
.build();factory
Create a factory function for any class.
import { factory } from 'bamboots';
class User {
name: string = '';
age: number = 0;
}
const createUser = factory(User);
const user = createUser('John', 30);TypeScript Configuration
Make sure your tsconfig.json has decorators enabled:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}Examples
Check out the examples directory for practical usage examples:
| Example | Description | |---------|-------------| | basic-usage.ts | Getting started with @Data | | builder-pattern.ts | Fluent object construction | | immutable-objects.ts | Immutable classes with @Value | | tostring-options.ts | Customizing toString output | | equals-hashcode.ts | Object comparison and hashing | | fluent-accessors.ts | Custom accessor methods | | constructors.ts | Factory methods | | real-world-ecommerce.ts | E-commerce domain model |
Run examples with:
npx ts-node examples/basic-usage.tsContributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see the LICENSE file for details.
