Merge branch 'master' of github.com:spotify/backstage into ben/listing-components

* 'master' of github.com:spotify/backstage: (25 commits)
  backend/scaffolder: fix build
  backend,proto: added builds service that calls out to github api
  proto: update README
  proto: switch to grpc-web plugin + ship protoc plugin binary, because meh
  feat: returning correct list of included facts
  refactor: Protobuf messages
  No separate login link anymore
  add failing scenario for getting entity
  Persist login (for now - due to constant page reloads)
  feat: add set fact endpoint
  Mark package as private
  frontend: remove gen-proto script, replaced by proto package
  Updated docs
  Fixed prototool
  Added generated files
  Added service=grpc-web flag
  Added protobuf-gen-ts to prototool.yaml
  Ran yarn install
  Added a @backstage/protobuf-definitions package
  frontend/core: simplify plugin output handling
  ...
This commit is contained in:
blam
2020-02-06 14:48:08 +01:00
81 changed files with 10423 additions and 367 deletions
+1
View File
@@ -0,0 +1 @@
secrets.env
+10
View File
@@ -8,6 +8,16 @@ Backstage is an open platform for building developer portals.
## Getting started
### Protobuf Definitions
To generate the Protobuf definitions in Go and TypeScript, run the following command from the root with [Prototool](https://github.com/uber/prototool):
```bash
$ prototool generate ./proto
```
See [proto/README.md](proto/README.md) for more information.
## Plugins
### Creating a Plugin
+85
View File
@@ -0,0 +1,85 @@
package ghactions
import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
)
type Client struct {
client *http.Client
baseURL string
accessToken string
}
func NewFromEnv() (*Client, error) {
accessToken := os.Getenv("BOSS_GH_ACCESS_TOKEN")
if accessToken == "" {
return nil, fmt.Errorf("BOSS_GH_ACCESS_TOKEN not set")
}
return New(http.DefaultClient, "https://api.github.com", accessToken), nil
}
func New(client *http.Client, baseURL, accessToken string) *Client {
return &Client{
client: client,
baseURL: baseURL,
accessToken: accessToken,
}
}
func (c *Client) createRequest(ctx context.Context, owner, repo, path string) (*http.Request, error) {
url := fmt.Sprintf("%s/repos/%s/%s/actions%s", c.baseURL, owner, repo, path)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
}
req.Header.Add("Authorization", "Bearer "+c.accessToken)
return req.WithContext(ctx), nil
}
func (c *Client) ListWorkflowRuns(ctx context.Context, owner, repo string) (*WorkflowRunsListResponse, error) {
req, err := c.createRequest(ctx, owner, repo, "/runs")
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var resData WorkflowRunsListResponse
if err := json.NewDecoder(res.Body).Decode(&resData); err != nil {
return nil, err
}
return &resData, nil
}
func (c *Client) GetWorkflowRun(ctx context.Context, owner, repo, runId string) (*WorkflowRunResponse, error) {
req, err := c.createRequest(ctx, owner, repo, fmt.Sprintf("/runs/%s", runId))
if err != nil {
return nil, err
}
res, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var resData WorkflowRunResponse
if err := json.NewDecoder(res.Body).Decode(&resData); err != nil {
return nil, err
}
return &resData, nil
}
+53
View File
@@ -0,0 +1,53 @@
package ghactions
type User struct {
Name string `json:"name"` // "Octo Cat"
Email string `json:"email"` // "octocat@github.com"
}
type Commit struct {
ID string `json:"id"` // "acb5820ced9479c074f688cc328bf03f341a511d"
TreeID string `json:"tree_id"` // "d23f6eedb1e1b9610bbc754ddb5197bfe7271223"
Message string `json:"message"` // "Create linter.yml"
Timestamp string `json:"timestamp"` // "2020-01-22T19:33:05Z"
Author User `json:"author"`
Committer User `json:"committer"`
}
type Repository struct {
ID int64 `json:"id"` // 217723378
NodeID string `json:"node_id"` // MDEwOlJlcG9zaXRvcnkyMTc3MjMzNzg="
Name string `json:"name"` // o-repo"
FullName string `json:"full_name"` // "octo-org/octo-repo"
HTMLURL string `json:"html_url"` // "https://github.com/octo-org/octo-repo"
}
type WorkflowRunResponse struct {
ID int64 `json:"id"` // 30433642
NodeID string `json:"node_id"` // "MDEyOldvcmtmbG93IFJ1bjI2OTI4OQ=="
HeadBranch string `json:"head_branch"` // "master"
HeadSha string `json:"head_sha"` // "acb5820ced9479c074f688cc328bf03f341a511d"
RunNumber int64 `json:"run_number"` // 562
CheckSuiteID int64 `json:"check_suite_id"` // 414944374
Event string `json:"event"` // "push"
Status string `json:"status"` // "queued"
Conclusion *string `json:"conclusion"` // null
URL string `json:"url"` // "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642"
HTMLURL string `json:"html_url"` // "https://github.com/octo-org/octo-repo/actions/runs/30433642"
CreatedAt string `json:"created_at"` // "2020-01-22T19:33:08Z"
UpdatedAt string `json:"updated_at"` // "2020-01-22T19:33:08Z"
JobsURL string `json:"jobs_url"` // "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs"
LogsURL string `json:"logs_url"` // "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs"
ArtifactsURL string `json:"artifacts_url"` // "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts"
CancelURL string `json:"cancel_url"` // "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel"
RerunURL string `json:"rerun_url"` // "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun"
WorkflowURL string `json:"workflow_url"` // "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/30433642"
HeadCommit Commit `json:"head_commit"`
Repository Repository `json:"repository"`
HeadRepository Repository `json:"head_repository"`
}
type WorkflowRunsListResponse struct {
TotalCount int64 `json:"total_count"`
Runs []WorkflowRunResponse `json:"workflow_runs"`
}
+10
View File
@@ -0,0 +1,10 @@
module github.com/spotify/backstage/builds
go 1.12
replace github.com/spotify/backstage/proto => ../proto
require (
github.com/spotify/backstage/proto v0.0.0-00010101000000-000000000000
google.golang.org/grpc v1.27.1
)
+54
View File
@@ -0,0 +1,54 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+34
View File
@@ -0,0 +1,34 @@
package main
import (
"log"
"net"
"github.com/spotify/backstage/builds/ghactions"
"github.com/spotify/backstage/builds/service"
buildsv1 "github.com/spotify/backstage/proto/builds/v1"
"google.golang.org/grpc"
)
const (
port = ":50051"
)
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
ghClient, err := ghactions.NewFromEnv()
if err != nil {
log.Fatalf("Failed to create github client, %s", err)
}
buildsv1.RegisterBuildsServer(grpcServer, service.New(ghClient))
log.Println("Serving Builds Service")
grpcServer.Serve(lis)
}
+116
View File
@@ -0,0 +1,116 @@
package service
import (
"context"
"fmt"
"regexp"
"github.com/spotify/backstage/builds/ghactions"
buildsv1 "github.com/spotify/backstage/proto/builds/v1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type service struct {
ghClient *ghactions.Client
}
var _ buildsv1.BuildsServer = (*service)(nil)
// New creates a new identity data server
func New(ghClient *ghactions.Client) buildsv1.BuildsServer {
return &service{ghClient}
}
func (s *service) ListBuilds(ctx context.Context, req *buildsv1.ListBuildsRequest) (*buildsv1.ListBuildsReply, error) {
owner := "spotify"
repo := "backstage"
result, err := s.ghClient.ListWorkflowRuns(ctx, owner, repo)
if err != nil {
return nil, status.Errorf(codes.Internal, "Failed to fetch workflow runs for %s/%s, %s", owner, repo, err)
}
builds := make([]*buildsv1.Build, len(result.Runs))
for i, run := range result.Runs {
builds[i] = s.transformBuild(owner, repo, &run)
}
return &buildsv1.ListBuildsReply{
EntityUri: "",
Builds: builds,
}, nil
}
func (s *service) GetBuild(ctx context.Context, req *buildsv1.GetBuildRequest) (*buildsv1.GetBuildReply, error) {
uri := req.GetBuildUri()
owner, repo, runID, err := s.parseBuildURI(uri)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "Invalid build URI '%s', %s", uri, err)
}
run, err := s.ghClient.GetWorkflowRun(ctx, owner, repo, runID)
if err != nil {
return nil, status.Errorf(codes.Internal, "Failed to fetch workflow run for %s/%s/%s, %s", owner, repo, runID, err)
}
return &buildsv1.GetBuildReply{
Build: s.transformBuild(owner, repo, run),
Details: &buildsv1.BuildDetails{
Author: run.HeadCommit.Author.Name,
LogUrl: run.LogsURL,
OverviewUrl: run.HTMLURL,
},
}, nil
}
func (s *service) transformBuild(owner, repo string, run *ghactions.WorkflowRunResponse) *buildsv1.Build {
stat := buildsv1.BuildStatus_NULL
switch run.Status {
case "queued":
stat = buildsv1.BuildStatus_PENDING
case "in_progress":
stat = buildsv1.BuildStatus_RUNNING
case "completed":
if run.Conclusion != nil {
switch *run.Conclusion {
case "success":
stat = buildsv1.BuildStatus_SUCCESS
case "neutral":
stat = buildsv1.BuildStatus_SUCCESS
case "failure":
stat = buildsv1.BuildStatus_FAILURE
case "cancelled":
stat = buildsv1.BuildStatus_FAILURE
case "timed_out":
stat = buildsv1.BuildStatus_FAILURE
case "action_required":
stat = buildsv1.BuildStatus_RUNNING
}
}
}
return &buildsv1.Build{
Uri: fmt.Sprintf("entity:build:%s/%s/%d", owner, repo, run.ID),
CommitId: run.HeadCommit.ID,
Message: run.HeadCommit.Message,
Status: stat,
}
}
var entityURIRegex = regexp.MustCompile("^entity:build:([^/:]+)/([^/:]+)/([^/:]+)$")
func (s *service) parseBuildURI(uri string) (owner, repo, runID string, err error) {
if uri == "" {
return "", "", "", fmt.Errorf("uri is empty")
}
match := entityURIRegex.FindStringSubmatch(uri)
if err != nil {
return "", "", "", fmt.Errorf("uri does not match")
}
return match[1], match[2], match[3], nil
}
+29 -3
View File
@@ -3,6 +3,7 @@ package app
import (
"context"
"fmt"
"github.com/spotify/backstage/inventory/storage"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -18,16 +19,41 @@ type Server struct {
func (s *Server) CreateEntity(ctx context.Context, req *pb.CreateEntityRequest) (*pb.CreateEntityReply, error) {
err := s.Storage.CreateEntity(req.GetEntity().GetUri())
if err != nil {
return nil, status.Error(codes.Internal, "could not create entity")
return nil, status.Error(codes.Internal, "could not create entity")
}
return &pb.CreateEntityReply{Entity: req.GetEntity()} , nil
return &pb.CreateEntityReply{Entity: req.GetEntity()}, nil
}
// GetEntity returns an inventory Entity with the selected facts
func (s *Server) GetEntity(ctx context.Context, req *pb.GetEntityRequest) (*pb.GetEntityReply, error) {
var facts []*pb.Fact
entityUri, err := s.Storage.GetEntity(req.GetEntity().GetUri())
if err != nil {
return nil, status.Error(codes.Internal, fmt.Sprintf("could not get entity %v", err))
}
return &pb.GetEntityReply{Entity: &pb.Entity{Uri: entityUri}}, nil
for _, factName := range req.GetIncludeFacts() {
value, err := s.Storage.GetFact(entityUri, factName)
if err != nil {
return nil, status.Error(codes.Internal, fmt.Sprintf("could not get fact %v for %v" , factName, entityUri))
}
facts = append(facts, &pb.Fact{Name: factName, Value: value})
}
return &pb.GetEntityReply{Entity: &pb.Entity{Uri: entityUri}, Facts: facts}, nil
}
func (s *Server) SetFact(ctx context.Context, req *pb.SetFactRequest) (*pb.SetFactReply, error) {
err := s.Storage.SetFact(req.EntityUri, req.Name, req.Value)
if err != nil {
return nil, status.Error(codes.Internal, "could not set fact")
}
return &pb.SetFactReply{Fact: &pb.Fact{Name: req.GetName(), Value: req.GetValue()}}, nil
}
func (s *Server) GetFact(ctx context.Context, req *pb.GetFactRequest) (*pb.GetFactReply, error) {
val, err := s.Storage.GetFact(req.EntityUri, req.Name)
if err != nil {
return nil, status.Error(codes.Internal, "could not set fact")
}
return &pb.GetFactReply{Fact: &pb.Fact{Name: req.GetName(), Value: val}}, nil
}
+98 -30
View File
@@ -3,42 +3,16 @@ package app
import (
"context"
"fmt"
"github.com/spotify/backstage/inventory/storage"
"io/ioutil"
"os"
"reflect"
"testing"
"github.com/spotify/backstage/inventory/storage"
pb "github.com/spotify/backstage/proto/inventory/v1"
)
type TestStorage struct {
Storage *storage.Storage
Path string
}
// NewTestStorage returns a TestStorage using a temporary path.
func NewTestStorage() *TestStorage {
f, err := ioutil.TempFile("", "")
if err != nil {
panic(fmt.Sprintf("temp file: %s", err))
}
path := f.Name()
f.Close()
os.Remove(path)
// Open the database.
config := storage.Config{Path: path}
storage, _ := storage.OpenStorage(config)
// Return wrapped type.
return &TestStorage{Storage: storage, Path: path}
}
// Close and delete Bolt database.
func (db *TestStorage) Close() {
defer os.Remove(db.Path)
db.Storage.Close()
}
func TestServerCreateEntity(t *testing.T) {
testStorage := NewTestStorage()
defer testStorage.Close()
@@ -50,7 +24,7 @@ func TestServerCreateEntity(t *testing.T) {
if err != nil {
t.Errorf("ServerTest(CreateEntity) got unexpected error %v", err)
}
if resp.GetEntity().GetUri() != entity.GetUri() {
if resp.GetEntity().GetUri() != entity.GetUri() {
t.Errorf("ServerTest(CreateEntity) expected %v, but got %v", entity.GetUri(), resp.GetEntity().GetUri())
}
}
@@ -76,3 +50,97 @@ func TestServerGetEntity(t *testing.T) {
t.Errorf("ServerTest(GetEntity) got %v, wanted %v", resp.GetEntity().GetUri(), entity.GetUri())
}
}
func TestServerGetEntityWithIncludedFacts(t *testing.T) {
testStorage := NewTestStorage()
defer testStorage.Close()
s := Server{Storage: testStorage.Storage}
entityUri := "boss://test/test"
setFactReq := &pb.SetFactRequest{EntityUri: entityUri, Name: "test-name", Value: "test-value"}
s.SetFact(context.Background(), setFactReq)
entity := &pb.Entity{Uri: entityUri}
req := &pb.GetEntityRequest{Entity: entity, IncludeFacts: []string{"test-name"}}
resp, err := s.GetEntity(context.Background(), req)
if err != nil {
t.Errorf("ServerTest(GetEntity) got unexpected error %v", err)
}
if resp == nil {
t.Errorf("ServerTest(GetEntity) returned nil")
}
expectedFacts := []*pb.Fact{{Name: "test-name", Value: "test-value"}}
if !reflect.DeepEqual(resp.GetFacts(), expectedFacts) {
t.Errorf("ServerTest(GetEntity) got %v, wanted %v", resp.GetFacts(), expectedFacts)
}
}
func TestServerSetFactForExistingEntity(t *testing.T) {
testStorage := NewTestStorage()
defer testStorage.Close()
s := Server{Storage: testStorage.Storage}
entity := &pb.Entity{Uri: "boss://test/test"}
createReq := &pb.CreateEntityRequest{Entity: entity}
s.CreateEntity(context.Background(), createReq)
req := &pb.SetFactRequest{EntityUri: "boss://test/test", Name: "test-name", Value: "test-value"}
resp, err := s.SetFact(context.Background(), req)
if err != nil {
t.Errorf("ServerTest(SetFact) got unexpected error %v", err)
}
if resp == nil {
t.Errorf("ServerTest(SetFact) returned nil")
}
fact := &pb.Fact{Name: req.GetName(), Value: req.GetValue()}
if !reflect.DeepEqual(resp.GetFact(), fact) {
t.Errorf("ServerTest(SetFact) got %v, wanted %v", resp.GetFact(), fact)
}
}
func TestServerSetFactForNonExistingEntity(t *testing.T) {
testStorage := NewTestStorage()
defer testStorage.Close()
s := Server{Storage: testStorage.Storage}
entityUri := "boss://test/test"
req := &pb.SetFactRequest{EntityUri: entityUri, Name: "test-name", Value: "test-value"}
resp, err := s.SetFact(context.Background(), req)
if err != nil {
t.Errorf("ServerTest(SetFact) got unexpected error %v", err)
}
if resp == nil {
t.Errorf("ServerTest(SetFact) returned nil")
}
fact := &pb.Fact{Name: req.GetName(), Value: req.GetValue()}
if !reflect.DeepEqual(resp.GetFact(), fact) {
t.Errorf("ServerTest(SetFact) got %v, wanted %v", resp.GetFact(), fact)
}
}
type TestStorage struct {
Storage *storage.Storage
Path string
}
// NewTestStorage returns a TestStorage using a temporary path.
func NewTestStorage() *TestStorage {
f, err := ioutil.TempFile("", "")
if err != nil {
panic(fmt.Sprintf("temp file: %s", err))
}
path := f.Name()
f.Close()
os.Remove(path)
config := storage.Config{Path: path}
storage, _ := storage.OpenStorage(config)
return &TestStorage{Storage: storage, Path: path}
}
func (db *TestStorage) Close() {
defer os.Remove(db.Path)
db.Storage.Close()
}
-2
View File
@@ -1,2 +0,0 @@
#!/bin/bash
protoc -I ../../ protos/inventory.proto --go_out=plugins=grpc:.
+3
View File
@@ -8,5 +8,8 @@ require (
github.com/golang/protobuf v1.3.3
github.com/spotify/backstage/proto v0.0.0-00010101000000-000000000000
go.etcd.io/bbolt v1.3.3
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 // indirect
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 // indirect
google.golang.org/grpc v1.27.0
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc // indirect
)
+6 -2
View File
@@ -37,13 +37,17 @@ func (s *Storage) Close() error {
return s.db.Close()
}
func (s *Storage) SetFact(entityUri, name, value string) error {
func (s *Storage) SetFact(entityUri, name, value string) (err error) {
return s.db.Update(func(tx *bbolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte(entityUri))
if err != nil {
return err
}
return b.Put([]byte(name), []byte(value))
err = b.Put([]byte(name), []byte(value))
if err != nil {
return err
}
return nil
})
}
+509
View File
@@ -0,0 +1,509 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: builds/v1/builds.proto
package buildsv1
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type BuildStatus int32
const (
BuildStatus_NULL BuildStatus = 0
BuildStatus_SUCCESS BuildStatus = 1
BuildStatus_FAILURE BuildStatus = 2
BuildStatus_PENDING BuildStatus = 3
BuildStatus_RUNNING BuildStatus = 4
)
var BuildStatus_name = map[int32]string{
0: "NULL",
1: "SUCCESS",
2: "FAILURE",
3: "PENDING",
4: "RUNNING",
}
var BuildStatus_value = map[string]int32{
"NULL": 0,
"SUCCESS": 1,
"FAILURE": 2,
"PENDING": 3,
"RUNNING": 4,
}
func (x BuildStatus) String() string {
return proto.EnumName(BuildStatus_name, int32(x))
}
func (BuildStatus) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_05a627abb7f9adb4, []int{0}
}
type ListBuildsRequest struct {
EntityUri string `protobuf:"bytes,1,opt,name=entity_uri,json=entityUri,proto3" json:"entity_uri,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListBuildsRequest) Reset() { *m = ListBuildsRequest{} }
func (m *ListBuildsRequest) String() string { return proto.CompactTextString(m) }
func (*ListBuildsRequest) ProtoMessage() {}
func (*ListBuildsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_05a627abb7f9adb4, []int{0}
}
func (m *ListBuildsRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListBuildsRequest.Unmarshal(m, b)
}
func (m *ListBuildsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListBuildsRequest.Marshal(b, m, deterministic)
}
func (m *ListBuildsRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListBuildsRequest.Merge(m, src)
}
func (m *ListBuildsRequest) XXX_Size() int {
return xxx_messageInfo_ListBuildsRequest.Size(m)
}
func (m *ListBuildsRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ListBuildsRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ListBuildsRequest proto.InternalMessageInfo
func (m *ListBuildsRequest) GetEntityUri() string {
if m != nil {
return m.EntityUri
}
return ""
}
type ListBuildsReply struct {
EntityUri string `protobuf:"bytes,1,opt,name=entity_uri,json=entityUri,proto3" json:"entity_uri,omitempty"`
Builds []*Build `protobuf:"bytes,2,rep,name=builds,proto3" json:"builds,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListBuildsReply) Reset() { *m = ListBuildsReply{} }
func (m *ListBuildsReply) String() string { return proto.CompactTextString(m) }
func (*ListBuildsReply) ProtoMessage() {}
func (*ListBuildsReply) Descriptor() ([]byte, []int) {
return fileDescriptor_05a627abb7f9adb4, []int{1}
}
func (m *ListBuildsReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListBuildsReply.Unmarshal(m, b)
}
func (m *ListBuildsReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListBuildsReply.Marshal(b, m, deterministic)
}
func (m *ListBuildsReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListBuildsReply.Merge(m, src)
}
func (m *ListBuildsReply) XXX_Size() int {
return xxx_messageInfo_ListBuildsReply.Size(m)
}
func (m *ListBuildsReply) XXX_DiscardUnknown() {
xxx_messageInfo_ListBuildsReply.DiscardUnknown(m)
}
var xxx_messageInfo_ListBuildsReply proto.InternalMessageInfo
func (m *ListBuildsReply) GetEntityUri() string {
if m != nil {
return m.EntityUri
}
return ""
}
func (m *ListBuildsReply) GetBuilds() []*Build {
if m != nil {
return m.Builds
}
return nil
}
type GetBuildRequest struct {
BuildUri string `protobuf:"bytes,1,opt,name=build_uri,json=buildUri,proto3" json:"build_uri,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetBuildRequest) Reset() { *m = GetBuildRequest{} }
func (m *GetBuildRequest) String() string { return proto.CompactTextString(m) }
func (*GetBuildRequest) ProtoMessage() {}
func (*GetBuildRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_05a627abb7f9adb4, []int{2}
}
func (m *GetBuildRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetBuildRequest.Unmarshal(m, b)
}
func (m *GetBuildRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetBuildRequest.Marshal(b, m, deterministic)
}
func (m *GetBuildRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetBuildRequest.Merge(m, src)
}
func (m *GetBuildRequest) XXX_Size() int {
return xxx_messageInfo_GetBuildRequest.Size(m)
}
func (m *GetBuildRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetBuildRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetBuildRequest proto.InternalMessageInfo
func (m *GetBuildRequest) GetBuildUri() string {
if m != nil {
return m.BuildUri
}
return ""
}
type GetBuildReply struct {
Build *Build `protobuf:"bytes,1,opt,name=build,proto3" json:"build,omitempty"`
Details *BuildDetails `protobuf:"bytes,2,opt,name=details,proto3" json:"details,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetBuildReply) Reset() { *m = GetBuildReply{} }
func (m *GetBuildReply) String() string { return proto.CompactTextString(m) }
func (*GetBuildReply) ProtoMessage() {}
func (*GetBuildReply) Descriptor() ([]byte, []int) {
return fileDescriptor_05a627abb7f9adb4, []int{3}
}
func (m *GetBuildReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetBuildReply.Unmarshal(m, b)
}
func (m *GetBuildReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetBuildReply.Marshal(b, m, deterministic)
}
func (m *GetBuildReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetBuildReply.Merge(m, src)
}
func (m *GetBuildReply) XXX_Size() int {
return xxx_messageInfo_GetBuildReply.Size(m)
}
func (m *GetBuildReply) XXX_DiscardUnknown() {
xxx_messageInfo_GetBuildReply.DiscardUnknown(m)
}
var xxx_messageInfo_GetBuildReply proto.InternalMessageInfo
func (m *GetBuildReply) GetBuild() *Build {
if m != nil {
return m.Build
}
return nil
}
func (m *GetBuildReply) GetDetails() *BuildDetails {
if m != nil {
return m.Details
}
return nil
}
type Build struct {
Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"`
CommitId string `protobuf:"bytes,2,opt,name=commit_id,json=commitId,proto3" json:"commit_id,omitempty"`
Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
Status BuildStatus `protobuf:"varint,4,opt,name=status,proto3,enum=spotify.backstage.builds.v1.BuildStatus" json:"status,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Build) Reset() { *m = Build{} }
func (m *Build) String() string { return proto.CompactTextString(m) }
func (*Build) ProtoMessage() {}
func (*Build) Descriptor() ([]byte, []int) {
return fileDescriptor_05a627abb7f9adb4, []int{4}
}
func (m *Build) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Build.Unmarshal(m, b)
}
func (m *Build) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Build.Marshal(b, m, deterministic)
}
func (m *Build) XXX_Merge(src proto.Message) {
xxx_messageInfo_Build.Merge(m, src)
}
func (m *Build) XXX_Size() int {
return xxx_messageInfo_Build.Size(m)
}
func (m *Build) XXX_DiscardUnknown() {
xxx_messageInfo_Build.DiscardUnknown(m)
}
var xxx_messageInfo_Build proto.InternalMessageInfo
func (m *Build) GetUri() string {
if m != nil {
return m.Uri
}
return ""
}
func (m *Build) GetCommitId() string {
if m != nil {
return m.CommitId
}
return ""
}
func (m *Build) GetMessage() string {
if m != nil {
return m.Message
}
return ""
}
func (m *Build) GetStatus() BuildStatus {
if m != nil {
return m.Status
}
return BuildStatus_NULL
}
type BuildDetails struct {
Author string `protobuf:"bytes,1,opt,name=author,proto3" json:"author,omitempty"`
OverviewUrl string `protobuf:"bytes,2,opt,name=overview_url,json=overviewUrl,proto3" json:"overview_url,omitempty"`
LogUrl string `protobuf:"bytes,3,opt,name=log_url,json=logUrl,proto3" json:"log_url,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BuildDetails) Reset() { *m = BuildDetails{} }
func (m *BuildDetails) String() string { return proto.CompactTextString(m) }
func (*BuildDetails) ProtoMessage() {}
func (*BuildDetails) Descriptor() ([]byte, []int) {
return fileDescriptor_05a627abb7f9adb4, []int{5}
}
func (m *BuildDetails) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BuildDetails.Unmarshal(m, b)
}
func (m *BuildDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BuildDetails.Marshal(b, m, deterministic)
}
func (m *BuildDetails) XXX_Merge(src proto.Message) {
xxx_messageInfo_BuildDetails.Merge(m, src)
}
func (m *BuildDetails) XXX_Size() int {
return xxx_messageInfo_BuildDetails.Size(m)
}
func (m *BuildDetails) XXX_DiscardUnknown() {
xxx_messageInfo_BuildDetails.DiscardUnknown(m)
}
var xxx_messageInfo_BuildDetails proto.InternalMessageInfo
func (m *BuildDetails) GetAuthor() string {
if m != nil {
return m.Author
}
return ""
}
func (m *BuildDetails) GetOverviewUrl() string {
if m != nil {
return m.OverviewUrl
}
return ""
}
func (m *BuildDetails) GetLogUrl() string {
if m != nil {
return m.LogUrl
}
return ""
}
func init() {
proto.RegisterEnum("spotify.backstage.builds.v1.BuildStatus", BuildStatus_name, BuildStatus_value)
proto.RegisterType((*ListBuildsRequest)(nil), "spotify.backstage.builds.v1.ListBuildsRequest")
proto.RegisterType((*ListBuildsReply)(nil), "spotify.backstage.builds.v1.ListBuildsReply")
proto.RegisterType((*GetBuildRequest)(nil), "spotify.backstage.builds.v1.GetBuildRequest")
proto.RegisterType((*GetBuildReply)(nil), "spotify.backstage.builds.v1.GetBuildReply")
proto.RegisterType((*Build)(nil), "spotify.backstage.builds.v1.Build")
proto.RegisterType((*BuildDetails)(nil), "spotify.backstage.builds.v1.BuildDetails")
}
func init() { proto.RegisterFile("builds/v1/builds.proto", fileDescriptor_05a627abb7f9adb4) }
var fileDescriptor_05a627abb7f9adb4 = []byte{
// 447 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x41, 0x6f, 0xd3, 0x30,
0x18, 0x25, 0x6b, 0x97, 0xb6, 0x5f, 0x07, 0x0b, 0x3e, 0x8c, 0x68, 0x13, 0x52, 0xc9, 0xa9, 0x4c,
0x28, 0x53, 0xcb, 0x05, 0x71, 0x82, 0x75, 0x65, 0xaa, 0xa8, 0x22, 0xe4, 0x2a, 0x17, 0x2e, 0x55,
0xda, 0x98, 0x62, 0x70, 0x71, 0xb0, 0x9d, 0xa0, 0xfc, 0x09, 0x0e, 0xfc, 0x3c, 0x7e, 0x0d, 0xb2,
0x9d, 0xa8, 0x11, 0x93, 0xda, 0xde, 0xfc, 0xbe, 0xf7, 0xbd, 0xbc, 0xf7, 0x49, 0x2f, 0x70, 0xb1,
0xca, 0x29, 0x4b, 0xe5, 0x4d, 0x31, 0xba, 0xb1, 0xaf, 0x30, 0x13, 0x5c, 0x71, 0x74, 0x25, 0x33,
0xae, 0xe8, 0x97, 0x32, 0x5c, 0x25, 0xeb, 0xef, 0x52, 0x25, 0x1b, 0x12, 0x56, 0x7c, 0x31, 0x0a,
0xc6, 0xf0, 0x74, 0x4e, 0xa5, 0xba, 0x35, 0x03, 0x4c, 0x7e, 0xe6, 0x44, 0x2a, 0xf4, 0x1c, 0x80,
0xfc, 0x50, 0x54, 0x95, 0xcb, 0x5c, 0x50, 0xdf, 0x19, 0x38, 0xc3, 0x1e, 0xee, 0xd9, 0x49, 0x2c,
0x68, 0xc0, 0xe0, 0xbc, 0xa9, 0xc9, 0x58, 0x79, 0x40, 0x81, 0xde, 0x82, 0x6b, 0x2d, 0xfd, 0x93,
0x41, 0x6b, 0xd8, 0x1f, 0x07, 0xe1, 0x9e, 0x4c, 0xa1, 0xf9, 0x30, 0xae, 0x14, 0x41, 0x08, 0xe7,
0xf7, 0xc4, 0x9a, 0xd5, 0xf9, 0xae, 0xa0, 0x67, 0xc8, 0x86, 0x59, 0xd7, 0x0c, 0x74, 0xba, 0xdf,
0x0e, 0x3c, 0xde, 0x09, 0x74, 0xb8, 0x37, 0x70, 0x6a, 0x58, 0xb3, 0x7a, 0x9c, 0xb9, 0x15, 0xa0,
0x09, 0x74, 0x52, 0xa2, 0x12, 0xca, 0x74, 0x70, 0xad, 0x7d, 0x79, 0x58, 0x7b, 0x67, 0x05, 0xb8,
0x56, 0x06, 0x7f, 0x1c, 0x38, 0x35, 0x0c, 0xf2, 0xa0, 0xb5, 0x4b, 0xac, 0x9f, 0xfa, 0x92, 0x35,
0xdf, 0x6e, 0xa9, 0x5a, 0xd2, 0xd4, 0x58, 0xf4, 0x70, 0xd7, 0x0e, 0x66, 0x29, 0xf2, 0xa1, 0xb3,
0x25, 0x52, 0x26, 0x1b, 0xe2, 0xb7, 0x0c, 0x55, 0x43, 0xf4, 0x0e, 0x5c, 0xa9, 0x12, 0x95, 0x4b,
0xbf, 0x3d, 0x70, 0x86, 0x4f, 0xc6, 0xc3, 0xc3, 0xb1, 0x16, 0x66, 0x1f, 0x57, 0xba, 0x60, 0x05,
0x67, 0xcd, 0xb4, 0xe8, 0x02, 0xdc, 0x24, 0x57, 0x5f, 0xb9, 0xa8, 0xd2, 0x55, 0x08, 0xbd, 0x80,
0x33, 0x5e, 0x10, 0x51, 0x50, 0xf2, 0x6b, 0x99, 0x0b, 0x56, 0x65, 0xec, 0xd7, 0xb3, 0x58, 0x30,
0xf4, 0x0c, 0x3a, 0x8c, 0x6f, 0x0c, 0x6b, 0x63, 0xba, 0x8c, 0x6f, 0x62, 0xc1, 0xae, 0x3f, 0x42,
0xbf, 0x61, 0x8d, 0xba, 0xd0, 0x8e, 0xe2, 0xf9, 0xdc, 0x7b, 0x84, 0xfa, 0xd0, 0x59, 0xc4, 0x93,
0xc9, 0x74, 0xb1, 0xf0, 0x1c, 0x0d, 0x3e, 0xbc, 0x9f, 0xcd, 0x63, 0x3c, 0xf5, 0x4e, 0x34, 0xf8,
0x34, 0x8d, 0xee, 0x66, 0xd1, 0xbd, 0xd7, 0xd2, 0x00, 0xc7, 0x51, 0xa4, 0x41, 0x7b, 0xfc, 0xd7,
0x01, 0xd7, 0x36, 0x0e, 0x7d, 0x03, 0xd8, 0xf5, 0x0f, 0x85, 0x7b, 0x6f, 0x7f, 0x50, 0xee, 0xcb,
0x57, 0x47, 0xef, 0xeb, 0xee, 0xa4, 0xd0, 0xad, 0xcb, 0x84, 0xf6, 0x2b, 0xff, 0x2b, 0xe9, 0xe5,
0xf5, 0x91, 0xdb, 0x19, 0x2b, 0x6f, 0xe1, 0xb3, 0xed, 0xaf, 0x2c, 0x46, 0x2b, 0xd7, 0xfc, 0xb5,
0xaf, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x40, 0xf3, 0x96, 0x0b, 0xcf, 0x03, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// BuildsClient is the client API for Builds service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type BuildsClient interface {
ListBuilds(ctx context.Context, in *ListBuildsRequest, opts ...grpc.CallOption) (*ListBuildsReply, error)
GetBuild(ctx context.Context, in *GetBuildRequest, opts ...grpc.CallOption) (*GetBuildReply, error)
}
type buildsClient struct {
cc grpc.ClientConnInterface
}
func NewBuildsClient(cc grpc.ClientConnInterface) BuildsClient {
return &buildsClient{cc}
}
func (c *buildsClient) ListBuilds(ctx context.Context, in *ListBuildsRequest, opts ...grpc.CallOption) (*ListBuildsReply, error) {
out := new(ListBuildsReply)
err := c.cc.Invoke(ctx, "/spotify.backstage.builds.v1.Builds/ListBuilds", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *buildsClient) GetBuild(ctx context.Context, in *GetBuildRequest, opts ...grpc.CallOption) (*GetBuildReply, error) {
out := new(GetBuildReply)
err := c.cc.Invoke(ctx, "/spotify.backstage.builds.v1.Builds/GetBuild", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// BuildsServer is the server API for Builds service.
type BuildsServer interface {
ListBuilds(context.Context, *ListBuildsRequest) (*ListBuildsReply, error)
GetBuild(context.Context, *GetBuildRequest) (*GetBuildReply, error)
}
// UnimplementedBuildsServer can be embedded to have forward compatible implementations.
type UnimplementedBuildsServer struct {
}
func (*UnimplementedBuildsServer) ListBuilds(ctx context.Context, req *ListBuildsRequest) (*ListBuildsReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListBuilds not implemented")
}
func (*UnimplementedBuildsServer) GetBuild(ctx context.Context, req *GetBuildRequest) (*GetBuildReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBuild not implemented")
}
func RegisterBuildsServer(s *grpc.Server, srv BuildsServer) {
s.RegisterService(&_Builds_serviceDesc, srv)
}
func _Builds_ListBuilds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListBuildsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BuildsServer).ListBuilds(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/spotify.backstage.builds.v1.Builds/ListBuilds",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BuildsServer).ListBuilds(ctx, req.(*ListBuildsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Builds_GetBuild_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetBuildRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BuildsServer).GetBuild(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/spotify.backstage.builds.v1.Builds/GetBuild",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BuildsServer).GetBuild(ctx, req.(*GetBuildRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Builds_serviceDesc = grpc.ServiceDesc{
ServiceName: "spotify.backstage.builds.v1.Builds",
HandlerType: (*BuildsServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListBuilds",
Handler: _Builds_ListBuilds_Handler,
},
{
MethodName: "GetBuild",
Handler: _Builds_GetBuild_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "builds/v1/builds.proto",
}
+284 -23
View File
@@ -196,6 +196,186 @@ func (m *CreateEntityReply) GetEntity() *Entity {
return nil
}
type SetFactRequest struct {
EntityUri string `protobuf:"bytes,1,opt,name=entityUri,proto3" json:"entityUri,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SetFactRequest) Reset() { *m = SetFactRequest{} }
func (m *SetFactRequest) String() string { return proto.CompactTextString(m) }
func (*SetFactRequest) ProtoMessage() {}
func (*SetFactRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_70be9028e322f9d8, []int{4}
}
func (m *SetFactRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SetFactRequest.Unmarshal(m, b)
}
func (m *SetFactRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SetFactRequest.Marshal(b, m, deterministic)
}
func (m *SetFactRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_SetFactRequest.Merge(m, src)
}
func (m *SetFactRequest) XXX_Size() int {
return xxx_messageInfo_SetFactRequest.Size(m)
}
func (m *SetFactRequest) XXX_DiscardUnknown() {
xxx_messageInfo_SetFactRequest.DiscardUnknown(m)
}
var xxx_messageInfo_SetFactRequest proto.InternalMessageInfo
func (m *SetFactRequest) GetEntityUri() string {
if m != nil {
return m.EntityUri
}
return ""
}
func (m *SetFactRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *SetFactRequest) GetValue() string {
if m != nil {
return m.Value
}
return ""
}
type SetFactReply struct {
Fact *Fact `protobuf:"bytes,1,opt,name=fact,proto3" json:"fact,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SetFactReply) Reset() { *m = SetFactReply{} }
func (m *SetFactReply) String() string { return proto.CompactTextString(m) }
func (*SetFactReply) ProtoMessage() {}
func (*SetFactReply) Descriptor() ([]byte, []int) {
return fileDescriptor_70be9028e322f9d8, []int{5}
}
func (m *SetFactReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SetFactReply.Unmarshal(m, b)
}
func (m *SetFactReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SetFactReply.Marshal(b, m, deterministic)
}
func (m *SetFactReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_SetFactReply.Merge(m, src)
}
func (m *SetFactReply) XXX_Size() int {
return xxx_messageInfo_SetFactReply.Size(m)
}
func (m *SetFactReply) XXX_DiscardUnknown() {
xxx_messageInfo_SetFactReply.DiscardUnknown(m)
}
var xxx_messageInfo_SetFactReply proto.InternalMessageInfo
func (m *SetFactReply) GetFact() *Fact {
if m != nil {
return m.Fact
}
return nil
}
type GetFactRequest struct {
EntityUri string `protobuf:"bytes,1,opt,name=entityUri,proto3" json:"entityUri,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetFactRequest) Reset() { *m = GetFactRequest{} }
func (m *GetFactRequest) String() string { return proto.CompactTextString(m) }
func (*GetFactRequest) ProtoMessage() {}
func (*GetFactRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_70be9028e322f9d8, []int{6}
}
func (m *GetFactRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetFactRequest.Unmarshal(m, b)
}
func (m *GetFactRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetFactRequest.Marshal(b, m, deterministic)
}
func (m *GetFactRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetFactRequest.Merge(m, src)
}
func (m *GetFactRequest) XXX_Size() int {
return xxx_messageInfo_GetFactRequest.Size(m)
}
func (m *GetFactRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetFactRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetFactRequest proto.InternalMessageInfo
func (m *GetFactRequest) GetEntityUri() string {
if m != nil {
return m.EntityUri
}
return ""
}
func (m *GetFactRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
type GetFactReply struct {
Fact *Fact `protobuf:"bytes,1,opt,name=fact,proto3" json:"fact,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetFactReply) Reset() { *m = GetFactReply{} }
func (m *GetFactReply) String() string { return proto.CompactTextString(m) }
func (*GetFactReply) ProtoMessage() {}
func (*GetFactReply) Descriptor() ([]byte, []int) {
return fileDescriptor_70be9028e322f9d8, []int{7}
}
func (m *GetFactReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetFactReply.Unmarshal(m, b)
}
func (m *GetFactReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetFactReply.Marshal(b, m, deterministic)
}
func (m *GetFactReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetFactReply.Merge(m, src)
}
func (m *GetFactReply) XXX_Size() int {
return xxx_messageInfo_GetFactReply.Size(m)
}
func (m *GetFactReply) XXX_DiscardUnknown() {
xxx_messageInfo_GetFactReply.DiscardUnknown(m)
}
var xxx_messageInfo_GetFactReply proto.InternalMessageInfo
func (m *GetFactReply) GetFact() *Fact {
if m != nil {
return m.Fact
}
return nil
}
type Entity struct {
Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -207,7 +387,7 @@ func (m *Entity) Reset() { *m = Entity{} }
func (m *Entity) String() string { return proto.CompactTextString(m) }
func (*Entity) ProtoMessage() {}
func (*Entity) Descriptor() ([]byte, []int) {
return fileDescriptor_70be9028e322f9d8, []int{4}
return fileDescriptor_70be9028e322f9d8, []int{8}
}
func (m *Entity) XXX_Unmarshal(b []byte) error {
@@ -247,7 +427,7 @@ func (m *Fact) Reset() { *m = Fact{} }
func (m *Fact) String() string { return proto.CompactTextString(m) }
func (*Fact) ProtoMessage() {}
func (*Fact) Descriptor() ([]byte, []int) {
return fileDescriptor_70be9028e322f9d8, []int{5}
return fileDescriptor_70be9028e322f9d8, []int{9}
}
func (m *Fact) XXX_Unmarshal(b []byte) error {
@@ -287,6 +467,10 @@ func init() {
proto.RegisterType((*GetEntityReply)(nil), "spotify.backstage.inventory.v1.GetEntityReply")
proto.RegisterType((*CreateEntityRequest)(nil), "spotify.backstage.inventory.v1.CreateEntityRequest")
proto.RegisterType((*CreateEntityReply)(nil), "spotify.backstage.inventory.v1.CreateEntityReply")
proto.RegisterType((*SetFactRequest)(nil), "spotify.backstage.inventory.v1.SetFactRequest")
proto.RegisterType((*SetFactReply)(nil), "spotify.backstage.inventory.v1.SetFactReply")
proto.RegisterType((*GetFactRequest)(nil), "spotify.backstage.inventory.v1.GetFactRequest")
proto.RegisterType((*GetFactReply)(nil), "spotify.backstage.inventory.v1.GetFactReply")
proto.RegisterType((*Entity)(nil), "spotify.backstage.inventory.v1.Entity")
proto.RegisterType((*Fact)(nil), "spotify.backstage.inventory.v1.Fact")
}
@@ -294,27 +478,32 @@ func init() {
func init() { proto.RegisterFile("inventory/v1/inventory.proto", fileDescriptor_70be9028e322f9d8) }
var fileDescriptor_70be9028e322f9d8 = []byte{
// 307 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xc9, 0xcc, 0x2b, 0x4b,
0xcd, 0x2b, 0xc9, 0x2f, 0xaa, 0xd4, 0x2f, 0x33, 0xd4, 0x87, 0x73, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b,
0xf2, 0x85, 0xe4, 0x8a, 0x0b, 0xf2, 0x4b, 0x32, 0xd3, 0x2a, 0xf5, 0x92, 0x12, 0x93, 0xb3, 0x8b,
0x4b, 0x12, 0xd3, 0x53, 0xf5, 0x10, 0x4a, 0xca, 0x0c, 0x95, 0xca, 0xb9, 0x04, 0xdc, 0x53, 0x4b,
0x5c, 0xf3, 0x4a, 0x32, 0x4b, 0x2a, 0x83, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0xec, 0xb8,
0xd8, 0x52, 0xc1, 0x02, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x6a, 0x7a, 0xf8, 0x0d, 0xd1,
0x83, 0x6a, 0x87, 0xea, 0x12, 0x52, 0xe6, 0xe2, 0xcd, 0xcc, 0x4b, 0xce, 0x29, 0x4d, 0x49, 0x8d,
0x4f, 0x4b, 0x4c, 0x2e, 0x29, 0x96, 0x60, 0x52, 0x60, 0xd6, 0xe0, 0x0c, 0xe2, 0x81, 0x0a, 0xba,
0x81, 0xc4, 0x94, 0x7a, 0x18, 0xb9, 0xf8, 0x90, 0x6c, 0x2e, 0xc8, 0xa9, 0xa4, 0xd8, 0x5e, 0x2b,
0x2e, 0x56, 0x84, 0x7d, 0xdc, 0x46, 0x2a, 0x84, 0xb4, 0x83, 0x1c, 0x12, 0x04, 0xd1, 0xa2, 0x14,
0xca, 0x25, 0xec, 0x5c, 0x94, 0x9a, 0x58, 0x92, 0x4a, 0xd5, 0xa0, 0x50, 0x0a, 0xe6, 0x12, 0x44,
0x35, 0x96, 0x0a, 0xfe, 0x54, 0x92, 0xe2, 0x62, 0x83, 0x88, 0x08, 0x09, 0x70, 0x31, 0x97, 0x16,
0x65, 0x82, 0x8d, 0xe1, 0x0c, 0x02, 0x31, 0x95, 0x0c, 0xb8, 0x58, 0x40, 0xde, 0x12, 0x12, 0xe2,
0x62, 0xc9, 0x4b, 0xcc, 0x4d, 0x85, 0x4a, 0x81, 0xd9, 0x42, 0x22, 0x5c, 0xac, 0x65, 0x89, 0x39,
0xa5, 0xa9, 0x12, 0x4c, 0x60, 0x41, 0x08, 0xc7, 0xe8, 0x13, 0x23, 0x17, 0xa7, 0x27, 0xcc, 0x36,
0xa1, 0x5c, 0x2e, 0x4e, 0x78, 0xac, 0x08, 0x19, 0x10, 0x72, 0x18, 0x7a, 0xd2, 0x91, 0xd2, 0x23,
0x41, 0x07, 0x28, 0x28, 0xca, 0xb8, 0x78, 0x90, 0xc3, 0x47, 0xc8, 0x98, 0x90, 0x7e, 0x2c, 0x91,
0x24, 0x65, 0x48, 0x9a, 0xa6, 0x82, 0x9c, 0x4a, 0x27, 0xde, 0x28, 0x6e, 0xb8, 0x8a, 0x32, 0xc3,
0x24, 0x36, 0x70, 0x66, 0x31, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x24, 0xd0, 0xf1, 0x50, 0x4c,
0x03, 0x00, 0x00,
// 390 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4d, 0x4f, 0xc2, 0x40,
0x10, 0x4d, 0x29, 0x60, 0x3a, 0x7c, 0x04, 0x57, 0x0f, 0x4d, 0x43, 0x0c, 0x59, 0x8d, 0xe1, 0x60,
0x0a, 0x85, 0x8b, 0xf1, 0xe0, 0x01, 0xa3, 0xd5, 0x6b, 0x09, 0x89, 0xf1, 0x62, 0x0a, 0x2e, 0xa4,
0x11, 0x5a, 0x6c, 0xb7, 0x35, 0xfd, 0x0f, 0xfe, 0x2c, 0x7f, 0x98, 0xd9, 0xed, 0x5a, 0x8a, 0x21,
0x16, 0x02, 0xb7, 0xdd, 0x99, 0x79, 0xf3, 0x5e, 0x5f, 0x5f, 0x0b, 0x4d, 0xc7, 0x8d, 0x88, 0x4b,
0x3d, 0x3f, 0xee, 0x44, 0x46, 0x27, 0xbd, 0xe8, 0x4b, 0xdf, 0xa3, 0x1e, 0x3a, 0x0b, 0x96, 0x1e,
0x75, 0xa6, 0xb1, 0x3e, 0xb6, 0x27, 0xef, 0x01, 0xb5, 0x67, 0x44, 0x5f, 0x8d, 0x44, 0x06, 0xfe,
0x84, 0x86, 0x49, 0xe8, 0xbd, 0x4b, 0x1d, 0x1a, 0x5b, 0xe4, 0x23, 0x24, 0x01, 0x45, 0xb7, 0x50,
0x26, 0xbc, 0xa0, 0x4a, 0x2d, 0xa9, 0x5d, 0xe9, 0x5d, 0xea, 0xff, 0x2f, 0xd1, 0x05, 0x5c, 0xa0,
0xd0, 0x39, 0xd4, 0x1c, 0x77, 0x32, 0x0f, 0xdf, 0xc8, 0xeb, 0xd4, 0x9e, 0xd0, 0x40, 0x2d, 0xb4,
0xe4, 0xb6, 0x62, 0x55, 0x45, 0xf1, 0x81, 0xd5, 0xf0, 0x97, 0x04, 0xf5, 0x0c, 0xf3, 0x72, 0x1e,
0xef, 0xcd, 0x7b, 0x03, 0xa5, 0x15, 0x5f, 0xa5, 0x77, 0x91, 0x07, 0x67, 0x42, 0xac, 0x04, 0x82,
0x47, 0x70, 0x72, 0xe7, 0x13, 0x9b, 0x92, 0x83, 0x5a, 0x81, 0x87, 0x70, 0xbc, 0xbe, 0xf6, 0x00,
0xcf, 0x89, 0x9f, 0xa1, 0x3e, 0x24, 0x94, 0xab, 0x17, 0x32, 0x9b, 0xa0, 0x24, 0xbd, 0x91, 0xef,
0xf0, 0xa5, 0x8a, 0xb5, 0x2a, 0x20, 0x04, 0x45, 0xd7, 0x5e, 0x10, 0xb5, 0xc0, 0x1b, 0xfc, 0x8c,
0x4e, 0xa1, 0x14, 0xd9, 0xf3, 0x90, 0xa8, 0x32, 0x2f, 0x26, 0x17, 0xfc, 0x08, 0xd5, 0x74, 0x33,
0x53, 0x7a, 0x0d, 0x45, 0x66, 0x8f, 0xd0, 0xb9, 0x9d, 0xa1, 0x1c, 0x81, 0x07, 0xfc, 0xed, 0xee,
0xa5, 0x91, 0xa9, 0x31, 0x0f, 0xa3, 0x46, 0x83, 0x72, 0xe2, 0x21, 0x6a, 0x80, 0x1c, 0xa6, 0xfc,
0xec, 0x88, 0xbb, 0x50, 0x64, 0x93, 0xa9, 0x02, 0x69, 0x93, 0x4b, 0x85, 0x8c, 0x4b, 0xbd, 0x6f,
0x19, 0x94, 0xa7, 0x5f, 0x26, 0xb4, 0x00, 0x25, 0xcd, 0x31, 0xea, 0xe6, 0x89, 0xfa, 0xfb, 0xb1,
0x69, 0xfa, 0x0e, 0x08, 0x66, 0x42, 0x04, 0xd5, 0x6c, 0xa2, 0x50, 0x3f, 0x0f, 0xbf, 0x21, 0xd6,
0x9a, 0xb1, 0x1b, 0x88, 0xf1, 0xce, 0xe0, 0x48, 0x44, 0x03, 0xe5, 0x4a, 0x5e, 0x4f, 0xa7, 0x76,
0xb5, 0xf5, 0xbc, 0x20, 0x32, 0xb7, 0x25, 0x32, 0x77, 0x24, 0xca, 0xc6, 0x69, 0x50, 0x7b, 0xa9,
0xa4, 0xcd, 0xc8, 0x18, 0x97, 0xf9, 0x0f, 0xb3, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0x4f, 0xab,
0xd5, 0x54, 0x50, 0x05, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -331,6 +520,8 @@ const _ = grpc.SupportPackageIsVersion6
type InventoryClient interface {
GetEntity(ctx context.Context, in *GetEntityRequest, opts ...grpc.CallOption) (*GetEntityReply, error)
CreateEntity(ctx context.Context, in *CreateEntityRequest, opts ...grpc.CallOption) (*CreateEntityReply, error)
SetFact(ctx context.Context, in *SetFactRequest, opts ...grpc.CallOption) (*SetFactReply, error)
GetFact(ctx context.Context, in *GetFactRequest, opts ...grpc.CallOption) (*GetFactReply, error)
}
type inventoryClient struct {
@@ -359,10 +550,30 @@ func (c *inventoryClient) CreateEntity(ctx context.Context, in *CreateEntityRequ
return out, nil
}
func (c *inventoryClient) SetFact(ctx context.Context, in *SetFactRequest, opts ...grpc.CallOption) (*SetFactReply, error) {
out := new(SetFactReply)
err := c.cc.Invoke(ctx, "/spotify.backstage.inventory.v1.Inventory/SetFact", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *inventoryClient) GetFact(ctx context.Context, in *GetFactRequest, opts ...grpc.CallOption) (*GetFactReply, error) {
out := new(GetFactReply)
err := c.cc.Invoke(ctx, "/spotify.backstage.inventory.v1.Inventory/GetFact", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// InventoryServer is the server API for Inventory service.
type InventoryServer interface {
GetEntity(context.Context, *GetEntityRequest) (*GetEntityReply, error)
CreateEntity(context.Context, *CreateEntityRequest) (*CreateEntityReply, error)
SetFact(context.Context, *SetFactRequest) (*SetFactReply, error)
GetFact(context.Context, *GetFactRequest) (*GetFactReply, error)
}
// UnimplementedInventoryServer can be embedded to have forward compatible implementations.
@@ -375,6 +586,12 @@ func (*UnimplementedInventoryServer) GetEntity(ctx context.Context, req *GetEnti
func (*UnimplementedInventoryServer) CreateEntity(ctx context.Context, req *CreateEntityRequest) (*CreateEntityReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateEntity not implemented")
}
func (*UnimplementedInventoryServer) SetFact(ctx context.Context, req *SetFactRequest) (*SetFactReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetFact not implemented")
}
func (*UnimplementedInventoryServer) GetFact(ctx context.Context, req *GetFactRequest) (*GetFactReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetFact not implemented")
}
func RegisterInventoryServer(s *grpc.Server, srv InventoryServer) {
s.RegisterService(&_Inventory_serviceDesc, srv)
@@ -416,6 +633,42 @@ func _Inventory_CreateEntity_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler)
}
func _Inventory_SetFact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SetFactRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(InventoryServer).SetFact(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/spotify.backstage.inventory.v1.Inventory/SetFact",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(InventoryServer).SetFact(ctx, req.(*SetFactRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Inventory_GetFact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetFactRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(InventoryServer).GetFact(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/spotify.backstage.inventory.v1.Inventory/GetFact",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(InventoryServer).GetFact(ctx, req.(*GetFactRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Inventory_serviceDesc = grpc.ServiceDesc{
ServiceName: "spotify.backstage.inventory.v1.Inventory",
HandlerType: (*InventoryServer)(nil),
@@ -428,6 +681,14 @@ var _Inventory_serviceDesc = grpc.ServiceDesc{
MethodName: "CreateEntity",
Handler: _Inventory_CreateEntity_Handler,
},
{
MethodName: "SetFact",
Handler: _Inventory_SetFact_Handler,
},
{
MethodName: "GetFact",
Handler: _Inventory_GetFact_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "inventory/v1/inventory.proto",
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"google.golang.org/grpc/status"
identity "github.com/spotify/backstage/backend/proto/identity/v1"
pb "github.com/spotify/backstage/proto/scaffolder/v1"
pb "github.com/spotify/backstage/backend/proto/scaffolder/v1"
"github.com/spotify/backstage/scaffolder/fs"
"github.com/spotify/backstage/scaffolder/remote"
"github.com/spotify/backstage/scaffolder/repository"
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"log"
"net"
pb "github.com/spotify/backstage/proto/scaffolder/v1"
pb "github.com/spotify/backstage/backend/proto/scaffolder/v1"
"github.com/spotify/backstage/scaffolder/app"
"google.golang.org/grpc"
)
+9
View File
@@ -21,6 +21,15 @@ services:
volumes:
- ./backend/identity/identity-data.json:/app/identity-data.json
builds:
container_name: boss-builds
build:
context: backend
args:
service: builds
restart: unless-stopped
env_file: secrets.env
scaffolder:
container_name: boss-scaffolder
build:
+5 -1
View File
@@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"@backstage/core": "0.0.0",
"@backstage/plugin-github-actions": "0.0.0",
"@backstage/plugin-hello-world": "0.0.0",
"@backstage/plugin-home-page": "0.0.0",
"@backstage/plugin-login": "0.0.0",
@@ -16,10 +17,13 @@
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/react-router-dom": "^5.1.3",
"@types/zen-observable": "^0.8.0",
"cross-env": "^7.0.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2"
"react-router-dom": "^5.1.2",
"react-use": "^13.24.0",
"zen-observable": "^0.8.15"
},
"workspaces": {
"nohoist": [
-10
View File
@@ -1,10 +0,0 @@
import React from 'react';
import { render } from '@testing-library/react';
import App from './App';
describe('App', () => {
it('renders learn react link', () => {
const rendered = render(<App />);
rendered.getByText('This is Backstage!');
});
});
+15 -24
View File
@@ -6,20 +6,17 @@ import {
Page,
theme,
} from '@backstage/core';
import HomePagePlugin from '@backstage/plugin-home-page';
//import PageHeader from './components/PageHeader';
import { LoginComponent } from '@backstage/plugin-login';
import HomePagePlugin from '@backstage/plugin-home-page';
import { CssBaseline, makeStyles, ThemeProvider } from '@material-ui/core';
import React, { FC } from 'react';
import {
BrowserRouter as Router,
Link as RouterLink,
Route,
Switch,
} from 'react-router-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import HomePageTimer from './components/HomepageTimer';
import SideBar from './components/SideBar';
import entities from './entities';
import { LoginBarrier } from './login/LoginBarrier';
import { MockCurrentUser } from './login/MockCurrentUser';
const useStyles = makeStyles(theme => ({
'@global': {
@@ -39,7 +36,7 @@ const useStyles = makeStyles(theme => ({
root: {
display: 'grid',
// FIXME: Don't used a fixed width here
gridTemplateColumns: '224px auto',
gridTemplateColumns: '64px auto',
gridTemplateRows: 'auto 1fr',
width: '100%',
height: '100vh',
@@ -56,13 +53,12 @@ const useStyles = makeStyles(theme => ({
},
}));
const currentUser = new MockCurrentUser();
const Login: FC<{}> = () => {
return (
<InfoCard title="Login Page">
<LoginComponent />
<div>
<RouterLink to="/">Go to Home</RouterLink>
</div>
<LoginComponent onLogin={username => currentUser.login(username)} />
</InfoCard>
);
};
@@ -96,18 +92,13 @@ const App: FC<{}> = () => {
return (
<CssBaseline>
<ThemeProvider theme={BackstageTheme}>
<AppShell>
<Router>
<Switch>
<Route path="/login">
<Login />
</Route>
<Route>
<AppComponent />
</Route>
</Switch>
</Router>
</AppShell>
<Router>
<LoginBarrier fallback={Login} state$={currentUser.state}>
<AppShell>
<AppComponent />
</AppShell>
</LoginBarrier>
</Router>
</ThemeProvider>
</CssBaseline>
);
@@ -1,60 +1,221 @@
import Avatar from '@material-ui/core/Avatar';
import Grid from '@material-ui/core/Grid';
import Link from '@material-ui/core/Link';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import React, { FC } from 'react';
import React, { FC, useState, createContext, useContext } from 'react';
import clsx from 'clsx';
import {
makeStyles,
SvgIcon,
Typography,
Link,
styled,
} from '@material-ui/core';
import HomeIcon from '@material-ui/icons/Home';
import ServiceIcon from '@material-ui/icons/DeviceHub';
import WebIcon from '@material-ui/icons/Language';
import LibIcon from '@material-ui/icons/LocalLibrary';
import CreateIcon from '@material-ui/icons/AddCircleOutline';
const drawerWidthClosed = 64;
const drawerWidthOpen = 220;
const Context = createContext<boolean>(false);
const useSidebarItemStyles = makeStyles({
root: {
color: '#b5b5b5',
display: 'flex',
flexFlow: 'row nowrap',
alignItems: 'center',
height: 40,
cursor: 'pointer',
},
closed: {
width: drawerWidthClosed,
justifyContent: 'center',
},
open: {
width: drawerWidthOpen,
},
iconContainer: {
height: '100%',
width: drawerWidthClosed,
marginRight: -16,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
});
type SidebarItemProps = {
icon: typeof SvgIcon;
text: string;
to?: string;
onClick?: () => void;
};
const SidebarItem: FC<SidebarItemProps> = ({
icon: Icon,
text,
to,
onClick,
}) => {
const classes = useSidebarItemStyles();
const open = useContext(Context);
if (!open) {
return (
<Link
className={clsx(classes.root, classes.closed)}
href={to}
onClick={onClick}
underline="none"
>
<Icon fontSize="small" />
</Link>
);
}
return (
<Link
className={clsx(classes.root, classes.open)}
href={to}
onClick={onClick}
underline="none"
>
<div className={classes.iconContainer}>
<Icon fontSize="small" />
</div>
<Typography variant="subtitle2">{text}</Typography>
</Link>
);
};
const useSidebarLogoStyles = makeStyles({
root: {
height: drawerWidthClosed,
color: '#fff',
display: 'flex',
flexFlow: 'row nowrap',
alignItems: 'center',
},
logoContainer: {
width: drawerWidthClosed,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
logo: {
fontSize: 32,
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginLeft: 22,
whiteSpace: 'nowrap',
},
titleDot: {
color: '#1DB954',
},
});
const SidebarLogo: FC<{}> = () => {
const classes = useSidebarLogoStyles();
const open = useContext(Context);
return (
<div className={classes.root}>
<Typography variant="h6" color="inherit" className={classes.title}>
{open ? 'Backstage' : 'B'}
<span className={classes.titleDot}>.</span>
</Typography>
</div>
);
};
const Space = styled('div')({
flex: 1,
});
const Spacer = styled('div')({
height: 8,
});
const Divider = styled('hr')({
height: 1,
width: '100%',
background: '#383838',
border: 'none',
});
const useStyles = makeStyles(theme => ({
root: {
background: '#181818',
color: 'white',
zIndex: 1000,
position: 'relative',
overflow: 'visible',
width: theme.spacing(7) + 1,
height: '100vh',
paddingLeft: theme.spacing(2),
paddingTop: theme.spacing(2),
},
drawer: {
display: 'flex',
flexFlow: 'column nowrap',
alignItems: 'flex-start',
position: 'absolute',
left: 0,
top: 0,
bottom: 0,
padding: 0,
background: '#171717',
overflowX: 'hidden',
width: drawerWidthClosed,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.shortest,
}),
},
drawerOpen: {
width: drawerWidthOpen,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.shorter,
}),
},
}));
const SideBar: FC<{}> = () => {
const classes = useStyles();
const [open, setOpen] = useState(false);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div className={classes.root}>
<Link href="#" variant="body1">
[Co-brand Logo]
</Link>
<List component="nav">
<ListItem button>
<ListItemText primary="Home" />
</ListItem>
<ListItem button>
<ListItemText primary="Services" />
</ListItem>
<ListItem button>
<ListItemText primary="Libraries" />
</ListItem>
<ListItem button>
<ListItemText primary="Websites" />
</ListItem>
<ListItem button>
<ListItemText primary="+ Create..." />
</ListItem>
</List>
<Grid
container
direction="row"
justify="flex-start"
alignItems="center"
spacing={2}
>
<Grid item>
<Avatar>A</Avatar>
</Grid>
<Typography variant="caption">$userName</Typography>
</Grid>
<div
className={classes.root}
onMouseEnter={handleOpen}
onFocus={handleOpen}
onMouseLeave={handleClose}
onBlur={handleClose}
data-testid="sidebar-root"
>
<Context.Provider value={open}>
<div className={clsx(classes.drawer, { [classes.drawerOpen]: open })}>
<SidebarLogo />
<Spacer />
<Divider />
<SidebarItem icon={HomeIcon} to="/" text="Home" />
<Divider />
<SidebarItem icon={ServiceIcon} to="/services" text="Services" />
<SidebarItem icon={WebIcon} to="/websites" text="Websites" />
<SidebarItem icon={LibIcon} to="/libraries" text="Libraries" />
<Divider />
<Space />
<SidebarItem icon={CreateIcon} text="Create..." />
</div>
</Context.Provider>
</div>
);
};
+6 -4
View File
@@ -1,20 +1,22 @@
import {
createEntityKind,
createWidgetView,
createEntityView,
createEntityPage,
} from '@backstage/core';
import ComputerIcon from '@material-ui/icons/Computer';
import MockEntityPage from './MockEntityPage';
import MockEntityCard from './MockEntityCard';
import GithubActionsPlugin from '@backstage/plugin-github-actions';
/* SERVICE */
const serviceOverviewPage = createWidgetView()
.addComponent(MockEntityCard)
.addComponent(MockEntityCard);
const serviceView = createEntityView()
.addPage('Overview', 'overview', serviceOverviewPage)
.addComponent('CI/CD', 'ci-cd', MockEntityPage);
const serviceView = createEntityPage()
.addPage('Overview', '/overview', serviceOverviewPage)
.register(GithubActionsPlugin)
.addComponent('Deployment', '/deployment', MockEntityPage);
const serviceEntity = createEntityKind({
kind: 'service',
@@ -0,0 +1,57 @@
import { render, wait, act } from '@testing-library/react';
import React from 'react';
import Observable from 'zen-observable';
import { LoginBarrier } from './LoginBarrier';
import { LoginState } from './types';
describe('LoginBarrier', () => {
it('passes through when logged in', async () => {
const state$ = Observable.of<LoginState>({
type: 'LOGGED_IN',
user: 'apa',
});
const rendered = render(
<LoginBarrier
state$={state$}
fallback={({ state }) => <div>{state.type}</div>}
>
Logged in!
</LoginBarrier>,
);
await wait(() => rendered.getByText('Logged in!'));
});
it('goes to fallback when not logged in', async () => {
const state$ = Observable.of<LoginState>({ type: 'LOGGED_OUT' });
const rendered = render(
<LoginBarrier
state$={state$}
fallback={({ state }) => <div>{state.type}</div>}
>
Logged in!
</LoginBarrier>,
);
await wait(() => rendered.getByText('LOGGED_OUT'));
});
it('transitions between states', async () => {
let subscriber: ZenObservable.SubscriptionObserver<LoginState> | undefined;
const state$ = new Observable<LoginState>(s => {
subscriber = s;
});
const rendered = render(
<LoginBarrier
state$={state$}
fallback={({ state }) => <div>{state.type}</div>}
>
Logged in!
</LoginBarrier>,
);
await wait(() => rendered.getByText('LOGGED_OUT'));
// @ts-ignore: Object is possibly 'undefined'
act(() => subscriber.next({ type: 'LOGGED_IN', user: 'apa' }));
await wait(() => rendered.getByText('Logged in!'));
});
});
@@ -0,0 +1,22 @@
import React, { FC } from 'react';
import Observable from 'zen-observable';
import { useObservable } from 'react-use';
import { LoginState } from './types';
type LoginBarrierProps = {
fallback: React.ComponentType<{ state: LoginState }>;
state$: Observable<LoginState>;
};
export const LoginBarrier: FC<LoginBarrierProps> = ({
fallback: Fallback,
state$,
children,
}) => {
const state = useObservable(state$, { type: 'LOGGED_OUT' });
if (state.type === 'LOGGED_IN') {
return <>{children}</>;
} else {
return <Fallback state={state} />;
}
};
@@ -0,0 +1,38 @@
import { MockCurrentUser } from './MockCurrentUser';
import { wait } from '@testing-library/react';
describe('MockCurrentUser', () => {
it('notifies immediately on subscribe', async () => {
const next = jest.fn();
const current = new MockCurrentUser();
current.state.subscribe(next);
await wait();
expect(next).toHaveBeenNthCalledWith(
1,
expect.objectContaining({ type: 'LOGGED_OUT' }),
);
});
it('logs in and out', async () => {
const next = jest.fn();
const current = new MockCurrentUser();
current.state.subscribe(next);
await wait();
expect(next).toHaveBeenNthCalledWith(
1,
expect.objectContaining({ type: 'LOGGED_OUT' }),
);
current.login('apa');
await wait();
expect(next).toHaveBeenNthCalledWith(
2,
expect.objectContaining({ type: 'LOGGED_IN', user: 'apa' }),
);
current.logout();
await wait();
expect(next).toHaveBeenNthCalledWith(
3,
expect.objectContaining({ type: 'LOGGED_OUT' }),
);
});
});
@@ -0,0 +1,67 @@
import Observable from 'zen-observable';
import { LoginState } from './types';
const LOCAL_STORAGE_KEY = 'mock_current_user';
export class MockCurrentUser {
private listeners: ZenObservable.SubscriptionObserver<LoginState>[];
private currentUser: string | undefined;
constructor() {
this.listeners = [];
this.currentUser = undefined;
this.loadPrevious();
}
login(user: string) {
this.currentUser = user;
this.saveCurrent();
this.notify();
}
logout() {
this.currentUser = undefined;
this.saveCurrent();
this.notify();
}
get state(): Observable<LoginState> {
return new Observable(subscriber => {
this.listeners.push(subscriber);
subscriber.next(this.getState());
return () => {
this.listeners = this.listeners.filter(x => x !== subscriber);
};
});
}
private loadPrevious() {
const user = localStorage.getItem(LOCAL_STORAGE_KEY);
if (user) {
try {
this.currentUser = JSON.parse(user);
} catch (e) {
localStorage.removeItem(LOCAL_STORAGE_KEY);
}
}
}
private saveCurrent() {
if (!this.currentUser) {
localStorage.removeItem(LOCAL_STORAGE_KEY);
} else {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(this.currentUser));
}
}
private notify() {
const state = this.getState();
this.listeners.forEach(listener => listener.next(state));
}
private getState(): LoginState {
return this.currentUser
? { type: 'LOGGED_IN', user: this.currentUser }
: { type: 'LOGGED_OUT' };
}
}
+11
View File
@@ -0,0 +1,11 @@
export type LoggedOutState = { type: 'LOGGED_OUT' };
export type LoggingInState = { type: 'LOGGING_IN' };
export type LoggedInState = { type: 'LOGGED_IN'; user: string };
export type LoggingOutState = { type: 'LOGGING_OUT' };
export type LoginFailedState = { type: 'LOGIN_FAILED'; error: Error };
export type LoginState =
| LoggedOutState
| LoggingInState
| LoggedInState
| LoggingOutState
| LoginFailedState;
+3 -3
View File
@@ -1,7 +1,7 @@
import AppBuilder from './app/AppBuilder';
import EntityKind, { EntityConfig } from './entity/EntityKind';
import WidgetViewBuilder from './widgetView/WidgetViewBuilder';
import EntityViewBuilder from './entityView/EntityViewPageBuilder';
import EntityPageBuilder from './entityView/EntityPageBuilder';
import BackstagePlugin, { PluginConfig } from './plugin/Plugin';
export function createApp() {
@@ -16,8 +16,8 @@ export function createWidgetView() {
return new WidgetViewBuilder();
}
export function createEntityView() {
return new EntityViewBuilder();
export function createEntityPage() {
return new EntityPageBuilder();
}
export function createPlugin(config: PluginConfig): BackstagePlugin {
@@ -1,10 +1,10 @@
import React, { ComponentType, FC } from 'react';
import { Route, Switch, useParams } from 'react-router-dom';
import { Route, Switch, useParams, Redirect } from 'react-router-dom';
import { AppContextProvider } from './AppContext';
import { App, AppComponentBuilder } from './types';
import EntityKind, { EntityConfig } from '../entity/EntityKind';
import { EntityContextProvider } from '../entityView/EntityContext';
import BackstagePlugin, { registerSymbol } from '../plugin/Plugin';
import BackstagePlugin from '../plugin/Plugin';
class AppImpl implements App {
constructor(private readonly entities: Map<string, EntityKind>) {}
@@ -97,8 +97,31 @@ export default class AppBuilder {
const pluginRoutes = new Array<JSX.Element>();
for (const plugin of this.plugins.values()) {
const { routes = [] } = plugin[registerSymbol]();
pluginRoutes.push(...routes);
for (const output of plugin.output()) {
switch (output.type) {
case 'route': {
const { path, component, options = {} } = output;
const { exact = true } = options;
pluginRoutes.push(
<Route
key={path}
path={path}
component={component}
exact={exact}
/>,
);
break;
}
case 'redirect-route': {
const { path, target, options = {} } = output;
const { exact = true } = options;
pluginRoutes.push(
<Redirect key={path} path={path} to={target} exact={exact} />,
);
break;
}
}
}
}
const routes = [...pluginRoutes, ...entityRoutes];
@@ -0,0 +1,167 @@
import React, { ComponentType, FC } from 'react';
import { Route, Redirect, Switch } from 'react-router-dom';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import { AppComponentBuilder, App } from '../app/types';
import { useEntity, useEntityUri, useEntityConfig } from './EntityContext';
import EntityLink from '../../components/EntityLink/EntityLink';
import BackstagePlugin from '../plugin/Plugin';
const EntityLayout: FC<{}> = ({ children }) => {
const config = useEntityConfig();
return (
<div style={{ backgroundColor: config.color.primary }}>{children}</div>
);
};
const EntitySidebar: FC<{}> = ({ children }) => {
return <List>{children}</List>;
};
const EntitySidebarItem: FC<{ title: string; path: string }> = ({
title,
path,
}) => {
const entityUri = useEntityUri();
return (
<ListItem>
<EntityLink uri={entityUri} subPath={path}>
{title}
</EntityLink>
</ListItem>
);
};
type EntityPageNavItem = {
title: string;
target: string;
};
type EntityPageView = {
path: string;
component: ComponentType<any>;
};
type Props = {
navItems: EntityPageNavItem[];
views: EntityPageView[];
};
const EntityPageComponent: FC<Props> = ({ navItems, views }) => {
const { kind, id } = useEntity();
const basePath = `/entity/${kind}/${id}`;
return (
<EntityLayout>
<EntitySidebar>
{navItems.map(({ title, target }) => (
<EntitySidebarItem key={target} title={title} path={target} />
))}
</EntitySidebar>
<Switch>
{views.map(({ path, component }) => (
<Route
key={path}
exact
path={`${basePath}${path}`}
component={component}
/>
))}
<Redirect from={basePath} to={`${basePath}${views[0].path}`} />
</Switch>
</EntityLayout>
);
};
type EntityPageRegistration =
| {
type: 'page';
title: string;
path: string;
page: AppComponentBuilder;
}
| {
type: 'plugin';
plugin: BackstagePlugin;
}
| {
type: 'component';
title: string;
path: string;
component: ComponentType<any>;
};
export default class EntityPageBuilder extends AppComponentBuilder {
private readonly registrations = new Array<EntityPageRegistration>();
addPage(
title: string,
path: string,
page: AppComponentBuilder,
): EntityPageBuilder {
this.registrations.push({ type: 'page', title, path, page });
return this;
}
addComponent(
title: string,
path: string,
component: ComponentType<any>,
): EntityPageBuilder {
this.registrations.push({ type: 'component', title, path, component });
return this;
}
register(plugin: BackstagePlugin): EntityPageBuilder {
this.registrations.push({ type: 'plugin', plugin });
return this;
}
build(app: App): ComponentType<any> {
const navItems = new Array<EntityPageNavItem>();
const views = new Array<EntityPageView>();
for (const reg of this.registrations) {
switch (reg.type) {
case 'page': {
const { title, path, page } = reg;
navItems.push({ title, target: path });
views.push({ path, component: page.build(app) });
break;
}
case 'component': {
const { title, path, component } = reg;
navItems.push({ title, target: path });
views.push({ path, component });
break;
}
case 'plugin': {
let added = false;
for (const output of reg.plugin.output()) {
switch (output.type) {
case 'entity-page-nav-item':
const { title, target } = output;
navItems.push({ title, target });
added = true;
break;
case 'entity-page-view-route':
const { path, component } = output;
views.push({ path, component });
added = true;
break;
}
}
if (!added) {
throw new Error(
`Plugin ${reg.plugin} was registered as entity view, but did not provide any output`,
);
}
break;
}
}
}
return () => <EntityPageComponent navItems={navItems} views={views} />;
}
}
@@ -1,124 +0,0 @@
import React, { ComponentType, FC } from 'react';
import { Route, Redirect, Switch } from 'react-router-dom';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import { AppComponentBuilder, App } from '../app/types';
import { useEntity, useEntityUri, useEntityConfig } from './EntityContext';
import EntityLink from '../../components/EntityLink/EntityLink';
const EntityLayout: FC<{}> = ({ children }) => {
const config = useEntityConfig();
return (
<div style={{ backgroundColor: config.color.primary }}>{children}</div>
);
};
const EntitySidebar: FC<{}> = ({ children }) => {
return <List>{children}</List>;
};
const EntitySidebarItem: FC<{ title: string; path: string }> = ({
title,
path,
}) => {
const entityUri = useEntityUri();
return (
<ListItem>
<EntityLink uri={entityUri} subPath={path}>
{title}
</EntityLink>
</ListItem>
);
};
type EntityViewPage = {
title: string;
path: string;
component: ComponentType<any>;
};
type Props = {
pages: EntityViewPage[];
};
const EntityViewComponent: FC<Props> = ({ pages }) => {
const { kind, id } = useEntity();
const basePath = `/entity/${kind}/${id}`;
return (
<EntityLayout>
<EntitySidebar>
{pages.map(({ title, path }) => (
<EntitySidebarItem key={path} title={title} path={path} />
))}
</EntitySidebar>
<Switch>
{pages.map(({ path, component }) => (
<Route
key={path}
exact
path={`${basePath}/${path}`}
component={component}
/>
))}
<Redirect from={basePath} to={`${basePath}/${pages[0].path}`} />
</Switch>
</EntityLayout>
);
};
type EntityViewRegistration =
| {
type: 'page';
title: string;
path: string;
page: AppComponentBuilder;
}
| {
type: 'component';
title: string;
path: string;
component: ComponentType<any>;
};
export default class EntityViewBuilder extends AppComponentBuilder {
private readonly registrations = new Array<EntityViewRegistration>();
addPage(
title: string,
path: string,
page: AppComponentBuilder,
): EntityViewBuilder {
this.registrations.push({ type: 'page', title, path, page });
return this;
}
addComponent(
title: string,
path: string,
component: ComponentType<any>,
): EntityViewBuilder {
this.registrations.push({ type: 'component', title, path, component });
return this;
}
build(app: App): ComponentType<any> {
const pages = this.registrations.map(registration => {
switch (registration.type) {
case 'page': {
const { title, path, page } = registration;
return { title, path, component: page.build(app) };
}
case 'component': {
const { title, path, component } = registration;
return { title, path, component };
}
default:
throw new Error(`Unknown EntityViewBuilder registration`);
}
});
return () => <EntityViewComponent pages={pages} />;
}
}
@@ -1,5 +1,5 @@
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { ComponentType } from 'react';
import { PluginOutput, RoutePath, RouteOptions } from './types';
export type PluginConfig = {
id: string;
@@ -7,89 +7,98 @@ export type PluginConfig = {
};
export type PluginHooks = {
router: Router;
router: RouterHooks;
entityPage: EntityPageHooks;
};
export type RouteOptions = {
// Whether the route path must match exactly, defaults to true.
exact?: boolean;
};
export type RedirectOptions = {
// Whether the route path must match exactly, defaults to true.
exact?: boolean;
};
export type Router = {
export type RouterHooks = {
registerRoute(
path: string,
Component: React.ComponentType<any>,
path: RoutePath,
Component: ComponentType<any>,
options?: RouteOptions,
): void;
registerRedirect(
path: string,
target: string,
options?: RedirectOptions,
path: RoutePath,
target: RoutePath,
options?: RouteOptions,
): void;
};
export type PluginRegistrationResult = {
routes?: JSX.Element[];
type EntityPageSidebarItemOptions = {
title: string;
target: RoutePath;
};
export type EntityPageHooks = {
navItem(options: EntityPageSidebarItemOptions): void;
route(
path: RoutePath,
component: ComponentType<any>,
options?: RouteOptions,
): void;
};
export const registerSymbol = Symbol('plugin-register');
export const outputSymbol = Symbol('plugin-output');
export default class Plugin {
private result?: PluginRegistrationResult;
private storedOutput?: PluginOutput[];
constructor(private readonly config: PluginConfig) {}
[registerSymbol](): PluginRegistrationResult {
if (this.result) {
return this.result;
output(): PluginOutput[] {
if (this.storedOutput) {
return this.storedOutput;
}
if (!this.config.register) {
return {};
return [];
}
const { id } = this.config;
const routes = new Array<JSX.Element>();
const outputs = new Array<PluginOutput>();
this.config.register({
router: {
registerRoute(path, component, options = {}) {
registerRoute(path, component, options) {
if (path.startsWith('/entity/')) {
throw new Error(
`Plugin ${id} tried to register forbidden route ${path}`,
);
}
const { exact = true } = options;
routes.push(
<Route
key={path}
path={path}
component={component}
exact={exact}
/>,
);
outputs.push({ type: 'route', path, component, options });
},
registerRedirect(path, target, options = {}) {
registerRedirect(path, target, options) {
if (path.startsWith('/entity/')) {
throw new Error(
`Plugin ${id} tried to register forbidden redirect ${path}`,
);
}
const { exact = true } = options;
routes.push(
<Redirect key={path} path={path} to={target} exact={exact} />,
);
outputs.push({ type: 'redirect-route', path, target, options });
},
},
entityPage: {
navItem({ title, target }) {
outputs.push({
type: 'entity-page-nav-item',
target,
title,
});
},
route(path, component, options) {
outputs.push({
type: 'entity-page-view-route',
path,
component,
options,
});
},
},
});
this.result = { routes };
return this.result;
this.storedOutput = outputs;
return this.storedOutput;
}
toString() {
@@ -0,0 +1,41 @@
import { ComponentType } from 'react';
export type RouteOptions = {
// Whether the route path must match exactly, defaults to true.
exact?: boolean;
};
export type RoutePath = string;
export type RouteOutput = {
type: 'route';
path: RoutePath;
component: ComponentType<{}>;
options?: RouteOptions;
};
export type RedirectRouteOutput = {
type: 'redirect-route';
path: RoutePath;
target: RoutePath;
options?: RouteOptions;
};
export type EntityPageViewRouteOutput = {
type: 'entity-page-view-route';
path: RoutePath;
component: ComponentType<any>;
options?: RouteOptions;
};
export type EntityPageNavItemOutput = {
type: 'entity-page-nav-item';
title: string;
target: RoutePath;
};
export type PluginOutput =
| RouteOutput
| RedirectRouteOutput
| EntityPageViewRouteOutput
| EntityPageNavItemOutput;
@@ -9,8 +9,8 @@ type Props = {
const WidgetViewComponent: FC<Props> = ({ cards }) => {
return (
<div>
{cards.map(CardComponent => (
<CardComponent />
{cards.map((CardComponent, index) => (
<CardComponent key={index} />
))}
</div>
);
@@ -13,10 +13,10 @@ type Props = {
}
);
function buildPath(kind: string, id?: string, subPath?: string) {
export function buildPath(kind: string, id?: string, subPath?: string) {
if (id) {
if (subPath) {
return `/entity/${kind}/${id}/${subPath}`;
return `/entity/${kind}/${id}/${subPath.replace(/^\//, '')}`;
}
return `/entity/${kind}/${id}`;
}
@@ -0,0 +1,16 @@
import React, { FC } from 'react';
import { Link } from 'react-router-dom';
import { useEntity } from '../../api';
import { buildPath } from './EntityLink';
type Props = {
view: string;
};
const RelativeEntityLink: FC<Props> = ({ view, children }) => {
const entity = useEntity();
return <Link to={buildPath(entity.kind, entity.id, view)}>{children}</Link>;
};
export default RelativeEntityLink;
@@ -1 +1,2 @@
export { default } from './EntityLink';
export { default as RelativeEntityLink } from './RelativeEntityLink';
+4 -1
View File
@@ -1,5 +1,8 @@
export * from './api';
export { default as EntityLink } from './components/EntityLink';
export {
default as EntityLink,
RelativeEntityLink,
} from './components/EntityLink';
export { default as Page } from '../src/layout/Page';
export { gradients, theme } from '../src/layout/Page';
export { default as Header } from '../src/layout/Header/Header';
@@ -26,9 +26,9 @@ class Header extends Component {
return typeLink ? (
// <Link to={typeLink}>
<Typography className={classes.type}>{type}</Typography>
// </Link>
<Typography className={classes.type}>{type}</Typography>
) : (
// </Link>
<Typography className={classes.type}>{type}</Typography>
);
}
@@ -69,12 +69,17 @@ class Header extends Component {
const { title, pageTitleOverride, children, style, classes } = this.props;
const pageTitle = pageTitleOverride || title;
if (typeof pageTitle !== 'string') {
console.warn('<Header/> title prop is not a string, pageTitleOverride should be provided.');
console.warn(
'<Header/> title prop is not a string, pageTitleOverride should be provided.',
);
}
return (
<Fragment>
<Helmet titleTemplate={`${pageTitle} | %s | Backstage`} defaultTitle={`${pageTitle} | Backstage`} />
<Helmet
titleTemplate={`${pageTitle} | %s | Backstage`}
defaultTitle={`${pageTitle} | Backstage`}
/>
<Theme.Consumer>
{theme => (
<header style={style} className={classes.header}>
@@ -98,7 +103,7 @@ const styles = theme => ({
gridArea: 'pageHeader',
padding: theme.spacing(3),
minHeight: 118,
width: 'calc(100vw - 224px)',
width: '100vw',
boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)',
position: 'relative',
zIndex: 100,
@@ -117,6 +122,7 @@ const styles = theme => ({
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center',
marginRight: theme.spacing(6),
},
title: {
color: theme.palette.bursts.fontColor,
@@ -0,0 +1 @@
Welcome to your github-actions plugin!
@@ -0,0 +1,4 @@
module.exports = {
...require('@spotify/web-scripts/config/jest.config.js'),
setupFilesAfterEnv: ['../jest.setup.ts'],
};
@@ -0,0 +1 @@
import '@testing-library/jest-dom/extend-expect';
@@ -0,0 +1,28 @@
{
"name": "@backstage/plugin-github-actions",
"version": "0.0.0",
"main": "src/index.ts",
"main:src": "src/index.ts",
"devDependencies": {
"@backstage/core": "0.0.0",
"@spotify/web-scripts": "^6.0.0",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"@types/jest": "^24.0.0",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/react-router-dom": "^5.1.3",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
"@material-ui/core": "^4.9.1",
"@material-ui/icons": "^4.9.1"
},
"scripts": {
"lint": "web-scripts lint",
"test": "web-scripts test"
},
"license": "Apache-2.0"
}
@@ -0,0 +1,20 @@
import React, { FC } from 'react';
import Button from '@material-ui/core/Button';
type Props = {
buildId: string;
};
const BuildDetailsPage: FC<Props> = ({ buildId }) => {
return (
<Button
variant="contained"
color="primary"
onClick={() => window.location.reload()}
>
Hello! Build details for {buildId}
</Button>
);
};
export default BuildDetailsPage;
@@ -0,0 +1 @@
export { default } from './BuildDetailsPage';
@@ -0,0 +1,8 @@
import React, { FC } from 'react';
import { InfoCard } from '@backstage/core';
const BuildInfoCard: FC<{}> = () => {
return <InfoCard>Last build was acb67fa3b5472w</InfoCard>;
};
export default BuildInfoCard;
@@ -0,0 +1 @@
export { default } from './BuildInfoCard';
@@ -0,0 +1,46 @@
import React, { FC } from 'react';
import {
TableContainer,
Table,
TableHead,
TableRow,
TableCell,
Paper,
TableBody,
} from '@material-ui/core';
import { RelativeEntityLink } from '@backstage/core';
const BuildListPage: FC<{}> = () => {
const rows = [
{ message: 'Fixed a Bar', commit: 'fb46ca3dfbd7af5bc43da', id: 165 },
{ message: 'Fixed a Foo', commit: 'd7af5bc43dafb46ca3dfb', id: 164 },
];
return (
<TableContainer component={Paper}>
<Table aria-label="CI/CD builds table">
<TableHead>
<TableRow>
<TableCell>Message</TableCell>
<TableCell>Commit</TableCell>
<TableCell>Build ID</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map(row => (
<TableRow key={row.commit}>
<TableCell>{row.message}</TableCell>
<TableCell>{row.commit}</TableCell>
<TableCell>
<RelativeEntityLink view={`builds/${row.id}`}>
{row.commit}
</RelativeEntityLink>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
export default BuildListPage;
@@ -0,0 +1 @@
export { default } from './BuildListPage';
@@ -0,0 +1 @@
export { default } from './plugin';
@@ -0,0 +1,7 @@
import plugin from './plugin';
describe('github-actions', () => {
it('should export plugin', () => {
expect(plugin).toBeDefined();
});
});
@@ -0,0 +1,16 @@
import { createPlugin } from '@backstage/core';
import BuildDetailsPage from './components/BuildDetailsPage';
import BuildListPage from './components/BuildListPage';
// export const buildListRoute = createEntityRoute<[]>('/builds')
// export const buildDetailsRoute = createEntityRoute<[number]>('/builds/:buildId')
export default createPlugin({
id: 'github-actions',
register({ entityPage }) {
entityPage.navItem({ title: 'CI/CD', target: '/builds' });
entityPage.route('/builds', BuildListPage);
entityPage.route('/builds/:buildId', BuildDetailsPage);
},
});
@@ -22,8 +22,7 @@
},
"scripts": {
"lint": "web-scripts lint",
"test": "web-scripts test",
"proto": "../../../scripts/gen-proto.sh hello.proto"
"test": "web-scripts test"
},
"license": "Apache-2.0"
}
@@ -1,14 +1,12 @@
import React, { FC } from 'react';
import { InfoCard, EntityLink } from '@backstage/core';
import { Link } from 'react-router-dom';
import { EntityLink, InfoCard } from '@backstage/core';
import { Typography } from '@material-ui/core';
import React, { FC } from 'react';
const HomePage: FC<{}> = () => {
return (
<InfoCard title="Home Page">
<Typography variant="body1">Welcome to Backstage!</Typography>
<div>
<Link to="/login">Go to Login</Link>
<EntityLink kind="service" id="backstage-backend">
Backstage Backend
</EntityLink>
@@ -4,7 +4,8 @@ import LoginComponent from './LoginComponent';
describe('LoginComponent', () => {
it('should render', () => {
const rendered = render(<LoginComponent />);
const onLogin = jest.fn();
const rendered = render(<LoginComponent onLogin={onLogin} />);
expect(rendered.getByText('Login')).toBeInTheDocument();
});
});
@@ -1,11 +1,36 @@
import React, { FC, Fragment } from 'react';
import React, { FC, useState } from 'react';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Grid from '@material-ui/core/Grid';
import { Typography } from '@material-ui/core';
type Props = {
onLogin: (username: string) => Promise<void> | void;
};
const LoginComponent: FC<Props> = ({ onLogin }) => {
const [error, setError] = useState('');
const [username, setUsername] = useState('');
const onUsernameChanged = async (e: React.ChangeEvent<HTMLInputElement>) => {
setUsername(e.target.value);
};
const onSubmit = async () => {
if (!username) {
setError('You have to supply a username');
}
setError('');
try {
await onLogin(username);
} catch (e) {
setError(`Login failed: ${e.message}`);
}
};
const LoginComponent: FC<{}> = () => {
return (
<Fragment>
<form onSubmit={onSubmit} autoComplete="off">
<Grid container spacing={8} alignItems="flex-end">
<Grid item md={true} sm={true} xs={true}>
<TextField
@@ -14,6 +39,8 @@ const LoginComponent: FC<{}> = () => {
type="email"
autoFocus
required
value={username}
onChange={onUsernameChanged}
/>
</Grid>
</Grid>
@@ -23,14 +50,17 @@ const LoginComponent: FC<{}> = () => {
style={{ marginTop: '24px', marginBottom: '24px' }}
>
<Button
type="submit"
variant="contained"
color="primary"
style={{ textTransform: 'none' }}
onClick={onSubmit}
disabled={!username}
>
Login
</Button>
</Grid>
</Fragment>
<Typography>{error || 'Just enter any fake username'}</Typography>
</form>
);
};
+8
View File
@@ -0,0 +1,8 @@
{
"private": true,
"name": "@backstage/protobuf-definitions",
"version": "0.0.0",
"devDependencies": {
"ts-protoc-gen": "^0.12.0"
}
}
@@ -0,0 +1,46 @@
import * as grpcWeb from 'grpc-web';
import {
GetBuildReply,
GetBuildRequest,
ListBuildsReply,
ListBuildsRequest} from './builds_pb';
export class BuildsClient {
constructor (hostname: string,
credentials?: null | { [index: string]: string; },
options?: null | { [index: string]: string; });
listBuilds(
request: ListBuildsRequest,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.Error,
response: ListBuildsReply) => void
): grpcWeb.ClientReadableStream<ListBuildsReply>;
getBuild(
request: GetBuildRequest,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.Error,
response: GetBuildReply) => void
): grpcWeb.ClientReadableStream<GetBuildReply>;
}
export class BuildsPromiseClient {
constructor (hostname: string,
credentials?: null | { [index: string]: string; },
options?: null | { [index: string]: string; });
listBuilds(
request: ListBuildsRequest,
metadata?: grpcWeb.Metadata
): Promise<ListBuildsReply>;
getBuild(
request: GetBuildRequest,
metadata?: grpcWeb.Metadata
): Promise<GetBuildReply>;
}
@@ -0,0 +1,233 @@
/**
* @fileoverview gRPC-Web generated client stub for spotify.backstage.builds.v1
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
const grpc = {};
grpc.web = require('grpc-web');
const proto = {};
proto.spotify = {};
proto.spotify.backstage = {};
proto.spotify.backstage.builds = {};
proto.spotify.backstage.builds.v1 = require('./builds_pb.js');
/**
* @param {string} hostname
* @param {?Object} credentials
* @param {?Object} options
* @constructor
* @struct
* @final
*/
proto.spotify.backstage.builds.v1.BuildsClient =
function(hostname, credentials, options) {
if (!options) options = {};
options['format'] = 'text';
/**
* @private @const {!grpc.web.GrpcWebClientBase} The client
*/
this.client_ = new grpc.web.GrpcWebClientBase(options);
/**
* @private @const {string} The hostname
*/
this.hostname_ = hostname;
};
/**
* @param {string} hostname
* @param {?Object} credentials
* @param {?Object} options
* @constructor
* @struct
* @final
*/
proto.spotify.backstage.builds.v1.BuildsPromiseClient =
function(hostname, credentials, options) {
if (!options) options = {};
options['format'] = 'text';
/**
* @private @const {!grpc.web.GrpcWebClientBase} The client
*/
this.client_ = new grpc.web.GrpcWebClientBase(options);
/**
* @private @const {string} The hostname
*/
this.hostname_ = hostname;
};
/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.spotify.backstage.builds.v1.ListBuildsRequest,
* !proto.spotify.backstage.builds.v1.ListBuildsReply>}
*/
const methodDescriptor_Builds_ListBuilds = new grpc.web.MethodDescriptor(
'/spotify.backstage.builds.v1.Builds/ListBuilds',
grpc.web.MethodType.UNARY,
proto.spotify.backstage.builds.v1.ListBuildsRequest,
proto.spotify.backstage.builds.v1.ListBuildsReply,
/**
* @param {!proto.spotify.backstage.builds.v1.ListBuildsRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.builds.v1.ListBuildsReply.deserializeBinary
);
/**
* @const
* @type {!grpc.web.AbstractClientBase.MethodInfo<
* !proto.spotify.backstage.builds.v1.ListBuildsRequest,
* !proto.spotify.backstage.builds.v1.ListBuildsReply>}
*/
const methodInfo_Builds_ListBuilds = new grpc.web.AbstractClientBase.MethodInfo(
proto.spotify.backstage.builds.v1.ListBuildsReply,
/**
* @param {!proto.spotify.backstage.builds.v1.ListBuildsRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.builds.v1.ListBuildsReply.deserializeBinary
);
/**
* @param {!proto.spotify.backstage.builds.v1.ListBuildsRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.Error, ?proto.spotify.backstage.builds.v1.ListBuildsReply)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.spotify.backstage.builds.v1.ListBuildsReply>|undefined}
* The XHR Node Readable Stream
*/
proto.spotify.backstage.builds.v1.BuildsClient.prototype.listBuilds =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/spotify.backstage.builds.v1.Builds/ListBuilds',
request,
metadata || {},
methodDescriptor_Builds_ListBuilds,
callback);
};
/**
* @param {!proto.spotify.backstage.builds.v1.ListBuildsRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @return {!Promise<!proto.spotify.backstage.builds.v1.ListBuildsReply>}
* A native promise that resolves to the response
*/
proto.spotify.backstage.builds.v1.BuildsPromiseClient.prototype.listBuilds =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/spotify.backstage.builds.v1.Builds/ListBuilds',
request,
metadata || {},
methodDescriptor_Builds_ListBuilds);
};
/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.spotify.backstage.builds.v1.GetBuildRequest,
* !proto.spotify.backstage.builds.v1.GetBuildReply>}
*/
const methodDescriptor_Builds_GetBuild = new grpc.web.MethodDescriptor(
'/spotify.backstage.builds.v1.Builds/GetBuild',
grpc.web.MethodType.UNARY,
proto.spotify.backstage.builds.v1.GetBuildRequest,
proto.spotify.backstage.builds.v1.GetBuildReply,
/**
* @param {!proto.spotify.backstage.builds.v1.GetBuildRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.builds.v1.GetBuildReply.deserializeBinary
);
/**
* @const
* @type {!grpc.web.AbstractClientBase.MethodInfo<
* !proto.spotify.backstage.builds.v1.GetBuildRequest,
* !proto.spotify.backstage.builds.v1.GetBuildReply>}
*/
const methodInfo_Builds_GetBuild = new grpc.web.AbstractClientBase.MethodInfo(
proto.spotify.backstage.builds.v1.GetBuildReply,
/**
* @param {!proto.spotify.backstage.builds.v1.GetBuildRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.builds.v1.GetBuildReply.deserializeBinary
);
/**
* @param {!proto.spotify.backstage.builds.v1.GetBuildRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.Error, ?proto.spotify.backstage.builds.v1.GetBuildReply)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.spotify.backstage.builds.v1.GetBuildReply>|undefined}
* The XHR Node Readable Stream
*/
proto.spotify.backstage.builds.v1.BuildsClient.prototype.getBuild =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/spotify.backstage.builds.v1.Builds/GetBuild',
request,
metadata || {},
methodDescriptor_Builds_GetBuild,
callback);
};
/**
* @param {!proto.spotify.backstage.builds.v1.GetBuildRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @return {!Promise<!proto.spotify.backstage.builds.v1.GetBuildReply>}
* A native promise that resolves to the response
*/
proto.spotify.backstage.builds.v1.BuildsPromiseClient.prototype.getBuild =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/spotify.backstage.builds.v1.Builds/GetBuild',
request,
metadata || {},
methodDescriptor_Builds_GetBuild);
};
module.exports = proto.spotify.backstage.builds.v1;
@@ -0,0 +1,151 @@
import * as jspb from "google-protobuf"
export class ListBuildsRequest extends jspb.Message {
getEntityUri(): string;
setEntityUri(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): ListBuildsRequest.AsObject;
static toObject(includeInstance: boolean, msg: ListBuildsRequest): ListBuildsRequest.AsObject;
static serializeBinaryToWriter(message: ListBuildsRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): ListBuildsRequest;
static deserializeBinaryFromReader(message: ListBuildsRequest, reader: jspb.BinaryReader): ListBuildsRequest;
}
export namespace ListBuildsRequest {
export type AsObject = {
entityUri: string,
}
}
export class ListBuildsReply extends jspb.Message {
getEntityUri(): string;
setEntityUri(value: string): void;
getBuildsList(): Array<Build>;
setBuildsList(value: Array<Build>): void;
clearBuildsList(): void;
addBuilds(value?: Build, index?: number): Build;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): ListBuildsReply.AsObject;
static toObject(includeInstance: boolean, msg: ListBuildsReply): ListBuildsReply.AsObject;
static serializeBinaryToWriter(message: ListBuildsReply, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): ListBuildsReply;
static deserializeBinaryFromReader(message: ListBuildsReply, reader: jspb.BinaryReader): ListBuildsReply;
}
export namespace ListBuildsReply {
export type AsObject = {
entityUri: string,
buildsList: Array<Build.AsObject>,
}
}
export class GetBuildRequest extends jspb.Message {
getBuildUri(): string;
setBuildUri(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetBuildRequest.AsObject;
static toObject(includeInstance: boolean, msg: GetBuildRequest): GetBuildRequest.AsObject;
static serializeBinaryToWriter(message: GetBuildRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetBuildRequest;
static deserializeBinaryFromReader(message: GetBuildRequest, reader: jspb.BinaryReader): GetBuildRequest;
}
export namespace GetBuildRequest {
export type AsObject = {
buildUri: string,
}
}
export class GetBuildReply extends jspb.Message {
getBuild(): Build | undefined;
setBuild(value?: Build): void;
hasBuild(): boolean;
clearBuild(): void;
getDetails(): BuildDetails | undefined;
setDetails(value?: BuildDetails): void;
hasDetails(): boolean;
clearDetails(): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetBuildReply.AsObject;
static toObject(includeInstance: boolean, msg: GetBuildReply): GetBuildReply.AsObject;
static serializeBinaryToWriter(message: GetBuildReply, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetBuildReply;
static deserializeBinaryFromReader(message: GetBuildReply, reader: jspb.BinaryReader): GetBuildReply;
}
export namespace GetBuildReply {
export type AsObject = {
build?: Build.AsObject,
details?: BuildDetails.AsObject,
}
}
export class Build extends jspb.Message {
getUri(): string;
setUri(value: string): void;
getCommitId(): string;
setCommitId(value: string): void;
getMessage(): string;
setMessage(value: string): void;
getStatus(): BuildStatus;
setStatus(value: BuildStatus): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Build.AsObject;
static toObject(includeInstance: boolean, msg: Build): Build.AsObject;
static serializeBinaryToWriter(message: Build, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): Build;
static deserializeBinaryFromReader(message: Build, reader: jspb.BinaryReader): Build;
}
export namespace Build {
export type AsObject = {
uri: string,
commitId: string,
message: string,
status: BuildStatus,
}
}
export class BuildDetails extends jspb.Message {
getAuthor(): string;
setAuthor(value: string): void;
getOverviewUrl(): string;
setOverviewUrl(value: string): void;
getLogUrl(): string;
setLogUrl(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): BuildDetails.AsObject;
static toObject(includeInstance: boolean, msg: BuildDetails): BuildDetails.AsObject;
static serializeBinaryToWriter(message: BuildDetails, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): BuildDetails;
static deserializeBinaryFromReader(message: BuildDetails, reader: jspb.BinaryReader): BuildDetails;
}
export namespace BuildDetails {
export type AsObject = {
author: string,
overviewUrl: string,
logUrl: string,
}
}
export enum BuildStatus {
NULL = 0,
SUCCESS = 1,
FAILURE = 2,
PENDING = 3,
RUNNING = 4,
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,46 @@
import * as grpcWeb from 'grpc-web';
import {
GetGroupReply,
GetGroupRequest,
GetUserReply,
GetUserRequest} from './identity_pb';
export class IdentityClient {
constructor (hostname: string,
credentials?: null | { [index: string]: string; },
options?: null | { [index: string]: string; });
getUser(
request: GetUserRequest,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.Error,
response: GetUserReply) => void
): grpcWeb.ClientReadableStream<GetUserReply>;
getGroup(
request: GetGroupRequest,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.Error,
response: GetGroupReply) => void
): grpcWeb.ClientReadableStream<GetGroupReply>;
}
export class IdentityPromiseClient {
constructor (hostname: string,
credentials?: null | { [index: string]: string; },
options?: null | { [index: string]: string; });
getUser(
request: GetUserRequest,
metadata?: grpcWeb.Metadata
): Promise<GetUserReply>;
getGroup(
request: GetGroupRequest,
metadata?: grpcWeb.Metadata
): Promise<GetGroupReply>;
}
@@ -0,0 +1,233 @@
/**
* @fileoverview gRPC-Web generated client stub for spotify.backstage.identity.v1
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
const grpc = {};
grpc.web = require('grpc-web');
const proto = {};
proto.spotify = {};
proto.spotify.backstage = {};
proto.spotify.backstage.identity = {};
proto.spotify.backstage.identity.v1 = require('./identity_pb.js');
/**
* @param {string} hostname
* @param {?Object} credentials
* @param {?Object} options
* @constructor
* @struct
* @final
*/
proto.spotify.backstage.identity.v1.IdentityClient =
function(hostname, credentials, options) {
if (!options) options = {};
options['format'] = 'text';
/**
* @private @const {!grpc.web.GrpcWebClientBase} The client
*/
this.client_ = new grpc.web.GrpcWebClientBase(options);
/**
* @private @const {string} The hostname
*/
this.hostname_ = hostname;
};
/**
* @param {string} hostname
* @param {?Object} credentials
* @param {?Object} options
* @constructor
* @struct
* @final
*/
proto.spotify.backstage.identity.v1.IdentityPromiseClient =
function(hostname, credentials, options) {
if (!options) options = {};
options['format'] = 'text';
/**
* @private @const {!grpc.web.GrpcWebClientBase} The client
*/
this.client_ = new grpc.web.GrpcWebClientBase(options);
/**
* @private @const {string} The hostname
*/
this.hostname_ = hostname;
};
/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.spotify.backstage.identity.v1.GetUserRequest,
* !proto.spotify.backstage.identity.v1.GetUserReply>}
*/
const methodDescriptor_Identity_GetUser = new grpc.web.MethodDescriptor(
'/spotify.backstage.identity.v1.Identity/GetUser',
grpc.web.MethodType.UNARY,
proto.spotify.backstage.identity.v1.GetUserRequest,
proto.spotify.backstage.identity.v1.GetUserReply,
/**
* @param {!proto.spotify.backstage.identity.v1.GetUserRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.identity.v1.GetUserReply.deserializeBinary
);
/**
* @const
* @type {!grpc.web.AbstractClientBase.MethodInfo<
* !proto.spotify.backstage.identity.v1.GetUserRequest,
* !proto.spotify.backstage.identity.v1.GetUserReply>}
*/
const methodInfo_Identity_GetUser = new grpc.web.AbstractClientBase.MethodInfo(
proto.spotify.backstage.identity.v1.GetUserReply,
/**
* @param {!proto.spotify.backstage.identity.v1.GetUserRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.identity.v1.GetUserReply.deserializeBinary
);
/**
* @param {!proto.spotify.backstage.identity.v1.GetUserRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.Error, ?proto.spotify.backstage.identity.v1.GetUserReply)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.spotify.backstage.identity.v1.GetUserReply>|undefined}
* The XHR Node Readable Stream
*/
proto.spotify.backstage.identity.v1.IdentityClient.prototype.getUser =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/spotify.backstage.identity.v1.Identity/GetUser',
request,
metadata || {},
methodDescriptor_Identity_GetUser,
callback);
};
/**
* @param {!proto.spotify.backstage.identity.v1.GetUserRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @return {!Promise<!proto.spotify.backstage.identity.v1.GetUserReply>}
* A native promise that resolves to the response
*/
proto.spotify.backstage.identity.v1.IdentityPromiseClient.prototype.getUser =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/spotify.backstage.identity.v1.Identity/GetUser',
request,
metadata || {},
methodDescriptor_Identity_GetUser);
};
/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.spotify.backstage.identity.v1.GetGroupRequest,
* !proto.spotify.backstage.identity.v1.GetGroupReply>}
*/
const methodDescriptor_Identity_GetGroup = new grpc.web.MethodDescriptor(
'/spotify.backstage.identity.v1.Identity/GetGroup',
grpc.web.MethodType.UNARY,
proto.spotify.backstage.identity.v1.GetGroupRequest,
proto.spotify.backstage.identity.v1.GetGroupReply,
/**
* @param {!proto.spotify.backstage.identity.v1.GetGroupRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.identity.v1.GetGroupReply.deserializeBinary
);
/**
* @const
* @type {!grpc.web.AbstractClientBase.MethodInfo<
* !proto.spotify.backstage.identity.v1.GetGroupRequest,
* !proto.spotify.backstage.identity.v1.GetGroupReply>}
*/
const methodInfo_Identity_GetGroup = new grpc.web.AbstractClientBase.MethodInfo(
proto.spotify.backstage.identity.v1.GetGroupReply,
/**
* @param {!proto.spotify.backstage.identity.v1.GetGroupRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.identity.v1.GetGroupReply.deserializeBinary
);
/**
* @param {!proto.spotify.backstage.identity.v1.GetGroupRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.Error, ?proto.spotify.backstage.identity.v1.GetGroupReply)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.spotify.backstage.identity.v1.GetGroupReply>|undefined}
* The XHR Node Readable Stream
*/
proto.spotify.backstage.identity.v1.IdentityClient.prototype.getGroup =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/spotify.backstage.identity.v1.Identity/GetGroup',
request,
metadata || {},
methodDescriptor_Identity_GetGroup,
callback);
};
/**
* @param {!proto.spotify.backstage.identity.v1.GetGroupRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @return {!Promise<!proto.spotify.backstage.identity.v1.GetGroupReply>}
* A native promise that resolves to the response
*/
proto.spotify.backstage.identity.v1.IdentityPromiseClient.prototype.getGroup =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/spotify.backstage.identity.v1.Identity/GetGroup',
request,
metadata || {},
methodDescriptor_Identity_GetGroup);
};
module.exports = proto.spotify.backstage.identity.v1;
@@ -0,0 +1,136 @@
import * as jspb from "google-protobuf"
export class GetUserRequest extends jspb.Message {
getId(): string;
setId(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetUserRequest.AsObject;
static toObject(includeInstance: boolean, msg: GetUserRequest): GetUserRequest.AsObject;
static serializeBinaryToWriter(message: GetUserRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetUserRequest;
static deserializeBinaryFromReader(message: GetUserRequest, reader: jspb.BinaryReader): GetUserRequest;
}
export namespace GetUserRequest {
export type AsObject = {
id: string,
}
}
export class GetUserReply extends jspb.Message {
getUser(): User | undefined;
setUser(value?: User): void;
hasUser(): boolean;
clearUser(): void;
getGroupsList(): Array<Group>;
setGroupsList(value: Array<Group>): void;
clearGroupsList(): void;
addGroups(value?: Group, index?: number): Group;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetUserReply.AsObject;
static toObject(includeInstance: boolean, msg: GetUserReply): GetUserReply.AsObject;
static serializeBinaryToWriter(message: GetUserReply, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetUserReply;
static deserializeBinaryFromReader(message: GetUserReply, reader: jspb.BinaryReader): GetUserReply;
}
export namespace GetUserReply {
export type AsObject = {
user?: User.AsObject,
groupsList: Array<Group.AsObject>,
}
}
export class GetGroupRequest extends jspb.Message {
getId(): string;
setId(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetGroupRequest.AsObject;
static toObject(includeInstance: boolean, msg: GetGroupRequest): GetGroupRequest.AsObject;
static serializeBinaryToWriter(message: GetGroupRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetGroupRequest;
static deserializeBinaryFromReader(message: GetGroupRequest, reader: jspb.BinaryReader): GetGroupRequest;
}
export namespace GetGroupRequest {
export type AsObject = {
id: string,
}
}
export class GetGroupReply extends jspb.Message {
getGroup(): Group | undefined;
setGroup(value?: Group): void;
hasGroup(): boolean;
clearGroup(): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetGroupReply.AsObject;
static toObject(includeInstance: boolean, msg: GetGroupReply): GetGroupReply.AsObject;
static serializeBinaryToWriter(message: GetGroupReply, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetGroupReply;
static deserializeBinaryFromReader(message: GetGroupReply, reader: jspb.BinaryReader): GetGroupReply;
}
export namespace GetGroupReply {
export type AsObject = {
group?: Group.AsObject,
}
}
export class User extends jspb.Message {
getId(): string;
setId(value: string): void;
getName(): string;
setName(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): User.AsObject;
static toObject(includeInstance: boolean, msg: User): User.AsObject;
static serializeBinaryToWriter(message: User, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): User;
static deserializeBinaryFromReader(message: User, reader: jspb.BinaryReader): User;
}
export namespace User {
export type AsObject = {
id: string,
name: string,
}
}
export class Group extends jspb.Message {
getId(): string;
setId(value: string): void;
getUsersList(): Array<User>;
setUsersList(value: Array<User>): void;
clearUsersList(): void;
addUsers(value?: User, index?: number): User;
getGroupsList(): Array<Group>;
setGroupsList(value: Array<Group>): void;
clearGroupsList(): void;
addGroups(value?: Group, index?: number): Group;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Group.AsObject;
static toObject(includeInstance: boolean, msg: Group): Group.AsObject;
static serializeBinaryToWriter(message: Group, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): Group;
static deserializeBinaryFromReader(message: Group, reader: jspb.BinaryReader): Group;
}
export namespace Group {
export type AsObject = {
id: string,
usersList: Array<User.AsObject>,
groupsList: Array<Group.AsObject>,
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,46 @@
import * as grpcWeb from 'grpc-web';
import {
CreateEntityReply,
CreateEntityRequest,
GetEntityReply,
GetEntityRequest} from './inventory_pb';
export class InventoryClient {
constructor (hostname: string,
credentials?: null | { [index: string]: string; },
options?: null | { [index: string]: string; });
getEntity(
request: GetEntityRequest,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.Error,
response: GetEntityReply) => void
): grpcWeb.ClientReadableStream<GetEntityReply>;
createEntity(
request: CreateEntityRequest,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.Error,
response: CreateEntityReply) => void
): grpcWeb.ClientReadableStream<CreateEntityReply>;
}
export class InventoryPromiseClient {
constructor (hostname: string,
credentials?: null | { [index: string]: string; },
options?: null | { [index: string]: string; });
getEntity(
request: GetEntityRequest,
metadata?: grpcWeb.Metadata
): Promise<GetEntityReply>;
createEntity(
request: CreateEntityRequest,
metadata?: grpcWeb.Metadata
): Promise<CreateEntityReply>;
}
@@ -0,0 +1,233 @@
/**
* @fileoverview gRPC-Web generated client stub for spotify.backstage.inventory.v1
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
const grpc = {};
grpc.web = require('grpc-web');
const proto = {};
proto.spotify = {};
proto.spotify.backstage = {};
proto.spotify.backstage.inventory = {};
proto.spotify.backstage.inventory.v1 = require('./inventory_pb.js');
/**
* @param {string} hostname
* @param {?Object} credentials
* @param {?Object} options
* @constructor
* @struct
* @final
*/
proto.spotify.backstage.inventory.v1.InventoryClient =
function(hostname, credentials, options) {
if (!options) options = {};
options['format'] = 'text';
/**
* @private @const {!grpc.web.GrpcWebClientBase} The client
*/
this.client_ = new grpc.web.GrpcWebClientBase(options);
/**
* @private @const {string} The hostname
*/
this.hostname_ = hostname;
};
/**
* @param {string} hostname
* @param {?Object} credentials
* @param {?Object} options
* @constructor
* @struct
* @final
*/
proto.spotify.backstage.inventory.v1.InventoryPromiseClient =
function(hostname, credentials, options) {
if (!options) options = {};
options['format'] = 'text';
/**
* @private @const {!grpc.web.GrpcWebClientBase} The client
*/
this.client_ = new grpc.web.GrpcWebClientBase(options);
/**
* @private @const {string} The hostname
*/
this.hostname_ = hostname;
};
/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.spotify.backstage.inventory.v1.GetEntityRequest,
* !proto.spotify.backstage.inventory.v1.GetEntityReply>}
*/
const methodDescriptor_Inventory_GetEntity = new grpc.web.MethodDescriptor(
'/spotify.backstage.inventory.v1.Inventory/GetEntity',
grpc.web.MethodType.UNARY,
proto.spotify.backstage.inventory.v1.GetEntityRequest,
proto.spotify.backstage.inventory.v1.GetEntityReply,
/**
* @param {!proto.spotify.backstage.inventory.v1.GetEntityRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.inventory.v1.GetEntityReply.deserializeBinary
);
/**
* @const
* @type {!grpc.web.AbstractClientBase.MethodInfo<
* !proto.spotify.backstage.inventory.v1.GetEntityRequest,
* !proto.spotify.backstage.inventory.v1.GetEntityReply>}
*/
const methodInfo_Inventory_GetEntity = new grpc.web.AbstractClientBase.MethodInfo(
proto.spotify.backstage.inventory.v1.GetEntityReply,
/**
* @param {!proto.spotify.backstage.inventory.v1.GetEntityRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.inventory.v1.GetEntityReply.deserializeBinary
);
/**
* @param {!proto.spotify.backstage.inventory.v1.GetEntityRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.Error, ?proto.spotify.backstage.inventory.v1.GetEntityReply)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.spotify.backstage.inventory.v1.GetEntityReply>|undefined}
* The XHR Node Readable Stream
*/
proto.spotify.backstage.inventory.v1.InventoryClient.prototype.getEntity =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/spotify.backstage.inventory.v1.Inventory/GetEntity',
request,
metadata || {},
methodDescriptor_Inventory_GetEntity,
callback);
};
/**
* @param {!proto.spotify.backstage.inventory.v1.GetEntityRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @return {!Promise<!proto.spotify.backstage.inventory.v1.GetEntityReply>}
* A native promise that resolves to the response
*/
proto.spotify.backstage.inventory.v1.InventoryPromiseClient.prototype.getEntity =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/spotify.backstage.inventory.v1.Inventory/GetEntity',
request,
metadata || {},
methodDescriptor_Inventory_GetEntity);
};
/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.spotify.backstage.inventory.v1.CreateEntityRequest,
* !proto.spotify.backstage.inventory.v1.CreateEntityReply>}
*/
const methodDescriptor_Inventory_CreateEntity = new grpc.web.MethodDescriptor(
'/spotify.backstage.inventory.v1.Inventory/CreateEntity',
grpc.web.MethodType.UNARY,
proto.spotify.backstage.inventory.v1.CreateEntityRequest,
proto.spotify.backstage.inventory.v1.CreateEntityReply,
/**
* @param {!proto.spotify.backstage.inventory.v1.CreateEntityRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.inventory.v1.CreateEntityReply.deserializeBinary
);
/**
* @const
* @type {!grpc.web.AbstractClientBase.MethodInfo<
* !proto.spotify.backstage.inventory.v1.CreateEntityRequest,
* !proto.spotify.backstage.inventory.v1.CreateEntityReply>}
*/
const methodInfo_Inventory_CreateEntity = new grpc.web.AbstractClientBase.MethodInfo(
proto.spotify.backstage.inventory.v1.CreateEntityReply,
/**
* @param {!proto.spotify.backstage.inventory.v1.CreateEntityRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.inventory.v1.CreateEntityReply.deserializeBinary
);
/**
* @param {!proto.spotify.backstage.inventory.v1.CreateEntityRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.Error, ?proto.spotify.backstage.inventory.v1.CreateEntityReply)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.spotify.backstage.inventory.v1.CreateEntityReply>|undefined}
* The XHR Node Readable Stream
*/
proto.spotify.backstage.inventory.v1.InventoryClient.prototype.createEntity =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/spotify.backstage.inventory.v1.Inventory/CreateEntity',
request,
metadata || {},
methodDescriptor_Inventory_CreateEntity,
callback);
};
/**
* @param {!proto.spotify.backstage.inventory.v1.CreateEntityRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @return {!Promise<!proto.spotify.backstage.inventory.v1.CreateEntityReply>}
* A native promise that resolves to the response
*/
proto.spotify.backstage.inventory.v1.InventoryPromiseClient.prototype.createEntity =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/spotify.backstage.inventory.v1.Inventory/CreateEntity',
request,
metadata || {},
methodDescriptor_Inventory_CreateEntity);
};
module.exports = proto.spotify.backstage.inventory.v1;
@@ -0,0 +1,182 @@
import * as jspb from "google-protobuf"
export class GetEntityRequest extends jspb.Message {
getEntity(): Entity | undefined;
setEntity(value?: Entity): void;
hasEntity(): boolean;
clearEntity(): void;
getIncludeFactsList(): Array<string>;
setIncludeFactsList(value: Array<string>): void;
clearIncludeFactsList(): void;
addIncludeFacts(value: string, index?: number): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetEntityRequest.AsObject;
static toObject(includeInstance: boolean, msg: GetEntityRequest): GetEntityRequest.AsObject;
static serializeBinaryToWriter(message: GetEntityRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetEntityRequest;
static deserializeBinaryFromReader(message: GetEntityRequest, reader: jspb.BinaryReader): GetEntityRequest;
}
export namespace GetEntityRequest {
export type AsObject = {
entity?: Entity.AsObject,
includeFactsList: Array<string>,
}
}
export class GetEntityReply extends jspb.Message {
getEntity(): Entity | undefined;
setEntity(value?: Entity): void;
hasEntity(): boolean;
clearEntity(): void;
getFactsList(): Array<Fact>;
setFactsList(value: Array<Fact>): void;
clearFactsList(): void;
addFacts(value?: Fact, index?: number): Fact;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetEntityReply.AsObject;
static toObject(includeInstance: boolean, msg: GetEntityReply): GetEntityReply.AsObject;
static serializeBinaryToWriter(message: GetEntityReply, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetEntityReply;
static deserializeBinaryFromReader(message: GetEntityReply, reader: jspb.BinaryReader): GetEntityReply;
}
export namespace GetEntityReply {
export type AsObject = {
entity?: Entity.AsObject,
factsList: Array<Fact.AsObject>,
}
}
export class CreateEntityRequest extends jspb.Message {
getEntity(): Entity | undefined;
setEntity(value?: Entity): void;
hasEntity(): boolean;
clearEntity(): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): CreateEntityRequest.AsObject;
static toObject(includeInstance: boolean, msg: CreateEntityRequest): CreateEntityRequest.AsObject;
static serializeBinaryToWriter(message: CreateEntityRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): CreateEntityRequest;
static deserializeBinaryFromReader(message: CreateEntityRequest, reader: jspb.BinaryReader): CreateEntityRequest;
}
export namespace CreateEntityRequest {
export type AsObject = {
entity?: Entity.AsObject,
}
}
export class CreateEntityReply extends jspb.Message {
getEntity(): Entity | undefined;
setEntity(value?: Entity): void;
hasEntity(): boolean;
clearEntity(): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): CreateEntityReply.AsObject;
static toObject(includeInstance: boolean, msg: CreateEntityReply): CreateEntityReply.AsObject;
static serializeBinaryToWriter(message: CreateEntityReply, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): CreateEntityReply;
static deserializeBinaryFromReader(message: CreateEntityReply, reader: jspb.BinaryReader): CreateEntityReply;
}
export namespace CreateEntityReply {
export type AsObject = {
entity?: Entity.AsObject,
}
}
export class SetFactRequest extends jspb.Message {
getEntityuri(): string;
setEntityuri(value: string): void;
getName(): string;
setName(value: string): void;
getValue(): string;
setValue(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): SetFactRequest.AsObject;
static toObject(includeInstance: boolean, msg: SetFactRequest): SetFactRequest.AsObject;
static serializeBinaryToWriter(message: SetFactRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): SetFactRequest;
static deserializeBinaryFromReader(message: SetFactRequest, reader: jspb.BinaryReader): SetFactRequest;
}
export namespace SetFactRequest {
export type AsObject = {
entityuri: string,
name: string,
value: string,
}
}
export class SetFactReply extends jspb.Message {
getFacturi(): string;
setFacturi(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): SetFactReply.AsObject;
static toObject(includeInstance: boolean, msg: SetFactReply): SetFactReply.AsObject;
static serializeBinaryToWriter(message: SetFactReply, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): SetFactReply;
static deserializeBinaryFromReader(message: SetFactReply, reader: jspb.BinaryReader): SetFactReply;
}
export namespace SetFactReply {
export type AsObject = {
facturi: string,
}
}
export class Entity extends jspb.Message {
getUri(): string;
setUri(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Entity.AsObject;
static toObject(includeInstance: boolean, msg: Entity): Entity.AsObject;
static serializeBinaryToWriter(message: Entity, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): Entity;
static deserializeBinaryFromReader(message: Entity, reader: jspb.BinaryReader): Entity;
}
export namespace Entity {
export type AsObject = {
uri: string,
}
}
export class Fact extends jspb.Message {
getEntityuri(): string;
setEntityuri(value: string): void;
getName(): string;
setName(value: string): void;
getValue(): string;
setValue(value: string): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Fact.AsObject;
static toObject(includeInstance: boolean, msg: Fact): Fact.AsObject;
static serializeBinaryToWriter(message: Fact, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): Fact;
static deserializeBinaryFromReader(message: Fact, reader: jspb.BinaryReader): Fact;
}
export namespace Fact {
export type AsObject = {
entityuri: string,
name: string,
value: string,
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,34 @@
import * as grpcWeb from 'grpc-web';
import * as identity_v1_identity_pb from '../../identity/v1/identity_pb';
import {
Empty,
GetAllTemplatesReply} from './scaffolder_pb';
export class ScaffolderClient {
constructor (hostname: string,
credentials?: null | { [index: string]: string; },
options?: null | { [index: string]: string; });
getAllTemplates(
request: Empty,
metadata: grpcWeb.Metadata | undefined,
callback: (err: grpcWeb.Error,
response: GetAllTemplatesReply) => void
): grpcWeb.ClientReadableStream<GetAllTemplatesReply>;
}
export class ScaffolderPromiseClient {
constructor (hostname: string,
credentials?: null | { [index: string]: string; },
options?: null | { [index: string]: string; });
getAllTemplates(
request: Empty,
metadata?: grpcWeb.Metadata
): Promise<GetAllTemplatesReply>;
}
@@ -0,0 +1,155 @@
/**
* @fileoverview gRPC-Web generated client stub for spotify.backstage.scaffolder.v1
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
const grpc = {};
grpc.web = require('grpc-web');
var identity_v1_identity_pb = require('../../identity/v1/identity_pb.js')
const proto = {};
proto.spotify = {};
proto.spotify.backstage = {};
proto.spotify.backstage.scaffolder = {};
proto.spotify.backstage.scaffolder.v1 = require('./scaffolder_pb.js');
/**
* @param {string} hostname
* @param {?Object} credentials
* @param {?Object} options
* @constructor
* @struct
* @final
*/
proto.spotify.backstage.scaffolder.v1.ScaffolderClient =
function(hostname, credentials, options) {
if (!options) options = {};
options['format'] = 'text';
/**
* @private @const {!grpc.web.GrpcWebClientBase} The client
*/
this.client_ = new grpc.web.GrpcWebClientBase(options);
/**
* @private @const {string} The hostname
*/
this.hostname_ = hostname;
};
/**
* @param {string} hostname
* @param {?Object} credentials
* @param {?Object} options
* @constructor
* @struct
* @final
*/
proto.spotify.backstage.scaffolder.v1.ScaffolderPromiseClient =
function(hostname, credentials, options) {
if (!options) options = {};
options['format'] = 'text';
/**
* @private @const {!grpc.web.GrpcWebClientBase} The client
*/
this.client_ = new grpc.web.GrpcWebClientBase(options);
/**
* @private @const {string} The hostname
*/
this.hostname_ = hostname;
};
/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.spotify.backstage.scaffolder.v1.Empty,
* !proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply>}
*/
const methodDescriptor_Scaffolder_GetAllTemplates = new grpc.web.MethodDescriptor(
'/spotify.backstage.scaffolder.v1.Scaffolder/GetAllTemplates',
grpc.web.MethodType.UNARY,
proto.spotify.backstage.scaffolder.v1.Empty,
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply,
/**
* @param {!proto.spotify.backstage.scaffolder.v1.Empty} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.deserializeBinary
);
/**
* @const
* @type {!grpc.web.AbstractClientBase.MethodInfo<
* !proto.spotify.backstage.scaffolder.v1.Empty,
* !proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply>}
*/
const methodInfo_Scaffolder_GetAllTemplates = new grpc.web.AbstractClientBase.MethodInfo(
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply,
/**
* @param {!proto.spotify.backstage.scaffolder.v1.Empty} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.deserializeBinary
);
/**
* @param {!proto.spotify.backstage.scaffolder.v1.Empty} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.Error, ?proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply>|undefined}
* The XHR Node Readable Stream
*/
proto.spotify.backstage.scaffolder.v1.ScaffolderClient.prototype.getAllTemplates =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/spotify.backstage.scaffolder.v1.Scaffolder/GetAllTemplates',
request,
metadata || {},
methodDescriptor_Scaffolder_GetAllTemplates,
callback);
};
/**
* @param {!proto.spotify.backstage.scaffolder.v1.Empty} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @return {!Promise<!proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply>}
* A native promise that resolves to the response
*/
proto.spotify.backstage.scaffolder.v1.ScaffolderPromiseClient.prototype.getAllTemplates =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/spotify.backstage.scaffolder.v1.Scaffolder/GetAllTemplates',
request,
metadata || {},
methodDescriptor_Scaffolder_GetAllTemplates);
};
module.exports = proto.spotify.backstage.scaffolder.v1;
@@ -0,0 +1,70 @@
import * as jspb from "google-protobuf"
import * as identity_v1_identity_pb from '../../identity/v1/identity_pb';
export class Empty extends jspb.Message {
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Empty.AsObject;
static toObject(includeInstance: boolean, msg: Empty): Empty.AsObject;
static serializeBinaryToWriter(message: Empty, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): Empty;
static deserializeBinaryFromReader(message: Empty, reader: jspb.BinaryReader): Empty;
}
export namespace Empty {
export type AsObject = {
}
}
export class GetAllTemplatesReply extends jspb.Message {
getTemplatesList(): Array<Template>;
setTemplatesList(value: Array<Template>): void;
clearTemplatesList(): void;
addTemplates(value?: Template, index?: number): Template;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetAllTemplatesReply.AsObject;
static toObject(includeInstance: boolean, msg: GetAllTemplatesReply): GetAllTemplatesReply.AsObject;
static serializeBinaryToWriter(message: GetAllTemplatesReply, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetAllTemplatesReply;
static deserializeBinaryFromReader(message: GetAllTemplatesReply, reader: jspb.BinaryReader): GetAllTemplatesReply;
}
export namespace GetAllTemplatesReply {
export type AsObject = {
templatesList: Array<Template.AsObject>,
}
}
export class Template extends jspb.Message {
getId(): string;
setId(value: string): void;
getName(): string;
setName(value: string): void;
getDescription(): string;
setDescription(value: string): void;
getUser(): identity_v1_identity_pb.User | undefined;
setUser(value?: identity_v1_identity_pb.User): void;
hasUser(): boolean;
clearUser(): void;
serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): Template.AsObject;
static toObject(includeInstance: boolean, msg: Template): Template.AsObject;
static serializeBinaryToWriter(message: Template, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): Template;
static deserializeBinaryFromReader(message: Template, reader: jspb.BinaryReader): Template;
}
export namespace Template {
export type AsObject = {
id: string,
name: string,
description: string,
user?: identity_v1_identity_pb.User.AsObject,
}
}
@@ -0,0 +1,567 @@
/**
* @fileoverview
* @enhanceable
* @suppress {messageConventions} JS Compiler reports an error if a variable or
* field starts with 'MSG_' and isn't a translatable message.
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();
var identity_v1_identity_pb = require('../../identity/v1/identity_pb.js');
goog.object.extend(proto, identity_v1_identity_pb);
goog.exportSymbol('proto.spotify.backstage.scaffolder.v1.Empty', null, global);
goog.exportSymbol('proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply', null, global);
goog.exportSymbol('proto.spotify.backstage.scaffolder.v1.Template', null, global);
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.spotify.backstage.scaffolder.v1.Empty = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.spotify.backstage.scaffolder.v1.Empty, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.spotify.backstage.scaffolder.v1.Empty.displayName = 'proto.spotify.backstage.scaffolder.v1.Empty';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.repeatedFields_, null);
};
goog.inherits(proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.displayName = 'proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.spotify.backstage.scaffolder.v1.Template = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.spotify.backstage.scaffolder.v1.Template, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.spotify.backstage.scaffolder.v1.Template.displayName = 'proto.spotify.backstage.scaffolder.v1.Template';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.spotify.backstage.scaffolder.v1.Empty.prototype.toObject = function(opt_includeInstance) {
return proto.spotify.backstage.scaffolder.v1.Empty.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.spotify.backstage.scaffolder.v1.Empty} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.spotify.backstage.scaffolder.v1.Empty.toObject = function(includeInstance, msg) {
var f, obj = {
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.spotify.backstage.scaffolder.v1.Empty}
*/
proto.spotify.backstage.scaffolder.v1.Empty.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.spotify.backstage.scaffolder.v1.Empty;
return proto.spotify.backstage.scaffolder.v1.Empty.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.spotify.backstage.scaffolder.v1.Empty} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.spotify.backstage.scaffolder.v1.Empty}
*/
proto.spotify.backstage.scaffolder.v1.Empty.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.spotify.backstage.scaffolder.v1.Empty.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.spotify.backstage.scaffolder.v1.Empty.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.spotify.backstage.scaffolder.v1.Empty} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.spotify.backstage.scaffolder.v1.Empty.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
};
/**
* List of repeated fields within this message type.
* @private {!Array<number>}
* @const
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.repeatedFields_ = [1];
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.prototype.toObject = function(opt_includeInstance) {
return proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.toObject = function(includeInstance, msg) {
var f, obj = {
templatesList: jspb.Message.toObjectList(msg.getTemplatesList(),
proto.spotify.backstage.scaffolder.v1.Template.toObject, includeInstance)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply}
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply;
return proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply}
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = new proto.spotify.backstage.scaffolder.v1.Template;
reader.readMessage(value,proto.spotify.backstage.scaffolder.v1.Template.deserializeBinaryFromReader);
msg.addTemplates(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getTemplatesList();
if (f.length > 0) {
writer.writeRepeatedMessage(
1,
f,
proto.spotify.backstage.scaffolder.v1.Template.serializeBinaryToWriter
);
}
};
/**
* repeated Template templates = 1;
* @return {!Array<!proto.spotify.backstage.scaffolder.v1.Template>}
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.prototype.getTemplatesList = function() {
return /** @type{!Array<!proto.spotify.backstage.scaffolder.v1.Template>} */ (
jspb.Message.getRepeatedWrapperField(this, proto.spotify.backstage.scaffolder.v1.Template, 1));
};
/** @param {!Array<!proto.spotify.backstage.scaffolder.v1.Template>} value */
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.prototype.setTemplatesList = function(value) {
jspb.Message.setRepeatedWrapperField(this, 1, value);
};
/**
* @param {!proto.spotify.backstage.scaffolder.v1.Template=} opt_value
* @param {number=} opt_index
* @return {!proto.spotify.backstage.scaffolder.v1.Template}
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.prototype.addTemplates = function(opt_value, opt_index) {
return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.spotify.backstage.scaffolder.v1.Template, opt_index);
};
/**
* Clears the list making it empty but non-null.
*/
proto.spotify.backstage.scaffolder.v1.GetAllTemplatesReply.prototype.clearTemplatesList = function() {
this.setTemplatesList([]);
};
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.spotify.backstage.scaffolder.v1.Template.prototype.toObject = function(opt_includeInstance) {
return proto.spotify.backstage.scaffolder.v1.Template.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.spotify.backstage.scaffolder.v1.Template} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.spotify.backstage.scaffolder.v1.Template.toObject = function(includeInstance, msg) {
var f, obj = {
id: jspb.Message.getFieldWithDefault(msg, 1, ""),
name: jspb.Message.getFieldWithDefault(msg, 2, ""),
description: jspb.Message.getFieldWithDefault(msg, 3, ""),
user: (f = msg.getUser()) && identity_v1_identity_pb.User.toObject(includeInstance, f)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.spotify.backstage.scaffolder.v1.Template}
*/
proto.spotify.backstage.scaffolder.v1.Template.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.spotify.backstage.scaffolder.v1.Template;
return proto.spotify.backstage.scaffolder.v1.Template.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.spotify.backstage.scaffolder.v1.Template} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.spotify.backstage.scaffolder.v1.Template}
*/
proto.spotify.backstage.scaffolder.v1.Template.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setId(value);
break;
case 2:
var value = /** @type {string} */ (reader.readString());
msg.setName(value);
break;
case 3:
var value = /** @type {string} */ (reader.readString());
msg.setDescription(value);
break;
case 4:
var value = new identity_v1_identity_pb.User;
reader.readMessage(value,identity_v1_identity_pb.User.deserializeBinaryFromReader);
msg.setUser(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.spotify.backstage.scaffolder.v1.Template.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.spotify.backstage.scaffolder.v1.Template.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.spotify.backstage.scaffolder.v1.Template} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.spotify.backstage.scaffolder.v1.Template.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getId();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
f = message.getName();
if (f.length > 0) {
writer.writeString(
2,
f
);
}
f = message.getDescription();
if (f.length > 0) {
writer.writeString(
3,
f
);
}
f = message.getUser();
if (f != null) {
writer.writeMessage(
4,
f,
identity_v1_identity_pb.User.serializeBinaryToWriter
);
}
};
/**
* optional string id = 1;
* @return {string}
*/
proto.spotify.backstage.scaffolder.v1.Template.prototype.getId = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
};
/** @param {string} value */
proto.spotify.backstage.scaffolder.v1.Template.prototype.setId = function(value) {
jspb.Message.setProto3StringField(this, 1, value);
};
/**
* optional string name = 2;
* @return {string}
*/
proto.spotify.backstage.scaffolder.v1.Template.prototype.getName = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
};
/** @param {string} value */
proto.spotify.backstage.scaffolder.v1.Template.prototype.setName = function(value) {
jspb.Message.setProto3StringField(this, 2, value);
};
/**
* optional string description = 3;
* @return {string}
*/
proto.spotify.backstage.scaffolder.v1.Template.prototype.getDescription = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
};
/** @param {string} value */
proto.spotify.backstage.scaffolder.v1.Template.prototype.setDescription = function(value) {
jspb.Message.setProto3StringField(this, 3, value);
};
/**
* optional spotify.backstage.identity.v1.User user = 4;
* @return {?proto.spotify.backstage.identity.v1.User}
*/
proto.spotify.backstage.scaffolder.v1.Template.prototype.getUser = function() {
return /** @type{?proto.spotify.backstage.identity.v1.User} */ (
jspb.Message.getWrapperField(this, identity_v1_identity_pb.User, 4));
};
/** @param {?proto.spotify.backstage.identity.v1.User|undefined} value */
proto.spotify.backstage.scaffolder.v1.Template.prototype.setUser = function(value) {
jspb.Message.setWrapperField(this, 4, value);
};
/**
* Clears the message field making it undefined.
*/
proto.spotify.backstage.scaffolder.v1.Template.prototype.clearUser = function() {
this.setUser(undefined);
};
/**
* Returns whether this field is set.
* @return {boolean}
*/
proto.spotify.backstage.scaffolder.v1.Template.prototype.hasUser = function() {
return jspb.Message.getField(this, 4) != null;
};
goog.object.extend(exports, proto.spotify.backstage.scaffolder.v1);
-8
View File
@@ -1,8 +0,0 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
OUT='src/proto'
mkdir -p "$OUT"
exec protoc -I="$DIR/../../protos" --js_out=import_style=commonjs:"$OUT" --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext:"$OUT" "$@"
+212 -3
View File
@@ -2890,6 +2890,11 @@
jest-diff "^25.1.0"
pretty-format "^25.1.0"
"@types/js-cookie@2.2.4":
version "2.2.4"
resolved "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.4.tgz#f79720b4755aa197c2e15e982e2f438f5748e348"
integrity sha512-WTfSE1Eauak/Nrg6cA9FgPTFvVawejsai6zXoq0QYTQ3mxONeRtGhKxa7wMlUzWWmzrmTeV+rwLjHgsCntdrsA==
"@types/json-schema@^7.0.3":
version "7.0.4"
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
@@ -3013,6 +3018,11 @@
dependencies:
"@types/yargs-parser" "*"
"@types/zen-observable@^0.8.0":
version "0.8.0"
resolved "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d"
integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg==
"@typescript-eslint/eslint-plugin@^2.14.0", "@typescript-eslint/eslint-plugin@^2.8.0":
version "2.18.0"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.18.0.tgz#f8cf272dfb057ecf1ea000fea1e0b3f06a32f9cb"
@@ -3202,6 +3212,11 @@
"@webassemblyjs/wast-parser" "1.8.5"
"@xtuc/long" "4.2.2"
"@xobotyi/scrollbar-width@1.8.2":
version "1.8.2"
resolved "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.8.2.tgz#056946ac41ade4885c576619c8d70c46c77e9683"
integrity sha512-RV6+4hR29oMaPCvSYFUvzOvlsrg2s2k5NE9tNERs+4nFIC9dRXxs+lL2CcaRTbl3yQxKwAZ8Cd+qMI8aUu9TFw==
"@xtuc/ieee754@^1.2.0":
version "1.2.0"
resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@@ -4033,6 +4048,11 @@ bottleneck@^2.18.1:
resolved "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91"
integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==
bowser@^1.7.3:
version "1.9.4"
resolved "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a"
integrity sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==
boxen@^1.2.1:
version "1.3.0"
resolved "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
@@ -5115,6 +5135,13 @@ copy-descriptor@^0.1.0:
resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
copy-to-clipboard@^3.2.0:
version "3.2.1"
resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.2.1.tgz#b1a1137100e5665d5a96015cb579e30e90e07c44"
integrity sha512-btru1Q6RD9wbonIvEU5EfnhIRGHLo//BGXQ1hNAD2avIs/nBZlpbOeKtv3mhoUByN4DB9Cb6/vXBymj1S43KmA==
dependencies:
toggle-selection "^1.0.6"
core-js-compat@^3.6.2:
version "3.6.4"
resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17"
@@ -5300,6 +5327,14 @@ css-has-pseudo@^0.10.0:
postcss "^7.0.6"
postcss-selector-parser "^5.0.0-rc.4"
css-in-js-utils@^2.0.0:
version "2.0.1"
resolved "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz#3b472b398787291b47cfe3e44fecfdd9e914ba99"
integrity sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==
dependencies:
hyphenate-style-name "^1.0.2"
isobject "^3.0.1"
css-loader@3.2.0:
version "3.2.0"
resolved "https://registry.npmjs.org/css-loader/-/css-loader-3.2.0.tgz#bb570d89c194f763627fcf1f80059c6832d009b2"
@@ -5358,6 +5393,14 @@ css-tree@1.0.0-alpha.37:
mdn-data "2.0.4"
source-map "^0.6.1"
css-tree@^1.0.0-alpha.28:
version "1.0.0-alpha.39"
resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb"
integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==
dependencies:
mdn-data "2.0.6"
source-map "^0.6.1"
css-unit-converter@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996"
@@ -5510,7 +5553,7 @@ cssstyle@^2.0.0:
dependencies:
cssom "~0.3.6"
csstype@^2.2.0, csstype@^2.5.2, csstype@^2.6.5, csstype@^2.6.7:
csstype@^2.2.0, csstype@^2.5.2, csstype@^2.5.5, csstype@^2.6.5, csstype@^2.6.7:
version "2.6.8"
resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.8.tgz#0fb6fc2417ffd2816a418c9336da74d7f07db431"
integrity sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA==
@@ -6154,6 +6197,13 @@ error-ex@^1.2.0, error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
error-stack-parser@^2.0.6:
version "2.0.6"
resolved "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8"
integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==
dependencies:
stackframe "^1.1.1"
es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2:
version "1.17.4"
resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184"
@@ -6758,6 +6808,16 @@ fast-levenshtein@~2.0.6:
resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
fast-shallow-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b"
integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==
fastest-stable-stringify@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028"
integrity sha1-kSLUBtTJ2YvqZEpraFPVh0uHsCg=
fastq@^1.6.0:
version "1.6.0"
resolved "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2"
@@ -7517,6 +7577,11 @@ google-protobuf@^3.11.2:
resolved "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.11.2.tgz#43272974521a5cec35a21f62730cf517a5a8e38c"
integrity sha512-T4fin7lcYLUPj2ChUZ4DvfuuHtg3xi1621qeRZt2J7SvOQusOzq+sDT4vbotWTCjUXJoR36CA016LlhtPy80uQ==
google-protobuf@^3.6.1:
version "3.11.3"
resolved "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.11.3.tgz#660977f5de29cc8f647172a170602887102fa677"
integrity sha512-Sp8E+0AJLxmiPwAk9VH3MkYAmYYheNUhywIyXOS7wvRkqbIYcHtGzJzIYicNqYsqgKmY35F9hxRkI+ZTqTB4Tg==
got@^6.7.1:
version "6.7.1"
resolved "https://registry.npmjs.org/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
@@ -7947,7 +8012,7 @@ humanize-ms@^1.2.1:
dependencies:
ms "^2.0.0"
hyphenate-style-name@^1.0.3:
hyphenate-style-name@^1.0.2, hyphenate-style-name@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
@@ -8147,6 +8212,14 @@ init-package-json@^1.10.3:
validate-npm-package-license "^3.0.1"
validate-npm-package-name "^3.0.0"
inline-style-prefixer@^4.0.0:
version "4.0.2"
resolved "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-4.0.2.tgz#d390957d26f281255fe101da863158ac6eb60911"
integrity sha512-N8nVhwfYga9MiV9jWlwfdj1UDIaZlBFu4cJSJkIr7tZX7sHpHhGR5su1qdpW+7KPL8ISTvCIkcaFi/JdBknvPg==
dependencies:
bowser "^1.7.3"
css-in-js-utils "^2.0.0"
inquirer@6.5.0:
version "6.5.0"
resolved "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42"
@@ -9541,6 +9614,11 @@ jest@^25.1.0:
import-local "^3.0.2"
jest-cli "^25.1.0"
js-cookie@^2.2.1:
version "2.2.1"
resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -10588,6 +10666,11 @@ mdn-data@2.0.4:
resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
mdn-data@2.0.6:
version "2.0.6"
resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978"
integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==
meant@~1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d"
@@ -11019,6 +11102,20 @@ nan@^2.12.1:
resolved "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
nano-css@^5.2.1:
version "5.2.1"
resolved "https://registry.npmjs.org/nano-css/-/nano-css-5.2.1.tgz#73b8470fa40b028a134d3393ae36bbb34b9fa332"
integrity sha512-T54okxMAha0+de+W8o3qFtuWhTxYvqQh2ku1cYEqTTP9mR62nWV2lLK9qRuAGWmoaYWhU7K4evT9Lc1iF65wuw==
dependencies:
css-tree "^1.0.0-alpha.28"
csstype "^2.5.5"
fastest-stable-stringify "^1.0.1"
inline-style-prefixer "^4.0.0"
rtl-css-js "^1.9.0"
sourcemap-codec "^1.4.1"
stacktrace-js "^2.0.0"
stylis "3.5.0"
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@@ -13360,7 +13457,7 @@ react-error-overlay@^6.0.5:
resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.5.tgz#55d59c2a3810e8b41922e0b4e5f85dcf239bd533"
integrity sha512-+DMR2k5c6BqMDSMF8hLH0vYKtKTeikiFW+fj0LClN+XZg4N9b8QUAdHC62CGWNLTi/gnuuemNcNcTFrCvK1f+A==
react-fast-compare@^2.0.2:
react-fast-compare@^2.0.2, react-fast-compare@^2.0.4:
version "2.0.4"
resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
@@ -13431,6 +13528,25 @@ react-transition-group@^4.3.0:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-use@^13.24.0:
version "13.24.0"
resolved "https://registry.npmjs.org/react-use/-/react-use-13.24.0.tgz#f4574e26cfaaad65e3f04c0d5ff80c1836546236"
integrity sha512-p8GsZuMdz8OeIGzuYLm6pzJysKOhNyQjCUG6SHrQGk6o6ghy/RVGSqnmxVacNbN9166S0+9FsM1N1yH9GzWlgg==
dependencies:
"@types/js-cookie" "2.2.4"
"@xobotyi/scrollbar-width" "1.8.2"
copy-to-clipboard "^3.2.0"
fast-shallow-equal "^1.0.0"
js-cookie "^2.2.1"
nano-css "^5.2.1"
react-fast-compare "^2.0.4"
resize-observer-polyfill "^1.5.1"
screenfull "^5.0.0"
set-harmonic-interval "^1.0.1"
throttle-debounce "^2.1.0"
ts-easing "^0.2.0"
tslib "^1.10.0"
react@^16.12.0:
version "16.12.0"
resolved "https://registry.npmjs.org/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83"
@@ -13900,6 +14016,11 @@ requires-port@^1.0.0:
resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
resize-observer-polyfill@^1.5.1:
version "1.5.1"
resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
@@ -14087,6 +14208,13 @@ rsvp@^4.8.4:
resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
rtl-css-js@^1.9.0:
version "1.14.0"
resolved "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.14.0.tgz#daa4f192a92509e292a0519f4b255e6e3c076b7d"
integrity sha512-Dl5xDTeN3e7scU1cWX8c9b6/Nqz3u/HgR4gePc1kWXYiQWVQbKCEyK6+Hxve9LbcJ5EieHy1J9nJCN3grTtGwg==
dependencies:
"@babel/runtime" "^7.1.2"
run-async@^2.2.0:
version "2.3.0"
resolved "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
@@ -14203,6 +14331,11 @@ schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.1.0, schema-utils@^2.2
ajv "^6.10.2"
ajv-keywords "^3.4.1"
screenfull@^5.0.0:
version "5.0.1"
resolved "https://registry.npmjs.org/screenfull/-/screenfull-5.0.1.tgz#873052411eb9096bc1c8e615f5badad119e6e42c"
integrity sha512-NgQH4KKh2V3zlj2u90l7TUcSFxr9qL/64QEvhAvCN/fu1YS39YLTBKIqZqiS3STj3QD8sN6XnsK/8jk3hRq4WA==
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@@ -14345,6 +14478,11 @@ set-blocking@^2.0.0, set-blocking@~2.0.0:
resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
set-harmonic-interval@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249"
integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==
set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@@ -14645,6 +14783,11 @@ source-map-url@^0.4.0:
resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
source-map@0.5.6:
version "0.5.6"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
integrity sha1-dc449SvwczxafwwRjYEzSiu19BI=
source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
@@ -14660,6 +14803,11 @@ source-map@^0.7.3:
resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
sourcemap-codec@^1.4.1:
version "1.4.8"
resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
spawn-error-forwarder@~1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz#1afd94738e999b0346d7b9fc373be55e07577029"
@@ -14787,11 +14935,40 @@ stable@^0.1.8:
resolved "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
stack-generator@^2.0.5:
version "2.0.5"
resolved "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.5.tgz#fb00e5b4ee97de603e0773ea78ce944d81596c36"
integrity sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==
dependencies:
stackframe "^1.1.1"
stack-utils@^1.0.1:
version "1.0.2"
resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
stackframe@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/stackframe/-/stackframe-1.1.1.tgz#ffef0a3318b1b60c3b58564989aca5660729ec71"
integrity sha512-0PlYhdKh6AfFxRyK/v+6/k+/mMfyiEBbTM5L94D0ZytQnJ166wuwoTYLHFWGbs2dpA8Rgq763KGWmN1EQEYHRQ==
stacktrace-gps@^3.0.4:
version "3.0.4"
resolved "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz#7688dc2fc09ffb3a13165ebe0dbcaf41bcf0c69a"
integrity sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg==
dependencies:
source-map "0.5.6"
stackframe "^1.1.1"
stacktrace-js@^2.0.0:
version "2.0.2"
resolved "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b"
integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==
dependencies:
error-stack-parser "^2.0.6"
stack-generator "^2.0.5"
stacktrace-gps "^3.0.4"
static-extend@^0.1.1:
version "0.1.2"
resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
@@ -15103,6 +15280,11 @@ stylehacks@^4.0.0:
postcss "^7.0.0"
postcss-selector-parser "^3.0.0"
stylis@3.5.0:
version "3.5.0"
resolved "https://registry.npmjs.org/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1"
integrity sha512-pP7yXN6dwMzAR29Q0mBrabPCe0/mNO1MSr93bhay+hcZondvMMTpeGyd8nbhYJdyperNT2DRxONQuUGcJr5iPw==
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -15331,6 +15513,11 @@ throat@^5.0.0:
resolved "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b"
integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==
throttle-debounce@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5"
integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg==
through2@^2.0.0, through2@^2.0.2, through2@~2.0.0:
version "2.0.5"
resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -15442,6 +15629,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
toggle-selection@^1.0.6:
version "1.0.6"
resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
toidentifier@1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
@@ -15499,6 +15691,11 @@ trim-off-newlines@^1.0.0:
resolved "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3"
integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM=
ts-easing@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec"
integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==
ts-jest@^25.0.0:
version "25.1.0"
resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-25.1.0.tgz#06e776c4cce8a4da8eec4945f36a5823d0c0f9ba"
@@ -15520,6 +15717,13 @@ ts-pnp@1.1.5, ts-pnp@^1.1.2:
resolved "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.5.tgz#840e0739c89fce5f3abd9037bb091dbff16d9dec"
integrity sha512-ti7OGMOUOzo66wLF3liskw6YQIaSsBgc4GOAlWRnIEj8htCxJUxskanMUoJOD6MDCRAXo36goXJZch+nOS0VMA==
ts-protoc-gen@^0.12.0:
version "0.12.0"
resolved "https://registry.npmjs.org/ts-protoc-gen/-/ts-protoc-gen-0.12.0.tgz#932e5738f14b67e7202825b06f8c548cb7d8ef34"
integrity sha512-V7jnICJxKqalBrnJSMTW5tB9sGi48gOC325bfcM7TDNUItVOlaMM//rQmuo49ybipk/SyJTnWXgtJnhHCevNJw==
dependencies:
google-protobuf "^3.6.1"
tslib@^1.8.1, tslib@^1.9.0:
version "1.10.0"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
@@ -16691,3 +16895,8 @@ yargs@^8.0.2:
which-module "^2.0.0"
y18n "^3.2.1"
yargs-parser "^7.0.0"
zen-observable@^0.8.15:
version "0.8.15"
resolved "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
+1892
View File
File diff suppressed because it is too large Load Diff
+54 -10
View File
@@ -4,32 +4,51 @@ Collection of all Backstage protobuf definitions.
## Usage
Managed with prototool, install instructions at https://github.com/uber/prototool/blob/dev/docs/install.md
Managed with [Prototool](https://github.com/uber/prototool), install instructions at <https://github.com/uber/prototool/blob/dev/docs/install.md>
## Install Dependencies
You will need to have `protoc-gen-go` available in your path. You can find out more information here: https://github.com/golang/protobuf
### Prototool
```bash
$ brew install prototool
```
```sh
### protoc-gen-go
This will enable code generation in Go for interacting with gRPC-Web. You will need to have `protoc-gen-go` available in your path. You can find out more information here: https://github.com/golang/protobuf
```bash
$ go get -u github.com/golang/protobuf/protoc-gen-go
$ protoc-gen-go # should now be available in your path providing you GOPATH + GOBIN paths are setup correctly.
```
### protoc-gen-grpc-web
### Generate code
This will enable code generation for interacting with gRPC-Web.
Run to generate code to `backend/proto/`:
Installation instructions are found at https://github.com/grpc/grpc-web#code-generator-plugin
```
$ prototool generate
## Generating Code
To generate the Protobuf definitions in Go and TypeScript, run the following command from the root with [Prototool](https://github.com/uber/prototool):
```bash
$ prototool generate ./proto
```
Generated code should be check in to the repo.
This will generate the respective "generated" files in the following folders:
### Import generated go code
- `backend/proto`
- `frontend/packages/proto/src/generated`
Example import of inventory:
All generated code related to Protocol Buffers should be checked in to the repository.
## Code Examples
### Import using Go
This is what you'll need to use for development in any of the `backend` services.
```go
package spotify.backstage.identity.v1;
@@ -38,3 +57,28 @@ func main() {
identityv1.NewInventoryClient(nil)
}
```
### Import using TypeScript
This is what you'll need to use for development in any of the `frontend` services.
Firstly, ensure this line is in your `package.json` within the `frontend/` folder:
```js
"dependencies": {
"@backstage/protobuf-definitions": "0.0.0",
...
}
```
Next, you can use them in your [Yarn Workspaces](https://yarnpkg.com/en/docs/workspaces/) package using the following:
```ts
import { IdentityClient } from '@backstage/protocol-definitions/generated/identity/v1/identity_pb_service';
const client = new IdentityClient('http://localhost:8080');
// const req = new GetUserRequest();
// req.setUsername("johndoe");
// client.getUser(req, (err, user) => {
// /* ... */
// });
```
+49
View File
@@ -0,0 +1,49 @@
syntax = "proto3";
package spotify.backstage.builds.v1;
option go_package = "buildsv1";
service Builds {
rpc ListBuilds(ListBuildsRequest) returns (ListBuildsReply);
rpc GetBuild(GetBuildRequest) returns (GetBuildReply);
}
message ListBuildsRequest {
string entity_uri = 1;
}
message ListBuildsReply {
string entity_uri = 1;
repeated Build builds = 2;
}
message GetBuildRequest {
string build_uri = 1;
}
message GetBuildReply {
Build build = 1;
BuildDetails details = 2;
}
message Build {
string uri = 1;
string commit_id = 2;
string message = 3;
BuildStatus status = 4;
}
message BuildDetails {
string author = 1;
string overview_url = 2;
string log_url = 3;
}
enum BuildStatus {
NULL = 0;
SUCCESS = 1;
FAILURE = 2;
PENDING = 3;
RUNNING = 4;
}
+22 -1
View File
@@ -7,6 +7,8 @@ option go_package = "inventoryv1";
service Inventory {
rpc GetEntity(GetEntityRequest) returns (GetEntityReply);
rpc CreateEntity(CreateEntityRequest) returns (CreateEntityReply);
rpc SetFact(SetFactRequest) returns (SetFactReply);
rpc GetFact(GetFactRequest) returns (GetFactReply);
}
message GetEntityRequest {
@@ -27,6 +29,25 @@ message CreateEntityReply {
Entity entity = 1;
}
message SetFactRequest {
string entityUri = 1;
string name = 2;
string value = 3;
}
message SetFactReply {
Fact fact = 1;
}
message GetFactRequest {
string entityUri = 1;
string name = 2;
}
message GetFactReply {
Fact fact = 1;
}
message Entity {
string uri = 1;
}
@@ -34,4 +55,4 @@ message Entity {
message Fact {
string name = 1;
string value = 2;
}
}
+6 -1
View File
@@ -1,4 +1,3 @@
protoc:
version: 3.8.0
lint:
@@ -16,3 +15,9 @@ generate:
type: go
flags: plugins=grpc
output: ../backend/proto
- name: js
flags: import_style=commonjs
output: ../frontend/packages/proto/src/generated
- name: grpc-web
flags: import_style=commonjs+dts,mode=grpcwebtext
output: ../frontend/packages/proto/src/generated