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:
@@ -0,0 +1 @@
|
||||
secrets.env
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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=
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
protoc -I ../../ protos/inventory.proto --go_out=plugins=grpc:.
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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!');
|
||||
});
|
||||
});
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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' };
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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';
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
+20
@@ -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';
|
||||
+8
@@ -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';
|
||||
+46
@@ -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>
|
||||
|
||||
+2
-1
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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
+46
@@ -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
+34
@@ -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);
|
||||
@@ -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
@@ -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==
|
||||
|
||||
Generated
+1892
File diff suppressed because it is too large
Load Diff
+54
-10
@@ -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) => {
|
||||
// /* ... */
|
||||
// });
|
||||
```
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user