feat: first commit

This commit is contained in:
sittichok Ouamsiri
2026-06-15 21:25:57 +07:00
commit 3395ab6dd3
88 changed files with 10034 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
package domain
import "errors"
// Sentinel errors crossing the port boundary. Adapters translate infra errors
// into these; HTTP layer maps these to status codes.
var (
ErrNotFound = errors.New("not found")
ErrCodeTaken = errors.New("code already taken")
ErrReserved = errors.New("code is reserved")
ErrInvalidURL = errors.New("invalid destination url")
ErrInvalidAlias = errors.New("invalid custom alias")
ErrInvalidPin = errors.New("pin must be exactly 6 digits")
ErrUnauthorized = errors.New("authentication required")
ErrForbidden = errors.New("not allowed")
ErrPinRequired = errors.New("pin required")
ErrPinInvalid = errors.New("incorrect pin")
)
+49
View File
@@ -0,0 +1,49 @@
package domain
import "time"
// Mode is how a short code was produced.
type Mode string
const (
ModeRandom Mode = "random"
ModeMemorable Mode = "memorable"
ModeCustom Mode = "custom"
)
// DayCount is a single day's click total.
type DayCount struct {
Date string `json:"date"`
Count int64 `json:"count"`
}
// Link is the aggregate root: a short code pointing at a destination.
type Link struct {
ID string
Code string
LongURL string
Mode Mode
HasPin bool
PinHash string // bcrypt hash; never serialized out of the system
OwnerID string // empty for anonymous links
CreatedAt time.Time
TotalClicks int64
Last7Days []DayCount
}
// OwnerStats are the dashboard aggregate tiles, computed in the DB so the
// client never has to fetch every link to total them up.
type OwnerStats struct {
TotalLinks int `json:"totalLinks"`
TotalClicks int64 `json:"totalClicks"`
WeekClicks int64 `json:"weekClicks"`
}
// User is an authenticated account, keyed by (provider, subject).
type User struct {
ID string
Email string
Name string
Provider string
Subject string
}