~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
80 lines · 2.3 KB Raw History
package scoped

import (
	"context"
	"encoding/json"
	"errors"
	"strings"

	commonv1 "github.com/johnandersen777/socialweb-computer-kcp/api/common/v1alpha1"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/contract/atprotorepo"
)

func Route(inner atprotorepo.Repo, network atprotorepo.RecordReader) atprotorepo.Repo {
	if network == nil {
		return inner
	}
	return &routed{Repo: inner, network: network}
}

type routed struct {
	atprotorepo.Repo

	network atprotorepo.RecordReader
}

var (
	_ atprotorepo.SwapDeleter = (*routed)(nil)
	_ atprotorepo.SwapPutter  = (*routed)(nil)
)

func (r *routed) PutRecordSwap(ctx context.Context, collection, rkey string, value json.RawMessage, swapCID string) (commonv1.StrongRef, error) {
	inner, ok := r.Repo.(atprotorepo.SwapPutter)
	if !ok {
		return commonv1.StrongRef{}, errors.New("scoped: the routed repo cannot put a record by its cid")
	}
	return inner.PutRecordSwap(ctx, collection, rkey, value, swapCID)
}

func (r *routed) DeleteRecordSwap(ctx context.Context, collection, rkey, swapCID string) error {
	inner, ok := r.Repo.(atprotorepo.SwapDeleter)
	if !ok {
		return errors.New("scoped: the routed repo cannot delete a record by its cid")
	}
	return inner.DeleteRecordSwap(ctx, collection, rkey, swapCID)
}

func (r *routed) foreign(repo string) bool {
	repo = strings.TrimSpace(repo)
	return repo != "" && repo != r.DID()
}

func (r *routed) GetRecord(ctx context.Context, repo, collection, rkey string) (atprotorepo.Record, error) {
	if r.foreign(repo) {
		return r.network.GetRecord(ctx, repo, collection, rkey)
	}
	return r.Repo.GetRecord(ctx, repo, collection, rkey)
}

func (r *routed) ListRecords(ctx context.Context, repo, collection string, opts atprotorepo.ListOptions) (atprotorepo.ListPage, error) {
	if r.foreign(repo) {
		return r.network.ListRecords(ctx, repo, collection, opts)
	}
	return r.Repo.ListRecords(ctx, repo, collection, opts)
}

func (r *routed) Resolve(ctx context.Context, ref commonv1.StrongRef) (atprotorepo.Record, error) {
	if authority, ok := uriAuthority(ref.URI); ok && r.foreign(authority) {
		return r.network.Resolve(ctx, ref)
	}
	return r.Repo.Resolve(ctx, ref)
}

func uriAuthority(uri string) (string, bool) {
	rest, ok := strings.CutPrefix(strings.TrimSpace(uri), "at://")
	if !ok {
		return "", false
	}
	authority, _, _ := strings.Cut(rest, "/")
	return authority, authority != ""
}