malak

package module
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Feb 12, 2025 License: AGPL-3.0 Imports: 23 Imported by: 0

README

Malak

Codecov Go Report Card

Meet Malak, an opensource performance insights management tool for startups and their investors.

Angelist Raise, Carta and other tools are awesome to communicate with investors. However, these tools are very limited in terms of control and customization. Or can cost thousands of $ to run and still be limited to certain features subsets. Or have your data being used to cross-sell to other businesses for their own gain

That's where Malak comes in. Self-hosted on your own infra or hosted by us. White-label by design. Ready to be deployed on your own domain. Own full control of your data and company state if you decide to selfhost.

Features

[!NOTE] Hosted version available by mid March :)

  • 100% Opensource. Own your own data, metrics, and story
  • Send investors' updates to anyone via email
  • Manage metrics automatically from many sources such as Mercury, Brex, Stripe and more. Full list
  • Create, manage and share your decks.
  • Manage your fundraising pipeline
  • Own your captable
Built With
  • Golang
  • Postgresql
  • Redis
  • NextJS
  • Tailwind CSS
  • Stripe ( optional )

Self-hosting

Migrations
malak migrate

[!IMPORTANT] Everytime you upgrade the backend or re-download the binary/docker image, it makes sense to run the migrations again as migrations are usually added to support newer features or enhance existing ones

Backend

You can either download the raw binary or use our docker image. You can view a list of all available releases on Github.

The docker image is also available as docker pull ghcr.io/ayinke-llc/malak:version where version can be the version you want. The version can be in two formats:

  • semver version number e.g: docker pull ghcr.io/ayinke-llc/malak:0.4.2
  • commit hash e.g: docker pull ghcr.io/ayinke-llc/malak:101a434d

At the very minimum, your configuration needs to look like this:

[!IMPORTANT] You can also use environment values to configure this in cloud environments using the syntax MALAK_. So for auth.google.client_id, you can use MALAK_AUTH_GOOGLE_CLIENT_ID

Your config.yml below:

auth:
  google:
    client_id: "GOOGLE_CLIENT_ID"
    client_secret: "GOOGLE_CLIENT_SECRET"
    redirect_uri: "GOOGLE_REDIRECT_URI"
    is_enabled: true

  jwt:
    key: YOUR_SECRET_KEY

uploader:
  s3:
    access_key: YOUR_ACCESS_KEY
    access_secret: YOUR_SECRET_KEY
    region: lagos-1
    endpoint: http://localhost:9000
    use_tls: false

email:
  provider: smtp # OR resend
  sender: email@yourdomain
  sender_name: Malak
  resend:
    api_key: RESEND_API_KEY
  smtp:
    host: localhost
    password: random
    username: random
    use_tls: false
    port: 9125

[!IMPORTANT] The docker image runs the http server by default but if you are using the binary, you can run it with malak http

Plans are extremely important in Malak. Even though you are self hosting and not taking payments, you can still limit certain features for users on your instance. Every company/workspace must be have a plan.

You can view a complete list of all available configuration here.

Listing plans
malak plans list
Create a new plan
malak plans create
Set a default plan for newly created workspaces
malak plans set-default plan_id
Frontend
Dashboard
NEXT_PUBLIC_GOOGLE_CLIENT_ID=
NEXT_PUBLIC_MALAK_POSTHOG_KEY=
NEXT_PUBLIC_MALAK_ENABLE_POSTHOG=
NEXT_PUBLIC_MALAK_POSTHOG_HOST=
NEXT_PUBLIC_MALAK_TERMS_CONDITION_LINK=
NEXT_PUBLIC_MALAK_PRIVACY_POLICY_LINK=
NEXT_PUBLIC_SENTRY_DSN=
NEXT_PUBLIC_DECKS_DOMAIN=https://deck.yourdowmain
NEXT_PUBLIC_SUPPORT_EMAIL=support@yourdomain
Deck viewer

[!IMPORTANT] The decks viewer is not open sourced at the moment. You need a commercial/ Enterprise license for that.

LICENSE

Malak is a commercial open source product, which means some parts of this open source repository require a commercial license. The concept is called "Open Core" where the core software (99%) is fully open source, licensed under AGPLv3 and the last 1% is covered under a commercial license (/internal/integrations Enterprise/Commercial Edition) which we believe is entirely relevant for larger organisations that require those features.

Our philosophy is simple, all features are open-source under AGPLv3. But 3rd party integrations and auto-syncing are under a commercial/Enterprise license.

See details of commercial/Enterprise license here

FAQs

Using Minio locally for S3
Buckets

You need to create two buckets:

  • malak : for publicly available objects
  • deck: Make sure this bucket is private. Items here should not be publicly available

[!NOTE] This bucket names are not hard-coded. They are just defaults, you can name your buckets however you choose to. Just add the bucket names correctly in your configuration

Images are not showing correctly in the editor

Please make sure the buckets are publicly available. This allows images to be read correctly

Configure mc client
mc alias set malak http://localhost:9000 access secret
## this assumes you created a bucket in Minio called malak
mc stat malak/malak
mc share download --recursive malak/malak

This should return something like:

URL: http://localhost:9000/malak/575ca9e2-9782-439e-9a74-c0a8923c7e1e
Expire: 7 days 0 hours 0 minutes 0 seconds
Share: http://localhost:9000/malak/575ca9e2-9782-439e-9a74-c0a8923c7e1e?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=yy9Od9rfMjCX
I553bZKp%2F20240921%2Flagos-1%2Fs3%2Faws4_request&X-Amz-Date=20240921T161000Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Sign
ature=b96a68d4d4b048d7e8092ff3c9241880f3d32d78ae85023e0abd68b681ed33bd

URL: http://localhost:9000/malak/CleanShot 2024-09-17 at 20.22.15.png
Expire: 7 days 0 hours 0 minutes 0 seconds
Share: http://localhost:9000/malak/CleanShot%202024-09-17%20at%2020.22.15.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=yy9Od9
rfMjCXI553bZKp%2F20240921%2Flagos-1%2Fs3%2Faws4_request&X-Amz-Date=20240921T161000Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Am
z-Signature=6cc3487799e07e2de2681c024a842f81b189fc5968f1ed79b8e7760ef1c3019e

Viewing swagger docs

You need to first enable the dev swagger UI with the following config:

http:
  swagger:
    port: 9999
    ui_enabled: true

After which you can visit http://localhost:9999/swagger/

Documentation

Overview

@host localhost:5300 @BasePath /v1 @schemes http

@securityDefinitions.apikey ApiKeyAuth @in header @name Authorization

Index

Constants

View Source
const (
	ErrContactNotFound = MalakError("contact not found")
	ErrContactExists   = MalakError("contact with email already exists")
)
View Source
const (
	ErrUpdateNotFound                  = MalakError("update not exists")
	ErrUpdateRecipientCapacityExceeded = MalakError("you have reached the max number of recipients per update")

	ErrPinnedUpdateNotExists        = MalakError("update not pinned")
	ErrPinnedUpdateCapacityExceeded = MalakError(
		`you have exceeded the maximum number of pinned updates. Please unpin an update and pin this again`)

	ErrPinnedDeckCapacityExceeded = MalakError(
		`you have exceeded the maximum number of pinned updates. Please unpin an update and pin this again`)

	ErrUpdateScheduleNotFound = MalakError("update schedule not found")

	MaximumNumberOfPinnedUpdates = 4
)
View Source
const (
	ErrUserNotFound = MalakError("user not found")
	ErrUserExists   = MalakError("User with email already exists")
)
View Source
const (
	ErrDeckNotFound = MalakError("deck not found")
)

Variables

View Source
var (
	ErrPlanNotFound       = MalakError("plan does not exists")
	ErrCounterExhausted   = MalakError("no more units left")
	ErrOnlyOneDefaultPlan = MalakError("there can only be one default plan")
)
View Source
var (
	ErrContactListNotFound = MalakError("contact list not found")
)
View Source
var ErrInvalidContactShareItemType = errors.New("not a valid ContactShareItemType")
View Source
var ErrInvalidContactTitle = errors.New("not a valid ContactTitle")
View Source
var ErrInvalidEntityType = errors.New("not a valid EntityType")
View Source
var ErrInvalidIntegrationChartInternalNameType = errors.New("not a valid IntegrationChartInternalNameType")
View Source
var ErrInvalidIntegrationDataPointType = errors.New("not a valid IntegrationDataPointType")
View Source
var ErrInvalidIntegrationProvider = errors.New("not a valid IntegrationProvider")
View Source
var ErrInvalidIntegrationSyncCheckpointStatus = errors.New("not a valid IntegrationSyncCheckpointStatus")
View Source
var ErrInvalidIntegrationType = errors.New("not a valid IntegrationType")
View Source
var ErrInvalidListUpdateFilterStatus = errors.New("not a valid ListUpdateFilterStatus")
View Source
var ErrInvalidReactionStatus = errors.New("not a valid ReactionStatus")
View Source
var ErrInvalidRecipientStatus = errors.New("not a valid RecipientStatus")
View Source
var ErrInvalidRecipientType = errors.New("not a valid RecipientType")
View Source
var ErrInvalidRole = errors.New("not a valid Role")
View Source
var ErrInvalidUpdateRecipientLogProvider = errors.New("not a valid UpdateRecipientLogProvider")
View Source
var ErrInvalidUpdateSendSchedule = errors.New("not a valid UpdateSendSchedule")
View Source
var ErrInvalidUpdateStatus = errors.New("not a valid UpdateStatus")
View Source
var ErrInvalidUpdateType = errors.New("not a valid UpdateType")
View Source
var (
	ErrWorkspaceIntegrationNotFound = MalakError("integration not found")
)
View Source
var (
	ErrWorkspaceNotFound = MalakError("workspace not found")
)
View Source
var Migrations embed.FS

Functions

func GenerateReference

func GenerateReference(e EntityType) string

DEPRECATED

func GetTodayFormatted added in v0.5.0

func GetTodayFormatted() string

func HashPassword

func HashPassword(p string) (string, error)

func IsDuplicateUniqueError

func IsDuplicateUniqueError(e error) bool

func IsImageFromURL added in v0.3.1

func IsImageFromURL(s string) (bool, error)

func VerifyPassword

func VerifyPassword(hashed, plain string) bool

Types

type AccessToken added in v0.5.0

type AccessToken string

func (AccessToken) String added in v0.5.0

func (a AccessToken) String() string

type BillingPreferences added in v0.3.1

type BillingPreferences struct {
	FinanceEmail Email `json:"finance_email,omitempty"`
}

type Block

type Block struct {
	ID       string                 `json:"id"`
	Type     string                 `json:"type"`
	Props    map[string]interface{} `json:"props"`
	Content  interface{}            `json:"content"`
	Children []Block                `json:"children"`
}

type BlockContents

type BlockContents []Block

func SanitizeBlocks

func SanitizeBlocks(blocks BlockContents) (BlockContents, error)

func (BlockContents) HTML

func (bc BlockContents) HTML() string

type BulletListItemBlock

type BulletListItemBlock struct {
	Block
	Content []InlineContent `json:"content"`
}

type CommunicationPreferences added in v0.3.1

type CommunicationPreferences struct {
	EnableMarketing      bool `json:"enable_marketing,omitempty"`
	EnableProductUpdates bool `json:"enable_product_updates,omitempty"`
}

type Contact

type Contact struct {
	ID          uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Email       Email     `json:"email,omitempty"`
	WorkspaceID uuid.UUID `json:"workspace_id,omitempty"`
	Reference   Reference `json:"reference,omitempty"`
	FirstName   string    `json:"first_name,omitempty"`
	LastName    string    `json:"last_name,omitempty"`
	Company     string    `json:"company,omitempty"`

	// Legacy lmao. should be address but migrations bit ugh :))
	City  string               `json:"city,omitempty"`
	Phone string               `json:"phone,omitempty"`
	Notes string               `json:"notes,omitempty"`
	Lists []ContactListMapping `json:"lists" bun:"rel:has-many,join:id=contact_id"`

	// User who owns the contact.
	// Does not mean who added the contact but who chases
	// or follows up officially with the contact
	OwnerID uuid.UUID `json:"owner_id,omitempty"`

	// User who added/created this contact
	CreatedBy uuid.UUID `json:"created_by,omitempty"`

	Metadata CustomContactMetadata `json:"metadata,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type ContactList

type ContactList struct {
	ID          uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Title       string    `json:"title,omitempty"`
	WorkspaceID uuid.UUID `json:"workspace_id,omitempty"`
	Reference   Reference `json:"reference,omitempty"`

	CreatedBy uuid.UUID `json:"created_by,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type ContactListMapping

type ContactListMapping struct {
	ID        uuid.UUID    `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	ContactID uuid.UUID    `json:"contact_id,omitempty"`
	ListID    uuid.UUID    `json:"list_id,omitempty"`
	List      *ContactList `json:"list,omitempty" bun:"rel:has-one,join:list_id=id"`
	Reference Reference    `json:"reference,omitempty"`
	CreatedBy uuid.UUID    `json:"created_by,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type ContactListMappingWithContact

type ContactListMappingWithContact struct {
	ID        uuid.UUID `json:"id,omitempty"`
	ListID    uuid.UUID `json:"list_id,omitempty"`
	ContactID uuid.UUID `json:"contact_id,omitempty"`
	Reference string    `json:"reference,omitempty"`

	// Contact fields
	Email string `json:"email,omitempty"`
}

type ContactListOptions

type ContactListOptions struct {
	WorkspaceID   uuid.UUID
	IncludeEmails bool
}

type ContactShare added in v0.3.0

type ContactShare struct {
	ID            uuid.UUID            `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference     Reference            `json:"reference,omitempty"`
	SharedBy      uuid.UUID            `json:"shared_by,omitempty"`
	ContactID     uuid.UUID            `json:"contact_id,omitempty"`
	ItemType      ContactShareItemType `json:"item_type,omitempty"`
	ItemID        uuid.UUID            `json:"item_id,omitempty"`
	ItemReference Reference            `json:"item_reference,omitempty"`
	SharedAt      time.Time            `json:"shared_at,omitempty" bun:",nullzero,notnull,default:current_timestamp"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type ContactShareItem added in v0.3.0

type ContactShareItem struct {
	ContactShare
	Title string `json:"title,omitempty"`
}

type ContactShareItemType added in v0.3.0

type ContactShareItemType string

ENUM(update,dashboard,deck)

const (
	// ContactShareItemTypeUpdate is a ContactShareItemType of type update.
	ContactShareItemTypeUpdate ContactShareItemType = "update"
	// ContactShareItemTypeDashboard is a ContactShareItemType of type dashboard.
	ContactShareItemTypeDashboard ContactShareItemType = "dashboard"
	// ContactShareItemTypeDeck is a ContactShareItemType of type deck.
	ContactShareItemTypeDeck ContactShareItemType = "deck"
)

func ParseContactShareItemType added in v0.3.0

func ParseContactShareItemType(name string) (ContactShareItemType, error)

ParseContactShareItemType attempts to convert a string to a ContactShareItemType.

func (ContactShareItemType) IsValid added in v0.3.0

func (x ContactShareItemType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (ContactShareItemType) String added in v0.3.0

func (x ContactShareItemType) String() string

String implements the Stringer interface.

type ContactShareRepository added in v0.3.0

type ContactShareRepository interface {
	All(context.Context, *Contact) ([]ContactShareItem, error)
}

type ContactTitle

type ContactTitle string

ENUM(mr,mrs,miss,doctor,chief)

const (
	// ContactTitleMr is a ContactTitle of type mr.
	ContactTitleMr ContactTitle = "mr"
	// ContactTitleMrs is a ContactTitle of type mrs.
	ContactTitleMrs ContactTitle = "mrs"
	// ContactTitleMiss is a ContactTitle of type miss.
	ContactTitleMiss ContactTitle = "miss"
	// ContactTitleDoctor is a ContactTitle of type doctor.
	ContactTitleDoctor ContactTitle = "doctor"
	// ContactTitleChief is a ContactTitle of type chief.
	ContactTitleChief ContactTitle = "chief"
)

func ParseContactTitle

func ParseContactTitle(name string) (ContactTitle, error)

ParseContactTitle attempts to convert a string to a ContactTitle.

func (ContactTitle) IsValid

func (x ContactTitle) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (ContactTitle) String

func (x ContactTitle) String() string

String implements the Stringer interface.

type Counter

type Counter int64

func (Counter) Add

func (c Counter) Add()

func (Counter) Take

func (c Counter) Take() error

func (Counter) TakeN

func (c Counter) TakeN(n int64) error

type CreateDeckOptions

type CreateDeckOptions struct {
	RequireEmail      bool `json:"require_email,omitempty"`
	EnableDownloading bool `json:"enable_downloading,omitempty"`
	Password          struct {
		Enabled  bool     `json:"enabled,omitempty" validate:"required"`
		Password Password `json:"password,omitempty" validate:"required"`
	} `json:"password,omitempty" validate:"required"`
	ExpiresAt *time.Time `json:"expires_at,omitempty"`
	Reference Reference  `json:"reference,omitempty"`
}

type CreateUpdateOptions

type CreateUpdateOptions struct {
	Reference       func(EntityType) string
	Generator       ReferenceGeneratorOperation
	Email           Email
	WorkspaceID     uuid.UUID
	Emails          []Email
	Schedule        *UpdateSchedule
	UserID          uuid.UUID
	UpdateReference Reference
	Plan            *Plan
}

type CreateWorkspaceOptions

type CreateWorkspaceOptions struct {
	User      *User
	Workspace *Workspace
}

type CustomContactMetadata

type CustomContactMetadata map[string]string

type Dashboard added in v0.3.0

type Dashboard struct {
	ID        uuid.UUID `json:"id,omitempty"`
	Reference Reference `json:"reference,omitempty"`
}

type Deck

type Deck struct {
	ID uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`

	Reference   Reference `json:"reference,omitempty"`
	WorkspaceID uuid.UUID `json:"workspace_id,omitempty"`
	CreatedBy   uuid.UUID `json:"created_by,omitempty"`
	Title       string    `json:"title,omitempty"`
	ShortLink   string    `json:"short_link,omitempty"`
	DeckSize    int64     `json:"deck_size,omitempty"`

	IsArchived bool `json:"is_archived,omitempty"`

	IsPinned bool `json:"is_pinned,omitempty"`

	ObjectKey string `json:"object_key,omitempty"`

	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	DeckPreference *DeckPreference `bun:"rel:has-one,join:id=deck_id" json:"preferences,omitempty"`

	bun.BaseModel `bun:"table:decks" json:"-"`
}

type DeckPreference

type DeckPreference struct {
	ID uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`

	Reference Reference `json:"reference,omitempty"`

	WorkspaceID       uuid.UUID               `json:"workspace_id,omitempty"`
	DeckID            uuid.UUID               `json:"deck_id,omitempty"`
	EnableDownloading bool                    `json:"enable_downloading,omitempty"`
	RequireEmail      bool                    `json:"require_email,omitempty"`
	Password          PasswordDeckPreferences `json:"password,omitempty"`
	ExpiresAt         *time.Time              `bun:",soft_delete,nullzero" json:"expires_at,omitempty"`

	CreatedBy uuid.UUID `json:"created_by,omitempty"`

	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	DeletedAt     *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`
	bun.BaseModel `json:"-"`
}

type DeckRepository

type DeckRepository interface {
	Create(context.Context, *Deck, *CreateDeckOptions) error
	List(context.Context, *Workspace) ([]Deck, error)
	Get(context.Context, FetchDeckOptions) (*Deck, error)
	PublicDetails(context.Context, Reference) (*Deck, error)
	Delete(context.Context, *Deck) error
	UpdatePreferences(context.Context, *Deck) error
	ToggleArchive(context.Context, *Deck) error
	TogglePinned(context.Context, *Deck) error
}

type DefaultProps

type DefaultProps struct {
	BackgroundColor string `json:"backgroundColor"`
	TextColor       string `json:"textColor"`
	TextAlignment   string `json:"textAlignment"`
}

type Email

type Email string

func (Email) String

func (e Email) String() string

func (Email) Value

func (e Email) Value() (driver.Value, error)

type EntityType

type EntityType string

ENUM( workspace,invoice, team,invite,contact, update,link,room, recipient,schedule,list, list_email, update_stat, recipient_stat,recipient_log, deck,deck_preference, contact_share,dashboard, plan,price,integration,workspace_integration, integration_datapoint, integration_chart, integration_sync_checkpoint)

const (
	// EntityTypeWorkspace is a EntityType of type workspace.
	EntityTypeWorkspace EntityType = "workspace"
	// EntityTypeInvoice is a EntityType of type invoice.
	EntityTypeInvoice EntityType = "invoice"
	// EntityTypeTeam is a EntityType of type team.
	EntityTypeTeam EntityType = "team"
	// EntityTypeInvite is a EntityType of type invite.
	EntityTypeInvite EntityType = "invite"
	// EntityTypeContact is a EntityType of type contact.
	EntityTypeContact EntityType = "contact"
	// EntityTypeUpdate is a EntityType of type update.
	EntityTypeUpdate EntityType = "update"
	// EntityTypeLink is a EntityType of type link.
	EntityTypeLink EntityType = "link"
	// EntityTypeRoom is a EntityType of type room.
	EntityTypeRoom EntityType = "room"
	// EntityTypeRecipient is a EntityType of type recipient.
	EntityTypeRecipient EntityType = "recipient"
	// EntityTypeSchedule is a EntityType of type schedule.
	EntityTypeSchedule EntityType = "schedule"
	// EntityTypeList is a EntityType of type list.
	EntityTypeList EntityType = "list"
	// EntityTypeListEmail is a EntityType of type list_email.
	EntityTypeListEmail EntityType = "list_email"
	// EntityTypeUpdateStat is a EntityType of type update_stat.
	EntityTypeUpdateStat EntityType = "update_stat"
	// EntityTypeRecipientStat is a EntityType of type recipient_stat.
	EntityTypeRecipientStat EntityType = "recipient_stat"
	// EntityTypeRecipientLog is a EntityType of type recipient_log.
	EntityTypeRecipientLog EntityType = "recipient_log"
	// EntityTypeDeck is a EntityType of type deck.
	EntityTypeDeck EntityType = "deck"
	// EntityTypeDeckPreference is a EntityType of type deck_preference.
	EntityTypeDeckPreference EntityType = "deck_preference"
	// EntityTypeContactShare is a EntityType of type contact_share.
	EntityTypeContactShare EntityType = "contact_share"
	// EntityTypeDashboard is a EntityType of type dashboard.
	EntityTypeDashboard EntityType = "dashboard"
	// EntityTypePlan is a EntityType of type plan.
	EntityTypePlan EntityType = "plan"
	// EntityTypePrice is a EntityType of type price.
	EntityTypePrice EntityType = "price"
	// EntityTypeIntegration is a EntityType of type integration.
	EntityTypeIntegration EntityType = "integration"
	// EntityTypeWorkspaceIntegration is a EntityType of type workspace_integration.
	EntityTypeWorkspaceIntegration EntityType = "workspace_integration"
	// EntityTypeIntegrationDatapoint is a EntityType of type integration_datapoint.
	EntityTypeIntegrationDatapoint EntityType = "integration_datapoint"
	// EntityTypeIntegrationChart is a EntityType of type integration_chart.
	EntityTypeIntegrationChart EntityType = "integration_chart"
	// EntityTypeIntegrationSyncCheckpoint is a EntityType of type integration_sync_checkpoint.
	EntityTypeIntegrationSyncCheckpoint EntityType = "integration_sync_checkpoint"
)

func ParseEntityType

func ParseEntityType(name string) (EntityType, error)

ParseEntityType attempts to convert a string to a EntityType.

func (EntityType) IsValid

func (x EntityType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (EntityType) String

func (x EntityType) String() string

String implements the Stringer interface.

type FetchContactListOptions

type FetchContactListOptions struct {
	Reference   Reference
	WorkspaceID uuid.UUID
}

type FetchContactOptions

type FetchContactOptions struct {
	ID          uuid.UUID
	Email       Email
	Reference   Reference
	WorkspaceID uuid.UUID
}

type FetchDeckOptions

type FetchDeckOptions struct {
	Reference   string
	WorkspaceID uuid.UUID
}

type FetchPlanOptions

type FetchPlanOptions struct {
	Reference string
	ID        uuid.UUID
}

type FetchUpdateOptions

type FetchUpdateOptions struct {
	Status      UpdateStatus
	Reference   Reference
	ID          uuid.UUID
	WorkspaceID uuid.UUID
}

type FindUserOptions

type FindUserOptions struct {
	Email Email `json:"email,omitempty"`
	ID    uuid.UUID
}

type FindWorkspaceIntegrationOptions added in v0.5.0

type FindWorkspaceIntegrationOptions struct {
	Reference Reference
	ID        uuid.UUID
}

type FindWorkspaceOptions

type FindWorkspaceOptions struct {
	StripeCustomerID string
	ID               uuid.UUID
	Reference        Reference
}

type HeadingBlock

type HeadingBlock struct {
	Block
	Props struct {
		DefaultProps
		Level int `json:"level"`
	} `json:"props"`
	Content []InlineContent `json:"content"`
}

type ImageBlock

type ImageBlock struct {
	Block
	Props struct {
		DefaultProps
		URL          string `json:"url"`
		Caption      string `json:"caption"`
		PreviewWidth int    `json:"previewWidth"`
	} `json:"props"`
}

type InlineContent

type InlineContent interface {
	// contains filtered or unexported methods
}

type Integration added in v0.3.1

type Integration struct {
	ID              uuid.UUID       `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	IntegrationName string          `json:"integration_name,omitempty"`
	Reference       Reference       `json:"reference,omitempty"`
	Description     string          `json:"description,omitempty"`
	IsEnabled       bool            `json:"is_enabled,omitempty"`
	IntegrationType IntegrationType `json:"integration_type,omitempty"`
	LogoURL         string          `json:"logo_url,omitempty"`

	Metadata IntegrationMetadata `json:"metadata,omitempty" bson:"metadata"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty" bson:"created_at"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty" bson:"updated_at"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty" bson:"deleted_at"`

	bun.BaseModel `json:"-"`
}

type IntegrationChart added in v0.5.0

type IntegrationChart struct {
	ID                     uuid.UUID                        `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	WorkspaceIntegrationID uuid.UUID                        `json:"workspace_integration_id,omitempty"`
	WorkspaceID            uuid.UUID                        `json:"workspace_id,omitempty"`
	Reference              Reference                        `json:"reference,omitempty"`
	UserFacingName         string                           `json:"user_facing_name,omitempty"`
	InternalName           IntegrationChartInternalNameType `json:"internal_name,omitempty"`
	Metadata               IntegrationChartMetadata         `json:"metadata,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type IntegrationChartInternalNameType added in v0.5.0

type IntegrationChartInternalNameType string

ENUM(mercury_account,mercury_account_transaction,brex_account,brex_account_transaction)

const (
	// IntegrationChartInternalNameTypeMercuryAccount is a IntegrationChartInternalNameType of type mercury_account.
	IntegrationChartInternalNameTypeMercuryAccount IntegrationChartInternalNameType = "mercury_account"
	// IntegrationChartInternalNameTypeMercuryAccountTransaction is a IntegrationChartInternalNameType of type mercury_account_transaction.
	IntegrationChartInternalNameTypeMercuryAccountTransaction IntegrationChartInternalNameType = "mercury_account_transaction"
	// IntegrationChartInternalNameTypeBrexAccount is a IntegrationChartInternalNameType of type brex_account.
	IntegrationChartInternalNameTypeBrexAccount IntegrationChartInternalNameType = "brex_account"
	// IntegrationChartInternalNameTypeBrexAccountTransaction is a IntegrationChartInternalNameType of type brex_account_transaction.
	IntegrationChartInternalNameTypeBrexAccountTransaction IntegrationChartInternalNameType = "brex_account_transaction"
)

func ParseIntegrationChartInternalNameType added in v0.5.0

func ParseIntegrationChartInternalNameType(name string) (IntegrationChartInternalNameType, error)

ParseIntegrationChartInternalNameType attempts to convert a string to a IntegrationChartInternalNameType.

func (IntegrationChartInternalNameType) IsValid added in v0.5.0

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (IntegrationChartInternalNameType) String added in v0.5.0

String implements the Stringer interface.

type IntegrationChartMetadata added in v0.5.0

type IntegrationChartMetadata struct {
	ProviderID string `json:"provider_id,omitempty"`
}

type IntegrationChartValues added in v0.5.0

type IntegrationChartValues struct {
	InternalName   IntegrationChartInternalNameType
	UserFacingName string
	ProviderID     string
}

type IntegrationDataPoint added in v0.5.0

type IntegrationDataPoint struct {
	ID                     uuid.UUID                    `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	WorkspaceIntegrationID uuid.UUID                    `json:"workspace_integration_id,omitempty"`
	WorkspaceID            uuid.UUID                    `json:"workspace_id,omitempty"`
	IntegrationChartID     uuid.UUID                    `json:"integration_chart_id,omitempty"`
	Reference              Reference                    `json:"reference,omitempty"`
	PointName              string                       `json:"point_name,omitempty"`
	PointValue             int64                        `json:"point_value,omitempty"`
	DataPointType          IntegrationDataPointType     `json:"data_point_type,omitempty"`
	Metadata               IntegrationDataPointMetadata `json:"metadata,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type IntegrationDataPointMetadata added in v0.5.0

type IntegrationDataPointMetadata struct {
}

type IntegrationDataPointType added in v0.5.0

type IntegrationDataPointType string

ENUM(currency,others)

const (
	// IntegrationDataPointTypeCurrency is a IntegrationDataPointType of type currency.
	IntegrationDataPointTypeCurrency IntegrationDataPointType = "currency"
	// IntegrationDataPointTypeOthers is a IntegrationDataPointType of type others.
	IntegrationDataPointTypeOthers IntegrationDataPointType = "others"
)

func ParseIntegrationDataPointType added in v0.5.0

func ParseIntegrationDataPointType(name string) (IntegrationDataPointType, error)

ParseIntegrationDataPointType attempts to convert a string to a IntegrationDataPointType.

func (IntegrationDataPointType) IsValid added in v0.5.0

func (x IntegrationDataPointType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (IntegrationDataPointType) String added in v0.5.0

func (x IntegrationDataPointType) String() string

String implements the Stringer interface.

type IntegrationDataValues added in v0.5.0

type IntegrationDataValues struct {
	// here so it is easy to find the chart this data point belongs to
	// without too much voodoo
	// InternalName + ProviderID search in db
	// We cannot use only InternalName becasue some integrations
	// like mercury have the same InternalName twice ( each account has a savings and checkings which we track)
	InternalName IntegrationChartInternalNameType
	ProviderID   string
	Data         IntegrationDataPoint
}

keeping it simple here with a new struct

type IntegrationFetchDataOptions added in v0.5.0

type IntegrationFetchDataOptions struct {
	IntegrationID      uuid.UUID
	WorkspaceID        uuid.UUID
	ReferenceGenerator ReferenceGeneratorOperation
	LastFetchedAt      time.Time
}

type IntegrationMetadata added in v0.3.1

type IntegrationMetadata struct {
	Endpoint string `json:"endpoint,omitempty"`
}

type IntegrationProvider added in v0.3.1

type IntegrationProvider string

ENUM(stripe,paystack,flutterwave,mercury,brex)

const (
	// IntegrationProviderStripe is a IntegrationProvider of type stripe.
	IntegrationProviderStripe IntegrationProvider = "stripe"
	// IntegrationProviderPaystack is a IntegrationProvider of type paystack.
	IntegrationProviderPaystack IntegrationProvider = "paystack"
	// IntegrationProviderFlutterwave is a IntegrationProvider of type flutterwave.
	IntegrationProviderFlutterwave IntegrationProvider = "flutterwave"
	// IntegrationProviderMercury is a IntegrationProvider of type mercury.
	IntegrationProviderMercury IntegrationProvider = "mercury"
	// IntegrationProviderBrex is a IntegrationProvider of type brex.
	IntegrationProviderBrex IntegrationProvider = "brex"
)

func ParseIntegrationProvider added in v0.5.0

func ParseIntegrationProvider(name string) (IntegrationProvider, error)

ParseIntegrationProvider attempts to convert a string to a IntegrationProvider.

func (IntegrationProvider) IsValid added in v0.5.0

func (x IntegrationProvider) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (IntegrationProvider) String added in v0.5.0

func (x IntegrationProvider) String() string

String implements the Stringer interface.

type IntegrationProviderClient added in v0.5.0

type IntegrationProviderClient interface {
	Name() IntegrationProvider

	// Ping tests the connection to make sure we have an
	// active connection
	Ping(context.Context, AccessToken) ([]IntegrationChartValues, error)

	Data(context.Context, AccessToken, *IntegrationFetchDataOptions) ([]IntegrationDataValues, error)

	io.Closer
}

type IntegrationSyncCheckpoint added in v0.5.0

type IntegrationSyncCheckpoint struct {
	ID                     uuid.UUID  `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference              Reference  `json:"reference,omitempty"`
	WorkspaceID            uuid.UUID  `bun:"workspace_id,notnull" json:"workspace_id,omitempty"`
	WorkspaceIntegrationID uuid.UUID  `json:"workspace_integration_id,omitempty"`
	LastSyncAttempt        time.Time  `bun:"last_sync_attempt" json:"last_sync_attempt,omitempty"`
	LastSuccessfulSync     *time.Time `bun:"last_successful_sync" json:"last_successful_sync,omitempty"`
	Status                 string     `bun:"status,notnull" json:"status,omitempty"`
	ErrorMessage           string     `bun:"error_message" json:"error_message,omitempty"`
	CreatedAt              time.Time  `bun:"created_at,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt              time.Time  `bun:"updated_at,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt              *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type IntegrationSyncCheckpointStatus added in v0.5.0

type IntegrationSyncCheckpointStatus string

ENUM(failed,pending,success)

const (
	// IntegrationSyncCheckpointStatusFailed is a IntegrationSyncCheckpointStatus of type failed.
	IntegrationSyncCheckpointStatusFailed IntegrationSyncCheckpointStatus = "failed"
	// IntegrationSyncCheckpointStatusPending is a IntegrationSyncCheckpointStatus of type pending.
	IntegrationSyncCheckpointStatusPending IntegrationSyncCheckpointStatus = "pending"
	// IntegrationSyncCheckpointStatusSuccess is a IntegrationSyncCheckpointStatus of type success.
	IntegrationSyncCheckpointStatusSuccess IntegrationSyncCheckpointStatus = "success"
)

func ParseIntegrationSyncCheckpointStatus added in v0.5.0

func ParseIntegrationSyncCheckpointStatus(name string) (IntegrationSyncCheckpointStatus, error)

ParseIntegrationSyncCheckpointStatus attempts to convert a string to a IntegrationSyncCheckpointStatus.

func (IntegrationSyncCheckpointStatus) IsValid added in v0.5.0

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (IntegrationSyncCheckpointStatus) String added in v0.5.0

String implements the Stringer interface.

type IntegrationType added in v0.3.1

type IntegrationType string

ENUM(oauth2,api_key)

const (
	// IntegrationTypeOauth2 is a IntegrationType of type oauth2.
	IntegrationTypeOauth2 IntegrationType = "oauth2"
	// IntegrationTypeApiKey is a IntegrationType of type api_key.
	IntegrationTypeApiKey IntegrationType = "api_key"
)

func ParseIntegrationType added in v0.3.1

func ParseIntegrationType(name string) (IntegrationType, error)

ParseIntegrationType attempts to convert a string to a IntegrationType.

func (IntegrationType) IsValid added in v0.3.1

func (x IntegrationType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (IntegrationType) String added in v0.3.1

func (x IntegrationType) String() string

String implements the Stringer interface.

type Link struct {
	Type    string       `json:"type"`
	Content []StyledText `json:"content"`
	Href    string       `json:"href"`
}

type ListContactOptions

type ListContactOptions struct {
	Paginator   Paginator
	WorkspaceID uuid.UUID
	Status      ListUpdateFilterStatus
}

type ListUpdateFilterStatus

type ListUpdateFilterStatus string

ENUM(draft,sent,all)

const (
	// ListUpdateFilterStatusDraft is a ListUpdateFilterStatus of type draft.
	ListUpdateFilterStatusDraft ListUpdateFilterStatus = "draft"
	// ListUpdateFilterStatusSent is a ListUpdateFilterStatus of type sent.
	ListUpdateFilterStatusSent ListUpdateFilterStatus = "sent"
	// ListUpdateFilterStatusAll is a ListUpdateFilterStatus of type all.
	ListUpdateFilterStatusAll ListUpdateFilterStatus = "all"
)

func ParseListUpdateFilterStatus

func ParseListUpdateFilterStatus(name string) (ListUpdateFilterStatus, error)

ParseListUpdateFilterStatus attempts to convert a string to a ListUpdateFilterStatus.

func (ListUpdateFilterStatus) IsValid

func (x ListUpdateFilterStatus) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (ListUpdateFilterStatus) String

func (x ListUpdateFilterStatus) String() string

String implements the Stringer interface.

type ListUpdateOptions

type ListUpdateOptions struct {
	Paginator   Paginator
	WorkspaceID uuid.UUID
	Status      ListUpdateFilterStatus
}

type MalakError

type MalakError string

func (MalakError) Error

func (m MalakError) Error() string

type NumberedListItemBlock

type NumberedListItemBlock struct {
	Block
	Content []InlineContent `json:"content"`
}

type PaginatedResultMetadata

type PaginatedResultMetadata struct {
	Total int64
}

type Paginator

type Paginator struct {
	PerPage int64
	Page    int64
}

func PaginatorFromRequest

func PaginatorFromRequest(r *http.Request) Paginator

func (Paginator) OTELAttributes

func (p Paginator) OTELAttributes() []attribute.KeyValue

func (Paginator) Offset

func (p Paginator) Offset() int64

type ParagraphBlock

type ParagraphBlock struct {
	Block
	Content []InlineContent `json:"content"`
}

type Password

type Password string

func (Password) Equals

func (p Password) Equals(other Password) bool

func (Password) IsZero

func (p Password) IsZero() bool

func (*Password) MarshalJSON

func (p *Password) MarshalJSON() ([]byte, error)

func (Password) String

func (p Password) String() string

func (Password) Value

func (p Password) Value() (driver.Value, error)

type PasswordDeckPreferences

type PasswordDeckPreferences struct {
	Enabled  bool     `json:"enabled,omitempty"`
	Password Password `json:"password,omitempty"`
}

type Plan

type Plan struct {
	ID uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`

	PlanName string `json:"plan_name,omitempty"`

	// Can use a fake id really
	// As this only matters if you turn on Stripe
	Reference string `json:"reference,omitempty"`

	Metadata PlanMetadata `json:"metadata,omitempty" bson:"metadata"`

	// Stripe default price id. Again not needed if not using Stripe
	DefaultPriceID string `json:"default_price_id,omitempty"`

	// Defaults to zero
	Amount int64 `json:"amount,omitempty"`

	// IsDefault if this is the default plan for the user to get signed up to
	// on sign up
	//
	// Better to keep this here than to use config
	IsDefault bool `json:"is_default,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty" bson:"created_at"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty" bson:"updated_at"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty" bson:"deleted_at"`

	bun.BaseModel `json:"-"`
}

type PlanMetadata

type PlanMetadata struct {
	Team struct {
		Size Counter `json:"size,omitempty"`
	} `json:"team,omitempty"`

	Deck struct {
		AutoTerminateLink bool `json:"auto_terminate_link,omitempty"`
		CustomDomain      bool `json:"custom_domain,omitempty"`
	} `json:"deck,omitempty"`

	Updates struct {
		MaxRecipients Counter `json:"max_recipients,omitempty"`
		CustomDomain  bool    `json:"custom_domain,omitempty"`
	} `json:"updates,omitempty"`

	Integrations struct {
		AvailableForUse Counter `json:"available_for_use,omitempty"`
	} `json:"integrations,omitempty"`

	Dashboard struct {
		ShareDashboardViaLink bool `json:"share_dashboard_via_link,omitempty"`
		EmbedDashboard        bool `json:"embed_dashboard,omitempty"`
	} `json:"dashboard,omitempty"`

	DataRoom struct {
		Size         Counter `json:"size,omitempty"`
		ShareViaLink bool    `json:"share_via_link,omitempty"`
	} `json:"data_room,omitempty"`
}

type PlanRepository

type PlanRepository interface {
	Get(context.Context, *FetchPlanOptions) (*Plan, error)
	List(context.Context) ([]*Plan, error)
	SetDefault(context.Context, *Plan) error
	Create(context.Context, *Plan) error
}

type Preference added in v0.3.1

type Preference struct {
	ID            uuid.UUID                `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	WorkspaceID   uuid.UUID                `json:"workspace_id,omitempty"`
	Communication CommunicationPreferences `json:"communication,omitempty"`
	Billing       BillingPreferences       `json:"billing,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty" bson:"created_at"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty" bson:"updated_at"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty" bson:"deleted_at"`

	bun.BaseModel `json:"-"`
}

func NewPreference added in v0.3.1

func NewPreference(workspace *Workspace) *Preference

type PreferenceRepository added in v0.3.1

type PreferenceRepository interface {
	Get(context.Context, *Workspace) (*Preference, error)
	Update(context.Context, *Preference) error
}

type PublicDeck added in v0.5.2

type PublicDeck struct {
	Reference   Reference `json:"reference,omitempty"`
	WorkspaceID uuid.UUID `json:"workspace_id,omitempty"`
	Title       string    `json:"title,omitempty"`
	ShortLink   string    `json:"short_link,omitempty"`
	DeckSize    int64     `json:"deck_size,omitempty"`

	IsArchived bool `json:"is_archived,omitempty"`

	ObjectLink string `json:"object_link,omitempty"`

	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	DeckPreference *DeckPreference `bun:"rel:has-one,join:id=deck_id" json:"preferences,omitempty"`
}

type ReactionStatus

type ReactionStatus string

ENUM(thumbs up,thumbs down)

const (
	// ReactionStatusThumbsUp is a ReactionStatus of type thumbs up.
	ReactionStatusThumbsUp ReactionStatus = "thumbs up"
	// ReactionStatusThumbsDown is a ReactionStatus of type thumbs down.
	ReactionStatusThumbsDown ReactionStatus = "thumbs down"
)

func ParseReactionStatus

func ParseReactionStatus(name string) (ReactionStatus, error)

ParseReactionStatus attempts to convert a string to a ReactionStatus.

func (ReactionStatus) IsValid

func (x ReactionStatus) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (ReactionStatus) String

func (x ReactionStatus) String() string

String implements the Stringer interface.

type RecipientStatus

type RecipientStatus string

ENUM(pending,sent,failed)

const (
	// RecipientStatusPending is a RecipientStatus of type pending.
	RecipientStatusPending RecipientStatus = "pending"
	// RecipientStatusSent is a RecipientStatus of type sent.
	RecipientStatusSent RecipientStatus = "sent"
	// RecipientStatusFailed is a RecipientStatus of type failed.
	RecipientStatusFailed RecipientStatus = "failed"
)

func ParseRecipientStatus

func ParseRecipientStatus(name string) (RecipientStatus, error)

ParseRecipientStatus attempts to convert a string to a RecipientStatus.

func (RecipientStatus) IsValid

func (x RecipientStatus) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (RecipientStatus) String

func (x RecipientStatus) String() string

String implements the Stringer interface.

type RecipientType

type RecipientType string

ENUM(list,email) List is a flattened group that can contain infinite amount of emails

const (
	// RecipientTypeList is a RecipientType of type list.
	RecipientTypeList RecipientType = "list"
	// RecipientTypeEmail is a RecipientType of type email.
	RecipientTypeEmail RecipientType = "email"
)

func ParseRecipientType

func ParseRecipientType(name string) (RecipientType, error)

ParseRecipientType attempts to convert a string to a RecipientType.

func (RecipientType) IsValid

func (x RecipientType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (RecipientType) String

func (x RecipientType) String() string

String implements the Stringer interface.

type Reference

type Reference string

func (Reference) String

func (r Reference) String() string

type ReferenceGenerator

type ReferenceGenerator struct{}

func NewReferenceGenerator

func NewReferenceGenerator() *ReferenceGenerator

func (*ReferenceGenerator) Generate

func (r *ReferenceGenerator) Generate(e EntityType) Reference
func (r *ReferenceGenerator) ShortLink() string

type ReferenceGeneratorOperation

type ReferenceGeneratorOperation interface {
	Generate(EntityType) Reference
	ShortLink() string
}

type Role

type Role string

ENUM(admin,member,billing,investor,guest)

const (
	// RoleAdmin is a Role of type admin.
	RoleAdmin Role = "admin"
	// RoleMember is a Role of type member.
	RoleMember Role = "member"
	// RoleBilling is a Role of type billing.
	RoleBilling Role = "billing"
	// RoleInvestor is a Role of type investor.
	RoleInvestor Role = "investor"
	// RoleGuest is a Role of type guest.
	RoleGuest Role = "guest"
)

func ParseRole

func ParseRole(name string) (Role, error)

ParseRole attempts to convert a string to a Role.

func (Role) IsValid

func (x Role) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (Role) String

func (x Role) String() string

String implements the Stringer interface.

type StyledText

type StyledText struct {
	Type   string `json:"type"`
	Text   string `json:"text"`
	Styles Styles `json:"styles"`
}

type Styles

type Styles struct {
	Bold            bool   `json:"bold"`
	Italic          bool   `json:"italic"`
	Underline       bool   `json:"underline"`
	Strikethrough   bool   `json:"strikethrough"`
	TextColor       string `json:"textColor"`
	BackgroundColor string `json:"backgroundColor"`
}

type TableBlock

type TableBlock struct {
	Block
	Content TableContent `json:"content"`
}

type TableContent

type TableContent struct {
	Type string `json:"type"`
	Rows []struct {
		Cells [][]InlineContent `json:"cells"`
	} `json:"rows"`
}

type Update

type Update struct {
	ID          uuid.UUID     `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	WorkspaceID uuid.UUID     `json:"workspace_id,omitempty"`
	Status      UpdateStatus  `json:"status,omitempty"`
	Reference   Reference     `json:"reference,omitempty"`
	CreatedBy   uuid.UUID     `json:"created_by,omitempty"`
	SentBy      uuid.UUID     `json:"sent_by,omitempty" bun:",nullzero"`
	Content     BlockContents `json:"content,omitempty"`
	// If this update is pinned
	IsPinned bool   `json:"is_pinned,omitempty"`
	Title    string `json:"title,omitempty"`

	Metadata UpdateMetadata `json:"metadata,omitempty"`

	SentAt    *time.Time `bun:",nullzero" json:"sent_at,omitempty"`
	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

func (*Update) IsSent

func (u *Update) IsSent() bool

type UpdateContent

type UpdateContent string
type UpdateLink struct {
	ID        uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference Reference `json:"reference,omitempty"`
	UpdateID  uuid.UUID `json:"update_id,omitempty"`

	// Sometimes, you want to share a link containing a specific update
	// for a few minutes or seconds :)
	ExpiresAt *time.Time `json:"expires_at,omitempty" bun:",nullzero,notnull,default:current_timestamp"`

	CreatedAt     time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at" `
	UpdatedAt     time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at" `
	DeletedAt     *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`
	bun.BaseModel `json:"-"`
}

type UpdateMetadata

type UpdateMetadata struct {
}

type UpdateRecipient

type UpdateRecipient struct {
	ID         uuid.UUID       `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference  Reference       `json:"reference,omitempty"`
	UpdateID   uuid.UUID       `json:"update_id,omitempty"`
	ContactID  uuid.UUID       `json:"contact_id,omitempty"`
	ScheduleID uuid.UUID       `json:"schedule_id,omitempty"`
	Status     RecipientStatus `json:"status,omitempty"`

	UpdateRecipientStat *UpdateRecipientStat `json:"update_recipient_stat,omitempty" bun:"rel:has-one,join:id=recipient_id"`
	Contact             *Contact             `json:"contact,omitempty" bun:"rel:has-one,join:contact_id=id"`

	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`

	bun.BaseModel `json:"-"`
}

type UpdateRecipientLog

type UpdateRecipientLog struct {
	ID          uuid.UUID                  `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference   Reference                  `json:"reference,omitempty"`
	RecipientID uuid.UUID                  `json:"recipient_id,omitempty"`
	ProviderID  string                     `json:"provider_id,omitempty"`
	Provider    UpdateRecipientLogProvider `json:"provider,omitempty"`

	Recipient *UpdateRecipient `json:"recipient" bun:"rel:has-one,join:recipient_id=id"`

	CreatedAt     time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt     time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt     *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`
	bun.BaseModel `json:"-"`
}

type UpdateRecipientLogProvider

type UpdateRecipientLogProvider string

ENUM(resend,sendgrid,smtp)

const (
	// UpdateRecipientLogProviderResend is a UpdateRecipientLogProvider of type resend.
	UpdateRecipientLogProviderResend UpdateRecipientLogProvider = "resend"
	// UpdateRecipientLogProviderSendgrid is a UpdateRecipientLogProvider of type sendgrid.
	UpdateRecipientLogProviderSendgrid UpdateRecipientLogProvider = "sendgrid"
	// UpdateRecipientLogProviderSmtp is a UpdateRecipientLogProvider of type smtp.
	UpdateRecipientLogProviderSmtp UpdateRecipientLogProvider = "smtp"
)

func ParseUpdateRecipientLogProvider

func ParseUpdateRecipientLogProvider(name string) (UpdateRecipientLogProvider, error)

ParseUpdateRecipientLogProvider attempts to convert a string to a UpdateRecipientLogProvider.

func (UpdateRecipientLogProvider) IsValid

func (x UpdateRecipientLogProvider) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (UpdateRecipientLogProvider) String

String implements the Stringer interface.

type UpdateRecipientStat

type UpdateRecipientStat struct {
	ID          uuid.UUID        `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference   Reference        `json:"reference,omitempty"`
	RecipientID uuid.UUID        `json:"recipient_id,omitempty"`
	Recipient   *UpdateRecipient `json:"recipient" bun:"rel:has-one,join:recipient_id=id"`

	LastOpenedAt *time.Time `bun:",soft_delete,nullzero" json:"last_opened_at,omitempty"`
	HasReaction  bool       `json:"has_reaction,omitempty"`
	IsDelivered  bool       `json:"is_delivered,omitempty"`
	IsBounced    bool       `json:"is_bounced,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type UpdateSchedule

type UpdateSchedule struct {
	ID          uuid.UUID          `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference   Reference          `json:"reference,omitempty"`
	UpdateID    uuid.UUID          `json:"update_id,omitempty"`
	ScheduledBy uuid.UUID          `json:"scheduled_by,omitempty"`
	Status      UpdateSendSchedule `json:"status,omitempty"`
	UpdateType  UpdateType         `json:"update_type,omitempty"`

	// Time to send this update at?
	SendAt    time.Time `json:"send_at,omitempty"`
	CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`

	bun.BaseModel `json:"-"`
}

type UpdateSendSchedule

type UpdateSendSchedule string

ENUM(scheduled,cancelled,sent,failed,processing)

const (
	// UpdateSendScheduleScheduled is a UpdateSendSchedule of type scheduled.
	UpdateSendScheduleScheduled UpdateSendSchedule = "scheduled"
	// UpdateSendScheduleCancelled is a UpdateSendSchedule of type cancelled.
	UpdateSendScheduleCancelled UpdateSendSchedule = "cancelled"
	// UpdateSendScheduleSent is a UpdateSendSchedule of type sent.
	UpdateSendScheduleSent UpdateSendSchedule = "sent"
	// UpdateSendScheduleFailed is a UpdateSendSchedule of type failed.
	UpdateSendScheduleFailed UpdateSendSchedule = "failed"
	// UpdateSendScheduleProcessing is a UpdateSendSchedule of type processing.
	UpdateSendScheduleProcessing UpdateSendSchedule = "processing"
)

func ParseUpdateSendSchedule

func ParseUpdateSendSchedule(name string) (UpdateSendSchedule, error)

ParseUpdateSendSchedule attempts to convert a string to a UpdateSendSchedule.

func (UpdateSendSchedule) IsValid

func (x UpdateSendSchedule) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (UpdateSendSchedule) String

func (x UpdateSendSchedule) String() string

String implements the Stringer interface.

type UpdateStat

type UpdateStat struct {
	ID        uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference Reference `json:"reference,omitempty"`
	UpdateID  uuid.UUID `json:"update_id,omitempty"`

	TotalOpens     int64 `json:"total_opens,omitempty"`
	TotalReactions int64 `json:"total_reactions,omitempty"`
	TotalClicks    int64 `json:"total_clicks,omitempty"`
	TotalSent      int64 `json:"total_sent,omitempty"`
	UniqueOpens    int64 `json:"unique_opens,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type UpdateStatus

type UpdateStatus string

ENUM(draft,sent)

const (
	// UpdateStatusDraft is a UpdateStatus of type draft.
	UpdateStatusDraft UpdateStatus = "draft"
	// UpdateStatusSent is a UpdateStatus of type sent.
	UpdateStatusSent UpdateStatus = "sent"
)

func ParseUpdateStatus

func ParseUpdateStatus(name string) (UpdateStatus, error)

ParseUpdateStatus attempts to convert a string to a UpdateStatus.

func (UpdateStatus) IsValid

func (x UpdateStatus) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (UpdateStatus) String

func (x UpdateStatus) String() string

String implements the Stringer interface.

type UpdateType

type UpdateType string

ENUM(preview,live)

const (
	// UpdateTypePreview is a UpdateType of type preview.
	UpdateTypePreview UpdateType = "preview"
	// UpdateTypeLive is a UpdateType of type live.
	UpdateTypeLive UpdateType = "live"
)

func ParseUpdateType

func ParseUpdateType(name string) (UpdateType, error)

ParseUpdateType attempts to convert a string to a UpdateType.

func (UpdateType) IsValid

func (x UpdateType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (UpdateType) String

func (x UpdateType) String() string

String implements the Stringer interface.

type User

type User struct {
	ID    uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id"`
	Email Email     `json:"email"`

	FullName string        `json:"full_name"`
	Metadata *UserMetadata `json:"metadata" `

	Roles UserRoles `json:"roles" bun:"rel:has-many,join:id=user_id"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at" `
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at" `
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty" `

	bun.BaseModel `bun:"table:users" json:"-"`
}

func (*User) CanAccessWorkspace added in v0.3.1

func (u *User) CanAccessWorkspace(id uuid.UUID) bool

func (*User) HasWorkspace

func (u *User) HasWorkspace() bool

type UserMetadata

type UserMetadata struct {
	// Used to keep track of the last used workspace
	// In the instance of multiple workspaces
	// So when next the user logs in, we remember and take them to the
	// right place rather than always a list of all their workspaces and they
	// have to select one
	CurrentWorkspace uuid.UUID `json:"current_workspace"`
}

type UserRepository

type UserRepository interface {
	Create(context.Context, *User) error
	Update(context.Context, *User) error
	Get(context.Context, *FindUserOptions) (*User, error)
}

type UserRole

type UserRole struct {
	ID uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`

	Role Role `json:"role,omitempty"`

	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	WorkspaceID uuid.UUID `json:"workspace_id,omitempty"`
	UserID      uuid.UUID `json:"user_id,omitempty"`

	bun.BaseModel `bun:"table:roles" json:"-"`
}

type UserRoles

type UserRoles []*UserRole

func (UserRoles) IsEmpty

func (m UserRoles) IsEmpty() bool

type UuidGenerator

type UuidGenerator interface {
	Create() uuid.UUID
}

func NewGoogleUUID

func NewGoogleUUID() UuidGenerator

type Workspace

type Workspace struct {
	ID uuid.UUID `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`

	WorkspaceName string `json:"workspace_name,omitempty"`
	Reference     string `json:"reference,omitempty"`
	Timezone      string `json:"timezone"`
	Website       string `json:"website,omitempty"`
	LogoURL       string `json:"logo_url,omitempty"`

	// Not required
	// Dummy values work really if not using stripe
	StripeCustomerID     string `json:"stripe_customer_id,omitempty"`
	SubscriptionID       string `json:"subscription_id,omitempty"`
	IsSubscriptionActive bool   `json:"is_subscription_active,omitempty"`

	PlanID uuid.UUID `json:"plan_id,omitempty"`
	Plan   *Plan     `json:"plan,omitempty" bun:"rel:belongs-to,join:plan_id=id"`

	Metadata WorkspaceMetadata `json:"metadata,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty" bson:"created_at"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty" bson:"updated_at"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty" bson:"deleted_at"`

	bun.BaseModel `json:"-"`
}

func NewWorkspace

func NewWorkspace(name string, u *User,
	plan *Plan, reference string) *Workspace

func (*Workspace) MarshalJSON added in v0.5.0

func (w *Workspace) MarshalJSON() ([]byte, error)

type WorkspaceIntegration added in v0.3.1

type WorkspaceIntegration struct {
	ID            uuid.UUID    `bun:"type:uuid,default:uuid_generate_v4(),pk" json:"id,omitempty"`
	Reference     Reference    `json:"reference,omitempty"`
	WorkspaceID   uuid.UUID    `json:"workspace_id,omitempty"`
	IntegrationID uuid.UUID    `json:"integration_id,omitempty"`
	Integration   *Integration `bun:"rel:belongs-to,join:integration_id=id" json:"integration,omitempty"`

	// IsEnabled - this integration is enabled and data can be fetched
	IsEnabled bool `json:"is_enabled,omitempty"`

	// IsActive determines if the connection to the integration has been tested and works
	IsActive bool `json:"is_active,omitempty"`

	Metadata WorkspaceIntegrationMetadata `json:"metadata,omitempty"`

	CreatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"created_at,omitempty"`
	UpdatedAt time.Time  `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at,omitempty"`
	DeletedAt *time.Time `bun:",soft_delete,nullzero" json:"-,omitempty"`

	bun.BaseModel `json:"-"`
}

type WorkspaceIntegrationMetadata added in v0.3.1

type WorkspaceIntegrationMetadata struct {
	AccessToken   AccessToken `json:"access_token,omitempty"`
	LastFetchedAt time.Time   `json:"last_fetched_at,omitempty"`
}

type WorkspaceMetadata added in v0.4.0

type WorkspaceMetadata struct {
}

Directories

Path Synopsis
internal
pkg/jwttoken/mocks
Package mock_jwttoken is a generated GoMock package.
Package mock_jwttoken is a generated GoMock package.
pkg/socialauth/mocks
Package socialauth_mocks is a generated GoMock package.
Package socialauth_mocks is a generated GoMock package.
Package malak_mocks is a generated GoMock package.
Package malak_mocks is a generated GoMock package.
Package swagger Code generated by swaggo/swag.
Package swagger Code generated by swaggo/swag.
tools

Jump to

Keyboard shortcuts

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