~bigbes/sr-ht-spec

ref: 636dc7a8d00c0f988b5afa2d715ab1140fd6d912 sr-ht-spec/graph/proposals.go -rw-r--r-- 2.4 KiB
636dc7a8 — Eugene Blikh pages: read a form's body, bounded, and never its URL 9 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package graph

import (
	"context"

	"sourcecraft.dev/bigbes/sr-ht-spec/core"
	"sourcecraft.dev/bigbes/sr-ht-spec/service"
)

// proposalLister is the service-layer proposal read this package adapts. It is
// the method *service.Service grew in Phase 3, named as an interface here so the
// adapter is testable without a whole Service and so this file states exactly
// what it depends on.
type proposalLister interface {
	ListProposals(ctx context.Context, space core.SpaceRef, state core.ProposalState) ([]service.Proposal, error)
}

// serviceProposals adapts the service layer to the Proposals port.
//
// The port yields graph.Proposal (core types, no db/ leak) while the service
// yields service.Proposal, and the two cannot be one type without a dependency
// cycle — service/ must not import graph/. So the mapping lives here, at the
// edge, exactly as web.NewReader adapts the same service to the web surface's
// read shape. It is a field-for-field copy; the two structs are deliberately
// identical so this stays a rename rather than a translation.
type serviceProposals struct{ svc proposalLister }

// NewProposals wires the service layer into the schema's proposals field,
// closing the gap the Proposals port documented: with this set, Options.Proposals
// is no longer nil and the `proposals` query answers from service/ instead of
// failing with "no proposal listing yet".
func NewProposals(svc proposalLister) Proposals { return serviceProposals{svc: svc} }

func (s serviceProposals) ListProposals(ctx context.Context, space core.SpaceRef, state core.ProposalState) ([]Proposal, error) {
	ps, err := s.svc.ListProposals(ctx, space, state)
	if err != nil {
		return nil, err
	}
	out := make([]Proposal, 0, len(ps))
	for _, p := range ps {
		out = append(out, Proposal{
			ID:           p.ID,
			Space:        p.Space,
			Title:        p.Title,
			Rationale:    p.Rationale,
			BaseRev:      p.BaseRev,
			Branch:       p.Branch,
			State:        p.State,
			Approval:     p.Approval,
			MergedRev:    p.MergedRev,
			Agent:        p.Agent,
			AgentSession: p.AgentSession,
			Created:      p.Created,
			Resolved:     p.Resolved,
		})
	}
	return out, nil
}

// Compile-time assertion that the production service satisfies the read this
// adapter needs. It lives here, beside the assertions in resolver.go, so a
// signature drift in service/ breaks the build rather than a test.
var _ proposalLister = (*service.Service)(nil)