nomadcode/services/core/internal/protosocket/envelope.go
toki e36db7281b feat: update project rules, roadmap, and core service changes
- Update agent-ops project rules and roadmap files
- Add proto-socket infrastructure communication rail milestone
- Update Flutter pubspec.lock and contracts notes
- Enhance core service: config, HTTP middleware, router
- Add notification module improvements
- Add protosocket internal package
2026-05-30 19:32:48 +09:00

121 lines
2.9 KiB
Go

package protosocket
import (
"fmt"
"google.golang.org/protobuf/types/known/structpb"
)
const ProtocolVersion = "nomadcode.proto-socket.v1"
type Envelope struct {
ProtocolVersion string `json:"protocol_version"`
ID string `json:"id"`
CorrelationID string `json:"correlation_id"`
Type string `json:"type"`
Channel string `json:"channel"`
Action string `json:"action"`
Actor map[string]any `json:"actor,omitempty"`
Auth map[string]any `json:"auth,omitempty"`
Payload map[string]any `json:"payload,omitempty"`
Error *EnvelopeError `json:"error,omitempty"`
Meta map[string]any `json:"meta,omitempty"`
}
type EnvelopeError struct {
Code string `json:"code"`
Message string `json:"message"`
Retryable bool `json:"retryable"`
Details map[string]any `json:"details,omitempty"`
}
func (e Envelope) ToStruct() (*structpb.Struct, error) {
m := map[string]any{
"protocol_version": e.ProtocolVersion,
"id": e.ID,
"correlation_id": e.CorrelationID,
"type": e.Type,
"channel": e.Channel,
"action": e.Action,
}
if e.Actor != nil {
m["actor"] = e.Actor
}
if e.Auth != nil {
m["auth"] = e.Auth
}
if e.Payload != nil {
m["payload"] = e.Payload
}
if e.Meta != nil {
m["meta"] = e.Meta
}
if e.Error != nil {
errMap := map[string]any{
"code": e.Error.Code,
"message": e.Error.Message,
"retryable": e.Error.Retryable,
}
if e.Error.Details != nil {
errMap["details"] = e.Error.Details
}
m["error"] = errMap
}
return structpb.NewStruct(m)
}
func EnvelopeFromStruct(s *structpb.Struct) (Envelope, error) {
var env Envelope
if s == nil {
return env, fmt.Errorf("nil struct")
}
m := s.AsMap()
if v, ok := m["protocol_version"].(string); ok {
env.ProtocolVersion = v
}
if v, ok := m["id"].(string); ok {
env.ID = v
}
if v, ok := m["correlation_id"].(string); ok {
env.CorrelationID = v
}
if v, ok := m["type"].(string); ok {
env.Type = v
}
if v, ok := m["channel"].(string); ok {
env.Channel = v
}
if v, ok := m["action"].(string); ok {
env.Action = v
}
if v, ok := m["actor"].(map[string]any); ok {
env.Actor = v
}
if v, ok := m["auth"].(map[string]any); ok {
env.Auth = v
}
if v, ok := m["payload"].(map[string]any); ok {
env.Payload = v
}
if v, ok := m["meta"].(map[string]any); ok {
env.Meta = v
}
if errVal, ok := m["error"].(map[string]any); ok {
var envErr EnvelopeError
if code, ok := errVal["code"].(string); ok {
envErr.Code = code
}
if msg, ok := errVal["message"].(string); ok {
envErr.Message = msg
}
if ret, ok := errVal["retryable"].(bool); ok {
envErr.Retryable = ret
}
if details, ok := errVal["details"].(map[string]any); ok {
envErr.Details = details
}
env.Error = &envErr
}
return env, nil
}