feat: game lobby service
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// gameIDPrefix is the mandatory opaque-identifier prefix for one Game Lobby
|
||||
// game record.
|
||||
const gameIDPrefix = "game-"
|
||||
|
||||
// applicationIDPrefix is the mandatory opaque-identifier prefix for one
|
||||
// Game Lobby application record.
|
||||
const applicationIDPrefix = "application-"
|
||||
|
||||
// inviteIDPrefix is the mandatory opaque-identifier prefix for one Game
|
||||
// Lobby invite record.
|
||||
const inviteIDPrefix = "invite-"
|
||||
|
||||
// membershipIDPrefix is the mandatory opaque-identifier prefix for one
|
||||
// Game Lobby membership record.
|
||||
const membershipIDPrefix = "membership-"
|
||||
|
||||
// GameID identifies one game record owned by Game Lobby Service. The value
|
||||
// is opaque and stable; only its `game-*` prefix is observable to callers.
|
||||
type GameID string
|
||||
|
||||
// String returns GameID as its stored identifier string.
|
||||
func (id GameID) String() string {
|
||||
return string(id)
|
||||
}
|
||||
|
||||
// IsZero reports whether GameID does not contain a usable value.
|
||||
func (id GameID) IsZero() bool {
|
||||
return strings.TrimSpace(string(id)) == ""
|
||||
}
|
||||
|
||||
// Validate reports whether GameID is non-empty, already trimmed, and carries
|
||||
// the frozen `game-*` opaque prefix.
|
||||
func (id GameID) Validate() error {
|
||||
return validatePrefixedID("game id", string(id), gameIDPrefix)
|
||||
}
|
||||
|
||||
// ApplicationID identifies one application record owned by Game Lobby
|
||||
// Service. The value is opaque and stable; only its `application-*` prefix
|
||||
// is observable to callers.
|
||||
type ApplicationID string
|
||||
|
||||
// String returns ApplicationID as its stored identifier string.
|
||||
func (id ApplicationID) String() string {
|
||||
return string(id)
|
||||
}
|
||||
|
||||
// IsZero reports whether ApplicationID does not contain a usable value.
|
||||
func (id ApplicationID) IsZero() bool {
|
||||
return strings.TrimSpace(string(id)) == ""
|
||||
}
|
||||
|
||||
// Validate reports whether ApplicationID is non-empty, already trimmed, and
|
||||
// carries the frozen `application-*` opaque prefix.
|
||||
func (id ApplicationID) Validate() error {
|
||||
return validatePrefixedID("application id", string(id), applicationIDPrefix)
|
||||
}
|
||||
|
||||
// InviteID identifies one invite record owned by Game Lobby Service. The
|
||||
// value is opaque and stable; only its `invite-*` prefix is observable to
|
||||
// callers.
|
||||
type InviteID string
|
||||
|
||||
// String returns InviteID as its stored identifier string.
|
||||
func (id InviteID) String() string {
|
||||
return string(id)
|
||||
}
|
||||
|
||||
// IsZero reports whether InviteID does not contain a usable value.
|
||||
func (id InviteID) IsZero() bool {
|
||||
return strings.TrimSpace(string(id)) == ""
|
||||
}
|
||||
|
||||
// Validate reports whether InviteID is non-empty, already trimmed, and
|
||||
// carries the frozen `invite-*` opaque prefix.
|
||||
func (id InviteID) Validate() error {
|
||||
return validatePrefixedID("invite id", string(id), inviteIDPrefix)
|
||||
}
|
||||
|
||||
// MembershipID identifies one membership record owned by Game Lobby
|
||||
// Service. The value is opaque and stable; only its `membership-*` prefix
|
||||
// is observable to callers.
|
||||
type MembershipID string
|
||||
|
||||
// String returns MembershipID as its stored identifier string.
|
||||
func (id MembershipID) String() string {
|
||||
return string(id)
|
||||
}
|
||||
|
||||
// IsZero reports whether MembershipID does not contain a usable value.
|
||||
func (id MembershipID) IsZero() bool {
|
||||
return strings.TrimSpace(string(id)) == ""
|
||||
}
|
||||
|
||||
// Validate reports whether MembershipID is non-empty, already trimmed, and
|
||||
// carries the frozen `membership-*` opaque prefix.
|
||||
func (id MembershipID) Validate() error {
|
||||
return validatePrefixedID("membership id", string(id), membershipIDPrefix)
|
||||
}
|
||||
|
||||
// validatePrefixedID reports whether raw is a non-empty, trimmed identifier
|
||||
// with the given opaque prefix and a non-empty suffix. The label is used to
|
||||
// format error messages.
|
||||
func validatePrefixedID(label, raw, prefix string) error {
|
||||
switch {
|
||||
case strings.TrimSpace(raw) == "":
|
||||
return fmt.Errorf("%s must not be empty", label)
|
||||
case strings.TrimSpace(raw) != raw:
|
||||
return fmt.Errorf("%s must not contain surrounding whitespace", label)
|
||||
case !strings.HasPrefix(raw, prefix):
|
||||
return fmt.Errorf("%s must start with %q", label, prefix)
|
||||
case len(raw) == len(prefix):
|
||||
return fmt.Errorf("%s must carry a non-empty suffix after %q", label, prefix)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Package common defines shared value objects used across the Game Lobby
|
||||
// Service domain model.
|
||||
//
|
||||
// The package exposes the opaque identifier types used by the game,
|
||||
// application, invite, and membership entities. Each identifier validates
|
||||
// its own frozen prefix and rejects surrounding whitespace so higher-level
|
||||
// domains can trust the value without re-checking.
|
||||
package common
|
||||
Reference in New Issue
Block a user