package dto import ( "time" "browser.local/platform/domain" ) type GameClientBridgeQueueRequest struct { ProfileKey string `json:"profileKey"` CommandType string `json:"commandType"` Payload map[string]any `json:"payload"` IdempotencyKey string `json:"idempotencyKey"` Priority int `json:"priority,omitempty"` ExpiresAt time.Time `json:"expiresAt"` } type GameClientBridgeClaimRequest struct { SessionToken string `json:"sessionToken"` Limit int `json:"limit,omitempty"` } type GameClientBridgeAckRequest struct { SessionToken string `json:"sessionToken"` FencingToken uint64 `json:"fencingToken"` } type GameClientBridgeResultRequest struct { SessionToken string `json:"sessionToken"` FencingToken uint64 `json:"fencingToken"` Status string `json:"status"` Summary string `json:"summary,omitempty"` Payload map[string]any `json:"payload,omitempty"` } type GameClientBridgeSnapshotIngestRequest struct { SessionToken string `json:"sessionToken"` Type string `json:"type"` SchemaVersion string `json:"schemaVersion"` StreamKey string `json:"streamKey"` Sequence uint64 `json:"sequence"` ObservedAt time.Time `json:"observedAt"` Payload map[string]any `json:"payload"` KeepForSeconds int `json:"keepForSeconds"` MaxRecords int `json:"maxRecords,omitempty"` } type GameClientBridgeCancelRequest struct { Reason string `json:"reason,omitempty"` } type GameClientBridgeSnapshotQuery struct { ProfileKey string `json:"profileKey,omitempty"` Type string `json:"type,omitempty"` StreamKey string `json:"streamKey,omitempty"` ObservedAfter time.Time `json:"observedAfter,omitempty"` Limit int `json:"limit,omitempty"` } // GameClientBridgeCommandResultResponse is the browser-safe projection of a // terminal command result. Result payloads pass the same bounded JSON // validation as command inputs before they can be persisted. type GameClientBridgeCommandResultResponse struct { Status string `json:"status"` Summary string `json:"summary,omitempty"` Payload map[string]any `json:"payload,omitempty"` CompletedAt time.Time `json:"completedAt"` } type GameClientBridgeCommandCancellationResponse struct { RequestedBy string `json:"requestedBy,omitempty"` Reason string `json:"reason,omitempty"` CancelledAt time.Time `json:"cancelledAt"` } type GameClientBridgeCommandResponse struct { ID string `json:"id"` ServerInstanceID string `json:"serverInstanceId"` PluginID string `json:"pluginId"` ProfileKey string `json:"profileKey"` CommandType string `json:"commandType"` Priority int `json:"priority"` State string `json:"state"` ApprovalState string `json:"approvalState"` RequesterID string `json:"requesterId,omitempty"` ResultSummary string `json:"resultSummary,omitempty"` Result *GameClientBridgeCommandResultResponse `json:"result,omitempty"` Cancellation *GameClientBridgeCommandCancellationResponse `json:"cancellation,omitempty"` AuditReferences []string `json:"auditReferences,omitempty"` ExpiresAt time.Time `json:"expiresAt"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` CompletedAt time.Time `json:"completedAt,omitempty"` } type GameClientBridgeRetentionResponse struct { KeepForSeconds int `json:"keepForSeconds"` MaxRecords int `json:"maxRecords,omitempty"` } type GameClientBridgeSnapshotResponse struct { ID string `json:"id"` ServerInstanceID string `json:"serverInstanceId"` PluginID string `json:"pluginId"` ProfileKey string `json:"profileKey"` Type string `json:"type"` SchemaVersion string `json:"schemaVersion"` StreamKey string `json:"streamKey"` Sequence uint64 `json:"sequence"` ObservedAt time.Time `json:"observedAt"` Payload map[string]any `json:"payload"` Retention GameClientBridgeRetentionResponse `json:"retention"` AuditReferences []string `json:"auditReferences,omitempty"` CreatedAt time.Time `json:"createdAt"` ExpiresAt time.Time `json:"expiresAt"` } type GameClientBridgeCommandListResponse struct { Items []GameClientBridgeCommandResponse `json:"items"` Count int `json:"count"` } type GameClientBridgeSnapshotListResponse struct { Items []GameClientBridgeSnapshotResponse `json:"items"` Count int `json:"count"` } type GameClientBridgeClaimedCommandResponse struct { ID string `json:"id"` ProfileKey string `json:"profileKey"` CommandType string `json:"commandType"` Payload map[string]any `json:"payload"` Priority int `json:"priority"` FencingToken uint64 `json:"fencingToken"` ClaimedAt time.Time `json:"claimedAt"` LeaseExpiresAt time.Time `json:"leaseExpiresAt"` ExpiresAt time.Time `json:"expiresAt"` } type GameClientBridgeClaimResponse struct { Items []GameClientBridgeClaimedCommandResponse `json:"items"` Count int `json:"count"` } // GameClientBridgeClaimBatchResponse is kept as a descriptive alias for API // handlers that name the operation after its bounded batch semantics. type GameClientBridgeClaimBatchResponse = GameClientBridgeClaimResponse type GameClientBridgeAckResponse struct { CommandID string `json:"commandId"` State string `json:"state"` FencingToken uint64 `json:"fencingToken"` AcknowledgedAt time.Time `json:"acknowledgedAt"` } type GameClientBridgeResultResponse struct { CommandID string `json:"commandId"` State string `json:"state"` Result GameClientBridgeCommandResultResponse `json:"result"` UpdatedAt time.Time `json:"updatedAt"` CompletedAt time.Time `json:"completedAt"` } type GameClientBridgeCancelResponse struct { CommandID string `json:"commandId"` State string `json:"state"` Cancellation GameClientBridgeCommandCancellationResponse `json:"cancellation"` AuditReferences []string `json:"auditReferences,omitempty"` UpdatedAt time.Time `json:"updatedAt"` } type GameClientBridgeSnapshotIngestResponse struct { SnapshotID string `json:"snapshotId"` ProfileKey string `json:"profileKey"` Type string `json:"type"` SchemaVersion string `json:"schemaVersion"` StreamKey string `json:"streamKey"` Sequence uint64 `json:"sequence"` AcceptedAt time.Time `json:"acceptedAt"` ExpiresAt time.Time `json:"expiresAt"` } type GameClientBridgeAuditReferenceResponse struct { ID string `json:"id"` CommandID string `json:"commandId,omitempty"` SnapshotID string `json:"snapshotId,omitempty"` AuditEventID string `json:"auditEventId"` CreatedAt time.Time `json:"createdAt"` } type GameClientBridgeAuditReferenceListResponse struct { Items []GameClientBridgeAuditReferenceResponse `json:"items"` Count int `json:"count"` } type GameClientBridgeProfileDeclarationResponse struct { PluginID string `json:"pluginId"` ProfileKey string `json:"profileKey"` Available bool `json:"available"` Reason string `json:"reason,omitempty"` CommandTypes []string `json:"commandTypes"` SnapshotTypes []string `json:"snapshotTypes"` QueryTemplateKeys []string `json:"queryTemplateKeys"` HandlerTypes []string `json:"handlerTypes"` EventProducerTypes []string `json:"eventProducerTypes"` } type GameClientBridgeFeatureAvailabilityResponse struct { Key string `json:"key"` Available bool `json:"available"` Reason string `json:"reason,omitempty"` } type GameClientBridgeStatusResponse struct { ServerInstanceID string `json:"serverInstanceId"` PluginID string `json:"pluginId"` Available bool `json:"available"` Reason string `json:"reason,omitempty"` Profiles []GameClientBridgeProfileDeclarationResponse `json:"profiles"` Features []GameClientBridgeFeatureAvailabilityResponse `json:"features"` } func (request GameClientBridgeQueueRequest) ToDomain(serverID, pluginID string) domain.GameClientBridgeQueueRequest { return domain.GameClientBridgeQueueRequest{ServerInstanceID: serverID, PluginID: pluginID, ProfileKey: request.ProfileKey, CommandType: request.CommandType, Payload: domain.CopyGameClientBridgePayload(request.Payload), IdempotencyKey: request.IdempotencyKey, Priority: request.Priority, ExpiresAt: request.ExpiresAt} } func (request GameClientBridgeClaimRequest) ToDomain() domain.GameClientBridgeClaimRequest { return domain.GameClientBridgeClaimRequest{SessionToken: request.SessionToken, Limit: request.Limit} } func (request GameClientBridgeAckRequest) ToDomain(commandID string) domain.GameClientBridgeAckRequest { return domain.GameClientBridgeAckRequest{SessionToken: request.SessionToken, CommandID: commandID, FencingToken: request.FencingToken} } func (request GameClientBridgeResultRequest) ToDomain(commandID string) domain.GameClientBridgeResultRequest { return domain.GameClientBridgeResultRequest{SessionToken: request.SessionToken, CommandID: commandID, FencingToken: request.FencingToken, Status: domain.GameClientBridgeResultStatus(request.Status), Summary: request.Summary, Payload: domain.CopyGameClientBridgePayload(request.Payload)} } func (request GameClientBridgeCancelRequest) ToDomain(commandID string) domain.GameClientBridgeCancelRequest { return domain.GameClientBridgeCancelRequest{CommandID: commandID, Reason: request.Reason} } func (request GameClientBridgeSnapshotIngestRequest) ToDomain() domain.GameClientBridgeSnapshotIngestRequest { return domain.GameClientBridgeSnapshotIngestRequest{SessionToken: request.SessionToken, Type: request.Type, SchemaVersion: request.SchemaVersion, StreamKey: request.StreamKey, Sequence: request.Sequence, ObservedAt: request.ObservedAt, Payload: domain.CopyGameClientBridgePayload(request.Payload), Retention: domain.GameClientBridgeRetention{KeepForSeconds: request.KeepForSeconds, MaxRecords: request.MaxRecords}} } func (query GameClientBridgeSnapshotQuery) ToDomain(serverID, pluginID string) domain.GameClientBridgeSnapshotQuery { return domain.GameClientBridgeSnapshotQuery{ServerInstanceID: serverID, PluginID: pluginID, ProfileKey: query.ProfileKey, Type: query.Type, StreamKey: query.StreamKey, ObservedAfter: query.ObservedAfter, Limit: query.Limit} } func GameClientBridgeCommandFromDomain(value domain.GameClientBridgeCommand) GameClientBridgeCommandResponse { value = domain.CopyGameClientBridgeCommand(value) response := GameClientBridgeCommandResponse{ ID: value.ID, ServerInstanceID: value.ServerInstanceID, PluginID: value.PluginID, ProfileKey: value.ProfileKey, CommandType: value.CommandType, Priority: value.Priority, State: string(value.State), ApprovalState: string(value.ApprovalState), RequesterID: value.RequesterID, ResultSummary: value.Result.Summary, AuditReferences: copyStrings(value.AuditReferences), ExpiresAt: value.ExpiresAt, CreatedAt: value.CreatedAt, UpdatedAt: value.UpdatedAt, CompletedAt: value.CompletedAt, } if hasGameClientBridgeResult(value.Result) { result := gameClientBridgeCommandResultFromDomain(value.Result) response.Result = &result } if hasGameClientBridgeCancellation(value.Cancellation) { cancellation := gameClientBridgeCommandCancellationFromDomain(value.Cancellation) response.Cancellation = &cancellation } return response } func GameClientBridgeSnapshotFromDomain(value domain.GameClientBridgeSnapshot) GameClientBridgeSnapshotResponse { value = domain.CopyGameClientBridgeSnapshot(value) return GameClientBridgeSnapshotResponse{ ID: value.ID, ServerInstanceID: value.ServerInstanceID, PluginID: value.PluginID, ProfileKey: value.ProfileKey, Type: value.Type, SchemaVersion: value.SchemaVersion, StreamKey: value.StreamKey, Sequence: value.Sequence, ObservedAt: value.ObservedAt, Payload: value.Payload, Retention: gameClientBridgeRetentionFromDomain(value.Retention), AuditReferences: copyStrings(value.AuditReferences), CreatedAt: value.CreatedAt, ExpiresAt: value.ExpiresAt, } } func GameClientBridgeClaimedCommandFromDomain(value domain.GameClientBridgeCommand) GameClientBridgeClaimedCommandResponse { value = domain.CopyGameClientBridgeCommand(value) return GameClientBridgeClaimedCommandResponse{ID: value.ID, ProfileKey: value.ProfileKey, CommandType: value.CommandType, Payload: value.Payload, Priority: value.Priority, FencingToken: value.Claim.FencingToken, ClaimedAt: value.Claim.ClaimedAt, LeaseExpiresAt: value.Claim.LeaseExpiresAt, ExpiresAt: value.ExpiresAt} } func GameClientBridgeCommandsFromDomain(values []domain.GameClientBridgeCommand) GameClientBridgeCommandListResponse { items := make([]GameClientBridgeCommandResponse, len(values)) for index, value := range values { items[index] = GameClientBridgeCommandFromDomain(value) } return GameClientBridgeCommandListResponse{Items: items, Count: len(items)} } func GameClientBridgeSnapshotsFromDomain(values []domain.GameClientBridgeSnapshot) GameClientBridgeSnapshotListResponse { items := make([]GameClientBridgeSnapshotResponse, len(values)) for index, value := range values { items[index] = GameClientBridgeSnapshotFromDomain(value) } return GameClientBridgeSnapshotListResponse{Items: items, Count: len(items)} } func GameClientBridgeClaimResponseFromDomain(values []domain.GameClientBridgeCommand) GameClientBridgeClaimResponse { items := make([]GameClientBridgeClaimedCommandResponse, len(values)) for index, value := range values { items[index] = GameClientBridgeClaimedCommandFromDomain(value) } return GameClientBridgeClaimResponse{Items: items, Count: len(items)} } func GameClientBridgeClaimBatchFromDomain(values []domain.GameClientBridgeCommand) GameClientBridgeClaimBatchResponse { return GameClientBridgeClaimResponseFromDomain(values) } func GameClientBridgeAckFromDomain(value domain.GameClientBridgeCommand) GameClientBridgeAckResponse { return GameClientBridgeAckResponse{CommandID: value.ID, State: string(value.State), FencingToken: value.Claim.FencingToken, AcknowledgedAt: value.Claim.AcknowledgedAt} } func GameClientBridgeResultFromDomain(value domain.GameClientBridgeCommand) GameClientBridgeResultResponse { value = domain.CopyGameClientBridgeCommand(value) return GameClientBridgeResultResponse{CommandID: value.ID, State: string(value.State), Result: gameClientBridgeCommandResultFromDomain(value.Result), UpdatedAt: value.UpdatedAt, CompletedAt: value.CompletedAt} } func GameClientBridgeCancelFromDomain(value domain.GameClientBridgeCommand) GameClientBridgeCancelResponse { value = domain.CopyGameClientBridgeCommand(value) return GameClientBridgeCancelResponse{CommandID: value.ID, State: string(value.State), Cancellation: gameClientBridgeCommandCancellationFromDomain(value.Cancellation), AuditReferences: copyStrings(value.AuditReferences), UpdatedAt: value.UpdatedAt} } func GameClientBridgeSnapshotIngestFromDomain(value domain.GameClientBridgeSnapshot) GameClientBridgeSnapshotIngestResponse { return GameClientBridgeSnapshotIngestResponse{SnapshotID: value.ID, ProfileKey: value.ProfileKey, Type: value.Type, SchemaVersion: value.SchemaVersion, StreamKey: value.StreamKey, Sequence: value.Sequence, AcceptedAt: value.CreatedAt, ExpiresAt: value.ExpiresAt} } func GameClientBridgeAuditReferenceFromDomain(value domain.GameClientBridgeAuditReference) GameClientBridgeAuditReferenceResponse { return GameClientBridgeAuditReferenceResponse{ID: value.ID, CommandID: value.CommandID, SnapshotID: value.SnapshotID, AuditEventID: value.AuditEventID, CreatedAt: value.CreatedAt} } func GameClientBridgeAuditReferencesFromDomain(values []domain.GameClientBridgeAuditReference) GameClientBridgeAuditReferenceListResponse { items := make([]GameClientBridgeAuditReferenceResponse, len(values)) for index, value := range values { items[index] = GameClientBridgeAuditReferenceFromDomain(value) } return GameClientBridgeAuditReferenceListResponse{Items: items, Count: len(items)} } func GameClientBridgeStatusFromDomain(value domain.GameClientBridgeStatus) GameClientBridgeStatusResponse { value = domain.CopyGameClientBridgeStatus(value) profiles := make([]GameClientBridgeProfileDeclarationResponse, len(value.Profiles)) for index, profile := range value.Profiles { profiles[index] = GameClientBridgeProfileDeclarationResponse{PluginID: profile.PluginID, ProfileKey: profile.ProfileKey, Available: profile.Available, Reason: profile.Reason, CommandTypes: nonNilStrings(profile.CommandTypes), SnapshotTypes: nonNilStrings(profile.SnapshotTypes), QueryTemplateKeys: nonNilStrings(profile.QueryTemplateKeys), HandlerTypes: nonNilStrings(profile.HandlerTypes), EventProducerTypes: nonNilStrings(profile.EventProducerTypes)} } features := make([]GameClientBridgeFeatureAvailabilityResponse, len(value.Features)) for index, feature := range value.Features { features[index] = GameClientBridgeFeatureAvailabilityResponse{Key: feature.Key, Available: feature.Available, Reason: feature.Reason} } return GameClientBridgeStatusResponse{ServerInstanceID: value.ServerInstanceID, PluginID: value.PluginID, Available: value.Available, Reason: value.Reason, Profiles: profiles, Features: features} } func gameClientBridgeCommandResultFromDomain(value domain.GameClientBridgeResult) GameClientBridgeCommandResultResponse { value = domain.CopyGameClientBridgeResult(value) return GameClientBridgeCommandResultResponse{Status: string(value.Status), Summary: value.Summary, Payload: value.Payload, CompletedAt: value.CompletedAt} } func gameClientBridgeCommandCancellationFromDomain(value domain.GameClientBridgeCancellation) GameClientBridgeCommandCancellationResponse { return GameClientBridgeCommandCancellationResponse{RequestedBy: value.RequestedBy, Reason: value.Reason, CancelledAt: value.CancelledAt} } func gameClientBridgeRetentionFromDomain(value domain.GameClientBridgeRetention) GameClientBridgeRetentionResponse { return GameClientBridgeRetentionResponse{KeepForSeconds: value.KeepForSeconds, MaxRecords: value.MaxRecords} } func hasGameClientBridgeResult(value domain.GameClientBridgeResult) bool { return value.Status != "" || value.Summary != "" || value.Payload != nil || value.CompletedBy != "" || !value.CompletedAt.IsZero() } func hasGameClientBridgeCancellation(value domain.GameClientBridgeCancellation) bool { return value.RequestedBy != "" || value.Reason != "" || !value.CancelledAt.IsZero() } func copyStrings(values []string) []string { if values == nil { return nil } result := make([]string, len(values)) copy(result, values) return result } func nonNilStrings(values []string) []string { if values == nil { return []string{} } return copyStrings(values) }