notes

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoteNotFound = errors.New("note not found")
	ErrConflict     = errors.New("conflict: server version is newer")
)

Functions

This section is empty.

Types

type Note

type Note struct {
	ID               uuid.UUID `gorm:"column:note_id;primaryKey;type:uuid"`
	UserID           uuid.UUID `gorm:"column:user_id;type:uuid;not null;index:idx_user_updated,priority:1"`
	EncryptedPayload []byte    `gorm:"column:encrypted_payload;type:bytea;not null"`
	CreatedAt        time.Time `gorm:"autoCreateTime"`
	UpdatedAt        time.Time `gorm:"autoUpdateTime;index:idx_user_updated,priority:2"`
}

type NoteCursor

type NoteCursor struct {
	AfterUpdatedAt time.Time `json:"updated_at"`
	AfterNoteID    uuid.UUID `json:"note_id"`
}

NoteCursor is the position marker for cursor-based pagination of notes, ordered by (updated_at ASC, note_id ASC).

type NoteResponse

type NoteResponse struct {
	NoteID           uuid.UUID  `json:"note_id"`
	EncryptedPayload string     `json:"encrypted_payload"`
	CreatedAt        *time.Time `json:"created_at"`
	UpdatedAt        *time.Time `json:"updated_at"`
}

type NoteTombstone

type NoteTombstone struct {
	NoteID    uuid.UUID `gorm:"column:note_id;primaryKey;type:uuid"`
	UserID    uuid.UUID `gorm:"column:user_id;type:uuid;not null;index"`
	DeletedAt time.Time `gorm:"not null"`
}

type NotesHandler

type NotesHandler struct {
	// contains filtered or unexported fields
}

func NewNotesHandler

func NewNotesHandler(service service) *NotesHandler

func (*NotesHandler) Delete

func (h *NotesHandler) Delete(c *echo.Context) error

func (*NotesHandler) GetAll

func (h *NotesHandler) GetAll(c *echo.Context) error

func (*NotesHandler) GetByID

func (h *NotesHandler) GetByID(c *echo.Context) error

func (*NotesHandler) Upsert

func (h *NotesHandler) Upsert(c *echo.Context) error

type NotesListResponse

type NotesListResponse struct {
	Notes      []NoteResponse      `json:"notes"`
	Tombstones []TombstoneResponse `json:"tombstones"`
	NextCursor *string             `json:"next_cursor"` // non-null when more pages exist
	ServerTime *time.Time          `json:"server_time"`
}

type NotesRepository

type NotesRepository struct {
	// contains filtered or unexported fields
}

func NewNotesRepository

func NewNotesRepository(db *gorm.DB) *NotesRepository

func (*NotesRepository) CountLiveNotes

func (r *NotesRepository) CountLiveNotes(ctx context.Context, userID uuid.UUID) (int64, error)

func (*NotesRepository) Delete

func (r *NotesRepository) Delete(ctx context.Context, noteID uuid.UUID, userID uuid.UUID) error

func (*NotesRepository) FindAll

func (r *NotesRepository) FindAll(ctx context.Context, userID uuid.UUID) ([]Note, error)

func (*NotesRepository) FindAllPaginated

func (r *NotesRepository) FindAllPaginated(ctx context.Context, userID uuid.UUID, limit int, afterUpdatedAt time.Time, afterNoteID uuid.UUID) ([]Note, error)

FindAllPaginated returns up to limit notes for the user, ordered by (updated_at ASC, note_id ASC). Pass zero values for afterUpdatedAt and afterNoteID to start from the beginning.

func (*NotesRepository) FindAllTombstones

func (r *NotesRepository) FindAllTombstones(ctx context.Context, userID uuid.UUID) ([]NoteTombstone, error)

func (*NotesRepository) FindByID

func (r *NotesRepository) FindByID(ctx context.Context, noteID uuid.UUID, userID uuid.UUID) (*Note, error)

func (*NotesRepository) FindTombstonesSince

func (r *NotesRepository) FindTombstonesSince(ctx context.Context, userID uuid.UUID, since time.Time) ([]NoteTombstone, error)

func (*NotesRepository) FindUpdatedSince

func (r *NotesRepository) FindUpdatedSince(ctx context.Context, userID uuid.UUID, since time.Time) ([]Note, error)

func (*NotesRepository) PurgeExpiredTombstones

func (r *NotesRepository) PurgeExpiredTombstones(ctx context.Context, olderThan time.Time) (int64, error)

func (*NotesRepository) Upsert

func (r *NotesRepository) Upsert(ctx context.Context, note *Note) error

type NotesService

type NotesService struct {
	// contains filtered or unexported fields
}

func NewNotesService

func NewNotesService(repository repository) *NotesService

func (*NotesService) DeleteNote

func (s *NotesService) DeleteNote(ctx context.Context, noteID uuid.UUID, userID uuid.UUID) error

func (*NotesService) GetNoteByID

func (s *NotesService) GetNoteByID(ctx context.Context, noteID uuid.UUID, userID uuid.UUID) (*Note, error)

func (*NotesService) GetNotesSince

func (s *NotesService) GetNotesSince(ctx context.Context, userID uuid.UUID, since *time.Time, cursor *NoteCursor, limit int) ([]Note, []NoteTombstone, bool, error)

GetNotesSince returns notes and tombstones for the user.

When since is non-nil (delta sync), all notes updated after that time are returned with no pagination — the result set is expected to be small.

When since is nil (full sync), notes are paginated using cursor-based pagination ordered by (updated_at ASC, note_id ASC). Pass a non-nil cursor to continue from a previous page. Tombstones are always returned in full (they carry no payload and are small). hasMore is true when there are additional pages to fetch.

func (*NotesService) UpsertNote

func (s *NotesService) UpsertNote(ctx context.Context, userID uuid.UUID, noteID uuid.UUID, encryptedPayload []byte, baseVersion *time.Time) (*Note, error)

type TombstoneResponse

type TombstoneResponse struct {
	NoteID    uuid.UUID  `json:"note_id"`
	DeletedAt *time.Time `json:"deleted_at"`
}

type UpsertNoteRequest

type UpsertNoteRequest struct {
	EncryptedPayload string     `json:"encrypted_payload" validate:"required"`
	BaseVersion      *time.Time `json:"base_version"` // the updated_at the client last saw; omit on first write
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL