Skip to content

✨Refactor: Make NoteBuilder immutable — return new builder instances instead of this #125

@jakub-k-slys

Description

@jakub-k-slys

🧩 Description

The current implementation of NoteBuilder uses a mutable fluent interface — each method (paragraph(), text(), bold(), etc.) returns this, mutating the builder in-place. This pattern can lead to:
• Hidden side effects between chains
• Inadvertent reuse of mutated builders
• Bugs caused by shared reference across multiple operations

To improve safety and predictability, we will refactor NoteBuilder to be immutable: every method call returns a new builder instance with updated internal state.

🎯 Goals
• Make NoteBuilder fully immutable
• Eliminate usage of this in return values
• Ensure every call (paragraph(), text(), bold(), etc.) returns a fresh builder with copied and updated state
• Maintain existing chainability and ergonomics
• Prevent accidental builder reuse across chains

✅ Example Before (mutable)

const builder = new NoteBuilder();
builder.paragraph().text("Hello").bold(" world");
const draft = builder.build(); // 🧨 Same builder reused

✅ Example After (immutable)

const draft = new NoteBuilder()
  .paragraph()
  .text("Hello")
  .bold(" world")
  .build(); // ✅ Each step produces a new builder

🛠️ Tasks
• Replace all return this statements with return new NoteBuilder({...updatedState})
• Use a shared internal state interface (e.g. NoteBuilderState) to manage propagation
• Update all internal helpers to operate on immutable copies
• Refactor .paragraph(), .text(), .bold(), .italic(), .bulletList(), .item(), .finish(), etc.
• Update all tests to avoid relying on shared builder reference
• Add regression tests for chained but diverging builder paths

💡 Design Considerations
• Prefer shallow copies for performance and simplicity
• Allow branching logic (e.g. copy a builder mid-chain for reuse):

const base = new NoteBuilder().paragraph().text("Shared ");
const a = base.bold("A");
const b = base.italic("B");

🏷️ Labels

refactor, immutability, api-safety, note-builder, breaking-change

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions