sitemanager

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 6 Imported by: 0

README

site_manager

Registro de sitios, membresías, planes y solicitudes de acceso para clientes de Velty (misitio.velty.cl).

Este módulo es el dueño del site_id dentro del ecosistema de Velty.

Documentación

API Pública (Public API)

  • SiteByID(siteID string) (*Site, error): Devuelve el sitio con ese id.
  • CreatePlan(p *Plan) error: Registra un plan con sus límites.
  • PlanOf(siteID string) (Plan, error): Devuelve los límites del plan asignado al sitio.
Publicación de Sitios
  • MarkDirty(siteID string) error: Marca el sitio como pendiente de publicar (Dirty = true). Es idempotente.
  • DirtySites() (SiteList, error): Devuelve la lista de sitios pendientes de publicar, excluyendo los suspendidos.
  • MarkPublished(siteID, ref string) error: Registra una publicación exitosa, limpia Dirty, guarda la marca de tiempo PublishedAt y la referencia PublishedRef, y promueve el estado de draft a live.

Operaciones (Ops)

Op Name Recurso Acción Descripción
site_get site read Consulta de sitio por ID (filtra por pertenencia)
site_create site create Creación de sitio con asignación de propietario (201 Created)
access_request Authenticated - Registro de solicitud de acceso para usuarios autenticados

Archivos clave

  • site.go — Definición de Site, estados Status y transiciones válidas.
  • publish.go — Estado de publicación (MarkDirty, DirtySites, MarkPublished).
  • member.go — Definición de SiteMember, roles Role, y métodos MemberOf / SitesOf.
  • plan.go — Registro y consulta de límites del Plan (CreatePlan, PlanOf).
  • access.go — Definición de AccessRequest y solicitudes de acceso.
  • module.go — Estructura Module, constructor New, montado de MountOps y operaciones.
  • errors.go — Errores centinela del módulo.
  • models.go — Literales model.Definition para generación de código con ormc.
  • models_orm.go — Código ORM generado automáticamente.
  • tests/conformance_test.go — Suite completa de pruebas de conformidad e integración.
  • tests/publish_test.go — Pruebas del ciclo de publicación.

Inicio Rápido

package main

import (
	"github.com/tinywasm/orm"
	"github.com/tinywasm/storage/mem"
	sitemanager "github.com/veltylabs/site_manager"
)

func main() {
	db := orm.New(mem.New())
	sm, err := sitemanager.New(sitemanager.Deps{
		DB:  db,
		IDs: myIDGenerator,
	})
	if err != nil {
		panic(err)
	}

	role, ok := sm.MemberOf("user_123", "site_456")
	_ = role
	_ = ok
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotFound          = fmt.Err("site_manager", "not", "found")
	ErrAlreadyExists     = fmt.Err("site_manager", "already", "exists")
	ErrInvalidTransition = fmt.Err("site_manager", "invalid", "transition")
	ErrInvalidData       = fmt.Err("site_manager", "invalid", "data")
	ErrNilDependency     = fmt.Err("site_manager", "nil", "dependency")
)
View Source
var AccessRequestModel = model.Definition{
	Name: "access_request",
	Fields: model.Fields{
		{Name: "id", Type: model.Text(), DB: &model.FieldDB{PK: true}},
		{Name: "email", Type: model.Text(), NotNull: true},
		{Name: "name", Type: model.Text()},
		{Name: "message", Type: model.Text()},
		{Name: "created_at", Type: model.Int()},
		{Name: "status", Type: model.Int()},
	},
}
View Source
var AccessRequest_ = struct {
	Id        string
	Email     string
	Name      string
	Message   string
	CreatedAt string
	Status    string
}{
	Id:        "id",
	Email:     "email",
	Name:      "name",
	Message:   "message",
	CreatedAt: "created_at",
	Status:    "status",
}
View Source
var PlanModel = model.Definition{
	Name: "plan",
	Fields: model.Fields{
		{Name: "name", Type: model.Text(), DB: &model.FieldDB{PK: true}},
		{Name: "max_pages", Type: model.Int()},
		{Name: "max_images", Type: model.Int()},
		{Name: "custom_domain", Type: model.Bool()},
	},
}
View Source
var Plan_ = struct {
	Name         string
	MaxPages     string
	MaxImages    string
	CustomDomain string
}{
	Name:         "name",
	MaxPages:     "max_pages",
	MaxImages:    "max_images",
	CustomDomain: "custom_domain",
}
View Source
var SiteMemberModel = model.Definition{
	Name: "site_member",
	Fields: model.Fields{
		{Name: "id", Type: model.Text(), DB: &model.FieldDB{PK: true}},
		{Name: "site_id", Type: model.Text(), NotNull: true, Ref: &SiteModel, DB: &model.FieldDB{RefColumn: "id"}},
		{Name: "user_id", Type: model.Text(), NotNull: true},
		{Name: "role", Type: model.Int()},
	},
}
View Source
var SiteMember_ = struct {
	Id     string
	SiteId string
	UserId string
	Role   string
}{
	Id:     "id",
	SiteId: "site_id",
	UserId: "user_id",
	Role:   "role",
}
View Source
var SiteModel = model.Definition{
	Name: "site",
	Fields: model.Fields{
		{Name: "id", Type: model.Text(), DB: &model.FieldDB{PK: true}},
		{Name: "slug", Type: model.Text(), NotNull: true, DB: &model.FieldDB{Unique: true}},
		{Name: "name", Type: model.Text(), NotNull: true},
		{Name: "domain", Type: model.Text()},
		{Name: "domain_expires_at", Type: model.Int()},
		{Name: "plan", Type: model.Text()},
		{Name: "theme", Type: model.Text(), NotNull: true},
		{Name: "status", Type: model.Int()},
		{Name: "dirty", Type: model.Bool()},
		{Name: "published_at", Type: model.Int()},
		{Name: "published_ref", Type: model.Text()},
	},
}
View Source
var Site_ = struct {
	Id              string
	Slug            string
	Name            string
	Domain          string
	DomainExpiresAt string
	Plan            string
	Theme           string
	Status          string
	Dirty           string
	PublishedAt     string
	PublishedRef    string
}{
	Id:              "id",
	Slug:            "slug",
	Name:            "name",
	Domain:          "domain",
	DomainExpiresAt: "domain_expires_at",
	Plan:            "plan",
	Theme:           "theme",
	Status:          "status",
	Dirty:           "dirty",
	PublishedAt:     "published_at",
	PublishedRef:    "published_ref",
}

Functions

func ValidateTransition added in v0.1.0

func ValidateTransition(from, to Status) error

Types

type AccessRequest added in v0.1.0

type AccessRequest struct {
	Id        string
	Email     string
	Name      string
	Message   string
	CreatedAt int64
	Status    int64
}

func ReadOneAccessRequest added in v0.1.0

func ReadOneAccessRequest(qb *orm.QB, model *AccessRequest) (*AccessRequest, error)

func (*AccessRequest) DecodeFields added in v0.1.0

func (m *AccessRequest) DecodeFields(r model.FieldReader)

func (*AccessRequest) EncodeFields added in v0.1.0

func (m *AccessRequest) EncodeFields(w model.FieldWriter)

func (*AccessRequest) IsNil added in v0.1.0

func (m *AccessRequest) IsNil() bool

func (*AccessRequest) ModelName added in v0.1.0

func (m *AccessRequest) ModelName() string

func (*AccessRequest) Pointers added in v0.1.0

func (m *AccessRequest) Pointers() []any

func (*AccessRequest) Schema added in v0.1.0

func (m *AccessRequest) Schema() []model.Field

func (*AccessRequest) Validate added in v0.1.0

func (m *AccessRequest) Validate(action byte) error

type AccessRequestList added in v0.1.0

type AccessRequestList []*AccessRequest

func ReadAllAccessRequest added in v0.1.0

func ReadAllAccessRequest(qb *orm.QB) (AccessRequestList, error)

func (*AccessRequestList) Append added in v0.1.0

func (s *AccessRequestList) Append() model.Fielder

func (*AccessRequestList) At added in v0.1.0

func (*AccessRequestList) DecodeFields added in v0.1.0

func (s *AccessRequestList) DecodeFields(_ model.FieldReader)

func (*AccessRequestList) EncodeFields added in v0.1.0

func (s *AccessRequestList) EncodeFields(_ model.FieldWriter)

func (*AccessRequestList) IsNil added in v0.1.0

func (s *AccessRequestList) IsNil() bool

func (*AccessRequestList) Len added in v0.1.0

func (s *AccessRequestList) Len() int

func (*AccessRequestList) Pointers added in v0.1.0

func (s *AccessRequestList) Pointers() []any

func (*AccessRequestList) Schema added in v0.1.0

func (s *AccessRequestList) Schema() []model.Field

type Deps added in v0.1.0

type Deps struct {
	DB  *orm.DB
	IDs model.IDGenerator
}

type Module added in v0.1.0

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

func New

func New(d Deps) (*Module, error)

func (*Module) AcceptRequest added in v0.1.0

func (m *Module) AcceptRequest(id string) error

AcceptRequest accepts an access request by setting its status to RequestAccepted. Note: Accepting an AccessRequest creates ZERO SiteMember entries.

func (*Module) AddMember added in v0.1.0

func (m *Module) AddMember(siteID, userID string, role Role) (*SiteMember, error)

AddMember adds a user membership to a site.

func (*Module) CreatePlan added in v0.3.0

func (m *Module) CreatePlan(p *Plan) error

CreatePlan registra un plan con sus límites.

func (*Module) CreateSite added in v0.1.0

func (m *Module) CreateSite(site *Site) error

CreateSite creates a new site ensuring slug uniqueness.

func (*Module) DirtySites added in v0.2.0

func (m *Module) DirtySites() (SiteList, error)

DirtySites devuelve los sitios pendientes de publicar, excluyendo los suspendidos.

func (*Module) MarkDirty added in v0.2.0

func (m *Module) MarkDirty(siteID string) error

MarkDirty marca el sitio como pendiente de publicar. Es idempotente: si ya estaba sucio no vuelve a escribir.

func (*Module) MarkPublished added in v0.2.0

func (m *Module) MarkPublished(siteID, ref string) error

MarkPublished registra una publicación exitosa: limpia Dirty, guarda cuándo y con qué referencia, y promueve el sitio a Live si era un borrador.

Ventana conocida: si el cliente guarda contenido mientras CI construye, MarkPublished limpiará un Dirty que corresponde a un cambio más nuevo, y ese cambio esperará al cron diario de publicación. Resolverlo de verdad exige versionar el contenido, que hoy no existe.

func (*Module) MemberOf added in v0.1.0

func (m *Module) MemberOf(userID, siteID string) (Role, bool)

MemberOf responds whether a user can touch a site, and with what role. It is the ONLY way to answer this question.

func (*Module) ModelName added in v0.1.0

func (m *Module) ModelName() string

func (*Module) MountOps added in v0.1.0

func (m *Module) MountOps(reg router.OpRegistry)

func (*Module) PendingRequests added in v0.4.0

func (m *Module) PendingRequests() ([]AccessRequest, error)

PendingRequests devuelve las solicitudes de acceso sin resolver, de la más antigua a la más reciente. Nota: Deja el orden natural de inserción que en mem/D1 coincide con el de creación.

func (*Module) PlanOf added in v0.3.0

func (m *Module) PlanOf(siteID string) (Plan, error)

PlanOf devuelve los límites del plan asignado al sitio.

func (*Module) Request added in v0.1.0

func (m *Module) Request(email, name, message string) (req AccessRequest, created bool, err error)

Request registers an access request. If a pending request already exists for that email, returns the existing one and created=false.

func (*Module) RequestByID added in v0.4.0

func (m *Module) RequestByID(id string) (AccessRequest, error)

RequestByID devuelve la solicitud de acceso con ese id.

func (*Module) SiteByID added in v0.3.0

func (m *Module) SiteByID(siteID string) (*Site, error)

SiteByID devuelve el sitio con ese id.

func (*Module) SitesOf added in v0.1.0

func (m *Module) SitesOf(userID string) ([]Site, error)

SitesOf returns the sites where the user has membership. Can return empty slice: normal state, not an error.

func (*Module) UpdateSiteStatus added in v0.1.0

func (m *Module) UpdateSiteStatus(siteID string, newStatus Status) error

UpdateSiteStatus updates a site's status following valid state transitions.

type Plan added in v0.1.0

type Plan struct {
	Name         string
	MaxPages     int64
	MaxImages    int64
	CustomDomain bool
}

func ReadOnePlan added in v0.1.0

func ReadOnePlan(qb *orm.QB, model *Plan) (*Plan, error)

func (*Plan) DecodeFields added in v0.1.0

func (m *Plan) DecodeFields(r model.FieldReader)

func (*Plan) EncodeFields added in v0.1.0

func (m *Plan) EncodeFields(w model.FieldWriter)

func (*Plan) IsNil added in v0.1.0

func (m *Plan) IsNil() bool

func (*Plan) ModelName added in v0.1.0

func (m *Plan) ModelName() string

func (*Plan) Pointers added in v0.1.0

func (m *Plan) Pointers() []any

func (*Plan) Schema added in v0.1.0

func (m *Plan) Schema() []model.Field

func (*Plan) Validate added in v0.1.0

func (m *Plan) Validate(action byte) error

type PlanList added in v0.1.0

type PlanList []*Plan

func ReadAllPlan added in v0.1.0

func ReadAllPlan(qb *orm.QB) (PlanList, error)

func (*PlanList) Append added in v0.1.0

func (s *PlanList) Append() model.Fielder

func (*PlanList) At added in v0.1.0

func (s *PlanList) At(i int) model.Fielder

func (*PlanList) DecodeFields added in v0.1.0

func (s *PlanList) DecodeFields(_ model.FieldReader)

func (*PlanList) EncodeFields added in v0.1.0

func (s *PlanList) EncodeFields(_ model.FieldWriter)

func (*PlanList) IsNil added in v0.1.0

func (s *PlanList) IsNil() bool

func (*PlanList) Len added in v0.1.0

func (s *PlanList) Len() int

func (*PlanList) Pointers added in v0.1.0

func (s *PlanList) Pointers() []any

func (*PlanList) Schema added in v0.1.0

func (s *PlanList) Schema() []model.Field

type RequestStatus added in v0.1.0

type RequestStatus uint8
const (
	RequestPending RequestStatus = iota // ZERO VALUE
	RequestAccepted
	RequestRejected
)

func (RequestStatus) String added in v0.1.0

func (s RequestStatus) String() string

type Role added in v0.1.0

type Role uint8
const (
	RoleViewer Role = iota // ZERO VALUE — el permiso más bajo
	RoleEditor
	RoleOwner
)

func (Role) String added in v0.1.0

func (r Role) String() string

type Site added in v0.1.0

type Site struct {
	Id              string
	Slug            string
	Name            string
	Domain          string
	DomainExpiresAt int64
	Plan            string
	Theme           string
	Status          int64
	Dirty           bool
	PublishedAt     int64
	PublishedRef    string
}

func ReadOneSite added in v0.1.0

func ReadOneSite(qb *orm.QB, model *Site) (*Site, error)

func (*Site) DecodeFields added in v0.1.0

func (m *Site) DecodeFields(r model.FieldReader)

func (*Site) EncodeFields added in v0.1.0

func (m *Site) EncodeFields(w model.FieldWriter)

func (*Site) IsNil added in v0.1.0

func (m *Site) IsNil() bool

func (*Site) ModelName added in v0.1.0

func (m *Site) ModelName() string

func (*Site) Pointers added in v0.1.0

func (m *Site) Pointers() []any

func (*Site) Schema added in v0.1.0

func (m *Site) Schema() []model.Field

func (*Site) Validate added in v0.1.0

func (m *Site) Validate(action byte) error

type SiteList added in v0.1.0

type SiteList []*Site

func ReadAllSite added in v0.1.0

func ReadAllSite(qb *orm.QB) (SiteList, error)

func (*SiteList) Append added in v0.1.0

func (s *SiteList) Append() model.Fielder

func (*SiteList) At added in v0.1.0

func (s *SiteList) At(i int) model.Fielder

func (*SiteList) DecodeFields added in v0.1.0

func (s *SiteList) DecodeFields(_ model.FieldReader)

func (*SiteList) EncodeFields added in v0.1.0

func (s *SiteList) EncodeFields(_ model.FieldWriter)

func (*SiteList) IsNil added in v0.1.0

func (s *SiteList) IsNil() bool

func (*SiteList) Len added in v0.1.0

func (s *SiteList) Len() int

func (*SiteList) Pointers added in v0.1.0

func (s *SiteList) Pointers() []any

func (*SiteList) Schema added in v0.1.0

func (s *SiteList) Schema() []model.Field

type SiteMember added in v0.1.0

type SiteMember struct {
	Id     string
	SiteId string
	UserId string
	Role   int64
}

func ReadOneSiteMember added in v0.1.0

func ReadOneSiteMember(qb *orm.QB, model *SiteMember) (*SiteMember, error)

func (*SiteMember) DecodeFields added in v0.1.0

func (m *SiteMember) DecodeFields(r model.FieldReader)

func (*SiteMember) EncodeFields added in v0.1.0

func (m *SiteMember) EncodeFields(w model.FieldWriter)

func (*SiteMember) IsNil added in v0.1.0

func (m *SiteMember) IsNil() bool

func (*SiteMember) ModelName added in v0.1.0

func (m *SiteMember) ModelName() string

func (*SiteMember) Pointers added in v0.1.0

func (m *SiteMember) Pointers() []any

func (*SiteMember) Schema added in v0.1.0

func (m *SiteMember) Schema() []model.Field

func (*SiteMember) SchemaExt added in v0.1.0

func (m *SiteMember) SchemaExt() []model.FieldExt

func (*SiteMember) Validate added in v0.1.0

func (m *SiteMember) Validate(action byte) error

type SiteMemberList added in v0.1.0

type SiteMemberList []*SiteMember

func ReadAllSiteMember added in v0.1.0

func ReadAllSiteMember(qb *orm.QB) (SiteMemberList, error)

func (*SiteMemberList) Append added in v0.1.0

func (s *SiteMemberList) Append() model.Fielder

func (*SiteMemberList) At added in v0.1.0

func (s *SiteMemberList) At(i int) model.Fielder

func (*SiteMemberList) DecodeFields added in v0.1.0

func (s *SiteMemberList) DecodeFields(_ model.FieldReader)

func (*SiteMemberList) EncodeFields added in v0.1.0

func (s *SiteMemberList) EncodeFields(_ model.FieldWriter)

func (*SiteMemberList) IsNil added in v0.1.0

func (s *SiteMemberList) IsNil() bool

func (*SiteMemberList) Len added in v0.1.0

func (s *SiteMemberList) Len() int

func (*SiteMemberList) Pointers added in v0.1.0

func (s *SiteMemberList) Pointers() []any

func (*SiteMemberList) Schema added in v0.1.0

func (s *SiteMemberList) Schema() []model.Field

type Status added in v0.1.0

type Status uint8
const (
	StatusDraft Status = iota // ZERO VALUE — no publicado
	StatusLive
	StatusSuspended
)

func (Status) String added in v0.1.0

func (s Status) String() string

Jump to

Keyboard shortcuts

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