feat(lunatask): add builder pattern for requests

Amolith created

Fluent builders for: TaskBuilder, TaskUpdateBuilder, NoteBuilder,
JournalEntryBuilder, PersonBuilder, TimelineNoteBuilder.

Example: task := lunatask.NewTask("Call
mom").InArea(id).WithPriority(1).Build()

Assisted-by: Claude Sonnet 4 via Crush

Change summary

lunatask/builders.go | 304 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 304 insertions(+)

Detailed changes

lunatask/builders.go 🔗

@@ -0,0 +1,304 @@
+// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+package lunatask
+
+import "time"
+
+// TaskBuilder provides a fluent interface for constructing CreateTaskRequest.
+type TaskBuilder struct {
+	req CreateTaskRequest
+}
+
+// NewTask creates a new TaskBuilder with the required name field.
+func NewTask(name string) *TaskBuilder {
+	return &TaskBuilder{req: CreateTaskRequest{Name: name}}
+}
+
+// InArea sets the area ID for the task.
+func (b *TaskBuilder) InArea(areaID string) *TaskBuilder {
+	b.req.AreaID = &areaID
+	return b
+}
+
+// InGoal sets the goal ID for the task.
+func (b *TaskBuilder) InGoal(goalID string) *TaskBuilder {
+	b.req.GoalID = &goalID
+	return b
+}
+
+// WithNote sets the note/description for the task.
+func (b *TaskBuilder) WithNote(note string) *TaskBuilder {
+	b.req.Note = &note
+	return b
+}
+
+// WithStatus sets the task status (later, next, started, waiting, completed).
+func (b *TaskBuilder) WithStatus(status string) *TaskBuilder {
+	b.req.Status = &status
+	return b
+}
+
+// WithMotivation sets the motivation (must, should, want).
+func (b *TaskBuilder) WithMotivation(motivation string) *TaskBuilder {
+	b.req.Motivation = &motivation
+	return b
+}
+
+// WithEstimate sets the time estimate in minutes (0-720).
+func (b *TaskBuilder) WithEstimate(minutes int) *TaskBuilder {
+	b.req.Estimate = &minutes
+	return b
+}
+
+// WithPriority sets the priority (-2 to 2: lowest, low, neutral, high, highest).
+func (b *TaskBuilder) WithPriority(priority int) *TaskBuilder {
+	b.req.Priority = &priority
+	return b
+}
+
+// WithEisenhower sets the Eisenhower matrix category (0-4).
+func (b *TaskBuilder) WithEisenhower(eisenhower int) *TaskBuilder {
+	b.req.Eisenhower = &eisenhower
+	return b
+}
+
+// ScheduledOn sets the scheduled date for the task.
+func (b *TaskBuilder) ScheduledOn(date Date) *TaskBuilder {
+	b.req.ScheduledOn = &date
+	return b
+}
+
+// CompletedAt sets the completion timestamp.
+func (b *TaskBuilder) CompletedAt(t time.Time) *TaskBuilder {
+	b.req.CompletedAt = &t
+	return b
+}
+
+// FromSource sets the external source integration.
+func (b *TaskBuilder) FromSource(source, sourceID string) *TaskBuilder {
+	b.req.Source = &source
+	b.req.SourceID = &sourceID
+	return b
+}
+
+// Build returns the constructed CreateTaskRequest.
+func (b *TaskBuilder) Build() *CreateTaskRequest {
+	return &b.req
+}
+
+// TaskUpdateBuilder provides a fluent interface for constructing UpdateTaskRequest.
+type TaskUpdateBuilder struct {
+	req UpdateTaskRequest
+}
+
+// NewTaskUpdate creates a new TaskUpdateBuilder.
+func NewTaskUpdate() *TaskUpdateBuilder {
+	return &TaskUpdateBuilder{}
+}
+
+// Name sets the task name.
+func (b *TaskUpdateBuilder) Name(name string) *TaskUpdateBuilder {
+	b.req.Name = &name
+	return b
+}
+
+// InArea sets the area ID for the task.
+func (b *TaskUpdateBuilder) InArea(areaID string) *TaskUpdateBuilder {
+	b.req.AreaID = &areaID
+	return b
+}
+
+// InGoal sets the goal ID for the task.
+func (b *TaskUpdateBuilder) InGoal(goalID string) *TaskUpdateBuilder {
+	b.req.GoalID = &goalID
+	return b
+}
+
+// WithNote sets the note/description for the task.
+func (b *TaskUpdateBuilder) WithNote(note string) *TaskUpdateBuilder {
+	b.req.Note = &note
+	return b
+}
+
+// WithStatus sets the task status (later, next, started, waiting, completed).
+func (b *TaskUpdateBuilder) WithStatus(status string) *TaskUpdateBuilder {
+	b.req.Status = &status
+	return b
+}
+
+// WithMotivation sets the motivation (must, should, want).
+func (b *TaskUpdateBuilder) WithMotivation(motivation string) *TaskUpdateBuilder {
+	b.req.Motivation = &motivation
+	return b
+}
+
+// WithEstimate sets the time estimate in minutes (0-720).
+func (b *TaskUpdateBuilder) WithEstimate(minutes int) *TaskUpdateBuilder {
+	b.req.Estimate = &minutes
+	return b
+}
+
+// WithPriority sets the priority (-2 to 2: lowest, low, neutral, high, highest).
+func (b *TaskUpdateBuilder) WithPriority(priority int) *TaskUpdateBuilder {
+	b.req.Priority = &priority
+	return b
+}
+
+// WithEisenhower sets the Eisenhower matrix category (0-4).
+func (b *TaskUpdateBuilder) WithEisenhower(eisenhower int) *TaskUpdateBuilder {
+	b.req.Eisenhower = &eisenhower
+	return b
+}
+
+// ScheduledOn sets the scheduled date for the task.
+func (b *TaskUpdateBuilder) ScheduledOn(date Date) *TaskUpdateBuilder {
+	b.req.ScheduledOn = &date
+	return b
+}
+
+// CompletedAt sets the completion timestamp.
+func (b *TaskUpdateBuilder) CompletedAt(t time.Time) *TaskUpdateBuilder {
+	b.req.CompletedAt = &t
+	return b
+}
+
+// Build returns the constructed UpdateTaskRequest.
+func (b *TaskUpdateBuilder) Build() *UpdateTaskRequest {
+	return &b.req
+}
+
+// NoteBuilder provides a fluent interface for constructing CreateNoteRequest.
+type NoteBuilder struct {
+	req CreateNoteRequest
+}
+
+// NewNote creates a new NoteBuilder.
+func NewNote() *NoteBuilder {
+	return &NoteBuilder{}
+}
+
+// WithName sets the note name/title.
+func (b *NoteBuilder) WithName(name string) *NoteBuilder {
+	b.req.Name = &name
+	return b
+}
+
+// WithContent sets the note content.
+func (b *NoteBuilder) WithContent(content string) *NoteBuilder {
+	b.req.Content = &content
+	return b
+}
+
+// InNotebook sets the notebook ID.
+func (b *NoteBuilder) InNotebook(notebookID string) *NoteBuilder {
+	b.req.NotebookID = &notebookID
+	return b
+}
+
+// FromSource sets the external source integration.
+func (b *NoteBuilder) FromSource(source, sourceID string) *NoteBuilder {
+	b.req.Source = &source
+	b.req.SourceID = &sourceID
+	return b
+}
+
+// Build returns the constructed CreateNoteRequest.
+func (b *NoteBuilder) Build() *CreateNoteRequest {
+	return &b.req
+}
+
+// JournalEntryBuilder provides a fluent interface for constructing CreateJournalEntryRequest.
+type JournalEntryBuilder struct {
+	req CreateJournalEntryRequest
+}
+
+// NewJournalEntry creates a new JournalEntryBuilder with the required date.
+func NewJournalEntry(date Date) *JournalEntryBuilder {
+	return &JournalEntryBuilder{req: CreateJournalEntryRequest{DateOn: date}}
+}
+
+// WithName sets the entry title (defaults to weekday name if omitted).
+func (b *JournalEntryBuilder) WithName(name string) *JournalEntryBuilder {
+	b.req.Name = &name
+	return b
+}
+
+// WithContent sets the Markdown content.
+func (b *JournalEntryBuilder) WithContent(content string) *JournalEntryBuilder {
+	b.req.Content = &content
+	return b
+}
+
+// Build returns the constructed CreateJournalEntryRequest.
+func (b *JournalEntryBuilder) Build() *CreateJournalEntryRequest {
+	return &b.req
+}
+
+// PersonBuilder provides a fluent interface for constructing CreatePersonRequest.
+type PersonBuilder struct {
+	req CreatePersonRequest
+}
+
+// NewPerson creates a new PersonBuilder.
+func NewPerson() *PersonBuilder {
+	return &PersonBuilder{}
+}
+
+// WithFirstName sets the person's first name.
+func (b *PersonBuilder) WithFirstName(name string) *PersonBuilder {
+	b.req.FirstName = &name
+	return b
+}
+
+// WithLastName sets the person's last name.
+func (b *PersonBuilder) WithLastName(name string) *PersonBuilder {
+	b.req.LastName = &name
+	return b
+}
+
+// WithRelationshipStrength sets the relationship strength category.
+func (b *PersonBuilder) WithRelationshipStrength(strength string) *PersonBuilder {
+	b.req.RelationshipStrength = &strength
+	return b
+}
+
+// FromSource sets the external source integration.
+func (b *PersonBuilder) FromSource(source, sourceID string) *PersonBuilder {
+	b.req.Source = &source
+	b.req.SourceID = &sourceID
+	return b
+}
+
+// Build returns the constructed CreatePersonRequest.
+func (b *PersonBuilder) Build() *CreatePersonRequest {
+	return &b.req
+}
+
+// TimelineNoteBuilder provides a fluent interface for constructing CreatePersonTimelineNoteRequest.
+type TimelineNoteBuilder struct {
+	req CreatePersonTimelineNoteRequest
+}
+
+// NewTimelineNote creates a new TimelineNoteBuilder with the required person ID.
+func NewTimelineNote(personID string) *TimelineNoteBuilder {
+	return &TimelineNoteBuilder{req: CreatePersonTimelineNoteRequest{PersonID: personID}}
+}
+
+// OnDate sets the date for the timeline note.
+func (b *TimelineNoteBuilder) OnDate(date Date) *TimelineNoteBuilder {
+	b.req.DateOn = &date
+	return b
+}
+
+// WithContent sets the Markdown content.
+func (b *TimelineNoteBuilder) WithContent(content string) *TimelineNoteBuilder {
+	b.req.Content = &content
+	return b
+}
+
+// Build returns the constructed CreatePersonTimelineNoteRequest.
+func (b *TimelineNoteBuilder) Build() *CreatePersonTimelineNoteRequest {
+	return &b.req
+}