[In Progress] init layout #2
23
.gitignore
vendored
23
.gitignore
vendored
@ -1,7 +1,6 @@
|
|||||||
# ---> Go
|
# Mac OS X files
|
||||||
# If you prefer the allow list template instead of the deny list, see community template:
|
*.DS_Store
|
||||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
|
||||||
#
|
|
||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
*.exe
|
*.exe
|
||||||
*.exe~
|
*.exe~
|
||||||
@ -9,16 +8,22 @@
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, build with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||||
# vendor/
|
.glide/
|
||||||
|
|
||||||
# Go workspace file
|
# Dependency directories
|
||||||
go.work
|
vendor/
|
||||||
|
|
||||||
|
bin/
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
.env
|
||||||
|
tmp/
|
||||||
|
|
||||||
/pkgdash
|
/pkgdash
|
||||||
|
23
cmd/rest/server.go
Normal file
23
cmd/rest/server.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.unistack.org/micro/v4/logger"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
svc, err := service.NewService(ctx)
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatalf(ctx, "failed to create service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// start server
|
||||||
|
if err = svc.Run(); err != nil {
|
||||||
|
logger.Fatal(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
config/config.go
Normal file
24
config/config.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import service "go.unistack.org/cms-service"
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
Address string `flag:"name=pkgdash.address,desc='listen address',default='127.0.0.1:8080'"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
App *App
|
||||||
|
Storage *service.ConfigStorage
|
||||||
|
Logger *service.ConfigLogger
|
||||||
|
Service *service.ConfigService
|
||||||
|
Core *service.ConfigCore
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig() *Config {
|
||||||
|
return &Config{
|
||||||
|
Service: &service.ConfigService{
|
||||||
|
Name: ServiceName,
|
||||||
|
Version: ServiceVersion,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
6
config/variables.go
Normal file
6
config/variables.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
var (
|
||||||
|
ServiceName = "pkgdash"
|
||||||
|
ServiceVersion = "0.0.1"
|
||||||
|
)
|
24
entities.go
24
entities.go
@ -1,24 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
type DBPackage struct {
|
|
||||||
Name string `db:"name"` // service name, last component path
|
|
||||||
URL string `db:"url"` // scm url
|
|
||||||
Modules []int64 `db:"modules"` // parsed go.mod modules
|
|
||||||
ID int64 `db:"id"` // package id
|
|
||||||
Issues []int64 `db:"issues"` // issues list
|
|
||||||
}
|
|
||||||
|
|
||||||
type DBModule struct {
|
|
||||||
Name string `db:"name"` // module name
|
|
||||||
Version string `db:"version"` // module
|
|
||||||
ID int64 `db:"id"`
|
|
||||||
Package int64 `db:"package"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DBIssue struct {
|
|
||||||
ID int64 `db:"id"`
|
|
||||||
Package int64 `db:"package"`
|
|
||||||
Modules []int64 `db:"modules"`
|
|
||||||
Status int64 `db:"status"`
|
|
||||||
Desc string `db:"desc"`
|
|
||||||
}
|
|
68
go.mod
68
go.mod
@ -3,10 +3,24 @@ module go.unistack.org/unistack-org/pkgdash
|
|||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v1.0.2
|
||||||
github.com/go-git/go-git/v5 v5.8.1
|
github.com/go-git/go-git/v5 v5.8.1
|
||||||
go.unistack.org/micro-codec-yaml/v4 v4.0.0
|
github.com/golang-migrate/migrate/v4 v4.15.1
|
||||||
go.unistack.org/micro-config-flag/v4 v4.0.2
|
github.com/google/uuid v1.3.0
|
||||||
go.unistack.org/micro/v4 v4.0.5
|
github.com/jackc/pgtype v1.14.0
|
||||||
|
github.com/pkg/errors v0.9.1
|
||||||
|
go.unistack.org/cms-service v0.0.1
|
||||||
|
go.unistack.org/micro-client-http/v3 v3.9.3
|
||||||
|
go.unistack.org/micro-config-flag/v4 v4.0.1
|
||||||
|
go.unistack.org/micro-proto/v3 v3.3.1
|
||||||
|
go.unistack.org/micro-server-grpc/v3 v3.10.6
|
||||||
|
go.unistack.org/micro-server-http/v3 v3.11.6
|
||||||
|
go.unistack.org/micro/v3 v3.10.24
|
||||||
|
go.unistack.org/micro/v4 v4.0.1
|
||||||
|
golang.org/x/mod v0.12.0
|
||||||
|
golang.org/x/net v0.12.0
|
||||||
|
golang.org/x/sync v0.3.0
|
||||||
|
google.golang.org/protobuf v1.31.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -15,26 +29,64 @@ require (
|
|||||||
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
|
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
|
||||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||||
github.com/cloudflare/circl v1.3.3 // indirect
|
github.com/cloudflare/circl v1.3.3 // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.4.1 // indirect
|
github.com/go-git/go-billy/v5 v5.4.1 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/iancoleman/strcase v0.2.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.16 // indirect
|
github.com/imdario/mergo v0.3.16 // indirect
|
||||||
|
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||||
|
github.com/jackc/pgconn v1.14.0 // indirect
|
||||||
|
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa // indirect
|
||||||
|
github.com/jackc/pgio v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
github.com/jackc/pgx/v4 v4.18.1 // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.3.1 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||||
|
github.com/lyft/protoc-gen-star/v2 v2.0.3 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/sergi/go-diff v1.3.1 // indirect
|
github.com/sergi/go-diff v1.3.1 // indirect
|
||||||
|
github.com/sijms/go-ora/v2 v2.6.7 // indirect
|
||||||
github.com/skeema/knownhosts v1.2.0 // indirect
|
github.com/skeema/knownhosts v1.2.0 // indirect
|
||||||
|
github.com/spf13/afero v1.3.3 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
go.unistack.org/micro-proto/v4 v4.0.1 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
|
go.unistack.org/cms-api-proto v0.0.5 // indirect
|
||||||
|
go.unistack.org/micro-broker-service/v3 v3.8.2 // indirect
|
||||||
|
go.unistack.org/micro-codec-yaml/v3 v3.10.0 // indirect
|
||||||
|
go.unistack.org/micro-config-env/v3 v3.8.5 // indirect
|
||||||
|
go.unistack.org/micro-config-file/v3 v3.8.3 // indirect
|
||||||
|
go.unistack.org/micro-config-flag/v3 v3.8.9 // indirect
|
||||||
|
go.unistack.org/micro-config-service/v3 v3.8.1 // indirect
|
||||||
golang.org/x/crypto v0.11.0 // indirect
|
golang.org/x/crypto v0.11.0 // indirect
|
||||||
golang.org/x/mod v0.12.0 // indirect
|
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||||
golang.org/x/net v0.12.0 // indirect
|
|
||||||
golang.org/x/sys v0.10.0 // indirect
|
golang.org/x/sys v0.10.0 // indirect
|
||||||
|
golang.org/x/text v0.11.0 // indirect
|
||||||
golang.org/x/tools v0.11.0 // indirect
|
golang.org/x/tools v0.11.0 // indirect
|
||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
|
||||||
|
google.golang.org/grpc v1.57.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
lukechampine.com/uint128 v1.3.0 // indirect
|
||||||
|
modernc.org/cc/v3 v3.40.0 // indirect
|
||||||
|
modernc.org/ccgo/v3 v3.16.13 // indirect
|
||||||
|
modernc.org/libc v1.22.3 // indirect
|
||||||
|
modernc.org/mathutil v1.5.0 // indirect
|
||||||
|
modernc.org/memory v1.5.0 // indirect
|
||||||
|
modernc.org/opt v0.1.3 // indirect
|
||||||
|
modernc.org/sqlite v1.21.0 // indirect
|
||||||
|
modernc.org/strutil v1.1.3 // indirect
|
||||||
|
modernc.org/token v1.1.0 // indirect
|
||||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
25
handler/encoders/json.go
Normal file
25
handler/encoders/json.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JSON struct{}
|
||||||
|
|
||||||
|
func (*JSON) Success(rw http.ResponseWriter, response interface{}) error {
|
||||||
|
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
rw.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
|
return errors.WithStack(json.NewEncoder(rw).Encode(response))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*JSON) Error(rw http.ResponseWriter, err *pb.Error, status int) error {
|
||||||
|
rw.Header().Set("Content-Type", "application/problem+json; charset=utf-8")
|
||||||
|
rw.WriteHeader(status)
|
||||||
|
|
||||||
|
return errors.WithStack(json.NewEncoder(rw).Encode(&pb.ErrorRsp{Error: err}))
|
||||||
|
}
|
51
handler/encoders/jsonpb.go
Normal file
51
handler/encoders/jsonpb.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package encoders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrWrongResponseType = errors.New("JSONProto: wrong response message type")
|
||||||
|
|
||||||
|
type JSONProto struct {
|
||||||
|
m protojson.MarshalOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJSONProto() *JSONProto {
|
||||||
|
return &JSONProto{m: protojson.MarshalOptions{
|
||||||
|
EmitUnpopulated: true,
|
||||||
|
UseProtoNames: false,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *JSONProto) Success(rw http.ResponseWriter, response interface{}) error {
|
||||||
|
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
rw.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
|
if v, ok := response.(proto.Message); ok {
|
||||||
|
return errors.WithStack(e.Fmarshal(rw, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrWrongResponseType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *JSONProto) Error(rw http.ResponseWriter, err *pb.Error, status int) error {
|
||||||
|
rw.Header().Set("Content-Type", "application/problem+json; charset=utf-8")
|
||||||
|
rw.WriteHeader(status)
|
||||||
|
|
||||||
|
return errors.WithStack(e.Fmarshal(rw, &pb.ErrorRsp{Error: err}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *JSONProto) Fmarshal(w io.Writer, m proto.Message) error {
|
||||||
|
b, err := e.m.Marshal(m)
|
||||||
|
if len(b) > 0 {
|
||||||
|
if _, err = w.Write(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
67
handler/errors.go
Normal file
67
handler/errors.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import "github.com/pkg/errors"
|
||||||
|
|
||||||
|
type UnmarshalError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *UnmarshalError) Error() string {
|
||||||
|
return e.err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *UnmarshalError) Unwrap() error {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnmarshalError(err error) error {
|
||||||
|
return errors.WithStack(&UnmarshalError{err: err})
|
||||||
|
}
|
||||||
|
|
||||||
|
type InternalError struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *InternalError) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInternalError(err error) error {
|
||||||
|
return errors.WithStack(&InternalError{Err: err})
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParametersMissingError struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ParametersMissingError) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewParametersMissingError(err error) error {
|
||||||
|
return errors.WithStack(&ParametersMissingError{Err: err})
|
||||||
|
}
|
||||||
|
|
||||||
|
type NotFoundError struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *NotFoundError) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNotFoundError(err error) error {
|
||||||
|
return errors.WithStack(&NotFoundError{Err: err})
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValidationError struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ValidationError) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewValidationError(err error) error {
|
||||||
|
return errors.WithStack(&ValidationError{Err: err})
|
||||||
|
}
|
74
handler/handlers.go
Normal file
74
handler/handlers.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
cmsstorage "go.unistack.org/cms-service/storage"
|
||||||
|
"go.unistack.org/micro/v3"
|
||||||
|
"go.unistack.org/micro/v3/errors"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/config"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/models"
|
||||||
|
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/storage"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
svc micro.Service
|
||||||
|
store storage.Storage
|
||||||
|
|
||||||
|
writer writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) ListPackage(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
logger := h.svc.Logger()
|
||||||
|
logger.Debug(ctx, "Start getListPackage")
|
||||||
|
|
||||||
|
dbRsp, err := h.store.List(ctx)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf(ctx, "error db response: %v", err)
|
||||||
|
h.writer.Response(ctx, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp := new(pb.ListPackageRsp)
|
||||||
|
rsp.Packages = models.ListPackage(dbRsp).Mapping()
|
||||||
|
|
||||||
|
logger.Debug(ctx, "Success finish getListPackage")
|
||||||
|
h.writer.Response(ctx, w, rsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) UpdateInfo(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
logger := h.svc.Logger()
|
||||||
|
logger.Debug(ctx, "Start UpdateInfo")
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) AddComment(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
logger := h.svc.Logger()
|
||||||
|
logger.Debug(ctx, "Start AddComment")
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandler(svc micro.Service, w writer) *Handler {
|
||||||
|
return &Handler{svc: svc, writer: w}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) Init(ctx context.Context) error {
|
||||||
|
store := cmsstorage.InterfaceFromContext(h.svc.Options().Context)
|
||||||
|
if store == nil {
|
||||||
|
return cmsstorage.ErrMissingStorage
|
||||||
|
}
|
||||||
|
st, ok := store.(storage.Storage)
|
||||||
|
if !ok {
|
||||||
|
return errors.New(config.ServiceName, "error init storage", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.store = st
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
34
handler/mapping.go
Normal file
34
handler/mapping.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
internalErrorCode = "1"
|
||||||
|
badRequestCode = "2"
|
||||||
|
notFoundErrorCode = "3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mapError(ctx context.Context, err error) (result *pb.Error, status int) {
|
||||||
|
status = http.StatusBadRequest
|
||||||
|
|
||||||
|
switch errors.Unwrap(err).(type) {
|
||||||
|
case *UnmarshalError:
|
||||||
|
result = &pb.Error{Code: badRequestCode, Title: "Bad request"}
|
||||||
|
case *ParametersMissingError:
|
||||||
|
result = &pb.Error{Code: badRequestCode, Title: "Required parameters are missing"}
|
||||||
|
case *NotFoundError:
|
||||||
|
result = &pb.Error{Code: notFoundErrorCode, Title: "Not found"}
|
||||||
|
status = http.StatusNotFound
|
||||||
|
default:
|
||||||
|
status = http.StatusInternalServerError
|
||||||
|
result = &pb.Error{Code: internalErrorCode, Title: "Internal error", Details: err.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
76
handler/writer.go
Normal file
76
handler/writer.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"go.unistack.org/micro/v4/logger"
|
||||||
|
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type encoder interface {
|
||||||
|
Success(rw http.ResponseWriter, response interface{}) error
|
||||||
|
Error(rw http.ResponseWriter, err *pb.Error, status int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type writer interface {
|
||||||
|
Response(ctx context.Context, rw http.ResponseWriter, value interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type stackTracer interface {
|
||||||
|
StackTrace() errors.StackTrace
|
||||||
|
}
|
||||||
|
|
||||||
|
type Writer struct {
|
||||||
|
encoder encoder
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriter(encoder encoder) (*Writer, error) {
|
||||||
|
if encoder == nil {
|
||||||
|
return nil, errors.New("empty encoder")
|
||||||
|
}
|
||||||
|
return &Writer{encoder: encoder}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) Response(ctx context.Context, rw http.ResponseWriter, value interface{}) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if v, ok := value.(error); ok {
|
||||||
|
err = w.error(ctx, rw, v)
|
||||||
|
} else {
|
||||||
|
err = w.success(rw, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(ctx, "Response writing error: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) error(ctx context.Context, rw http.ResponseWriter, err error) error {
|
||||||
|
e, status := mapError(ctx, err)
|
||||||
|
/*
|
||||||
|
switch {
|
||||||
|
case status >= http.StatusInternalServerError:
|
||||||
|
logger.Errorf(ctx, "error: %s, code: %s, http status: %d, uuid: %s", err, e.Code, status, e.Uuid)
|
||||||
|
|
||||||
|
if err, ok := err.(stackTracer); ok {
|
||||||
|
logger.Errorf(ctx, "error stacktrace: %+v, uuid: %s", err.StackTrace(), e.Uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
logger.Infof(ctx, "error: %s, code: %s, http status: %d, uuid: %s", err, e.Code, status, e.Uuid)
|
||||||
|
|
||||||
|
if err, ok := err.(stackTracer); ok {
|
||||||
|
logger.Infof(ctx, "error stacktrace: %+v, uuid: %s", err.StackTrace(), e.Uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
return w.encoder.Error(rw, e, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) success(rw http.ResponseWriter, value interface{}) error {
|
||||||
|
return w.encoder.Success(rw, value)
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
@ -1,4 +1,4 @@
|
|||||||
package main
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
10
main.go
10
main.go
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/internal"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -14,7 +15,6 @@ import (
|
|||||||
"github.com/go-git/go-git/v5/plumbing/filemode"
|
"github.com/go-git/go-git/v5/plumbing/filemode"
|
||||||
"github.com/go-git/go-git/v5/plumbing/object"
|
"github.com/go-git/go-git/v5/plumbing/object"
|
||||||
"github.com/go-git/go-git/v5/storage/memory"
|
"github.com/go-git/go-git/v5/storage/memory"
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
flagconfig "go.unistack.org/micro-config-flag/v4"
|
flagconfig "go.unistack.org/micro-config-flag/v4"
|
||||||
"go.unistack.org/micro/v4/config"
|
"go.unistack.org/micro/v4/config"
|
||||||
"go.unistack.org/micro/v4/logger"
|
"go.unistack.org/micro/v4/logger"
|
||||||
@ -101,12 +101,12 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
Updates(UpdateOptions{
|
internal.Updates(internal.UpdateOptions{
|
||||||
Pre: false,
|
Pre: false,
|
||||||
Major: false,
|
Major: false,
|
||||||
Cached: false,
|
Cached: false,
|
||||||
Modules: mvs,
|
Modules: mvs,
|
||||||
OnUpdate: func(u Update) {
|
OnUpdate: func(u internal.Update) {
|
||||||
if u.Err != nil {
|
if u.Err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%s: failed: %v\n", u.Module.Path, u.Err)
|
fmt.Fprintf(os.Stderr, "%s: failed: %v\n", u.Module.Path, u.Err)
|
||||||
} else {
|
} else {
|
||||||
@ -152,8 +152,12 @@ func Direct(file *object.File) ([]module.Version, error) {
|
|||||||
return mods, nil
|
return mods, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func Periodic(ctx context.Context, db *sqlx.DB) error {
|
func Periodic(ctx context.Context, db *sqlx.DB) error {
|
||||||
|
|
||||||
db.
|
db.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
44
models/entities.go
Normal file
44
models/entities.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "database/sql"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/jackc/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Package struct {
|
||||||
|
ID int64 `db:"id"` // package id
|
||||||
|
Name string `db:"name"` // service name, last component path
|
||||||
|
URL string `db:"url"` // scm url
|
||||||
|
Modules []Module `db:"modules"` // parsed go.mod modules
|
||||||
|
Issues []Issue `db:"issues"` // issues list
|
||||||
|
Comments []int64 `db:"comments"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Module struct {
|
||||||
|
ID int64 `db:"id"`
|
||||||
|
Name string `db:"name"` // module name
|
||||||
|
Version string `db:"version"` // module
|
||||||
|
Package int64 `db:"package"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Issue struct {
|
||||||
|
ID int64 `db:"id"`
|
||||||
|
Status int64 `db:"status"`
|
||||||
|
Desc string `db:"desc"`
|
||||||
|
Package int64 `db:"package"`
|
||||||
|
Modules []int64 `db:"modules"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Comment struct {
|
||||||
|
ID int64 `db:"id"`
|
||||||
|
Text string `db:"value"`
|
||||||
|
Created pgtype.Date `db:"created"`
|
||||||
|
Updated pgtype.Date `db:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dashboard struct {
|
||||||
|
ID int64 `db:"id"`
|
||||||
|
Uuid uuid.UUID `db:"uuid"`
|
||||||
|
Package int64 `db:"package"`
|
||||||
|
}
|
13
models/mapping.go
Normal file
13
models/mapping.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
pb "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListPackage []*Package
|
||||||
|
|
||||||
|
func (l ListPackage) Mapping() []*pb.Package {
|
||||||
|
result := make([]*pb.Package, 0, len(l))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
76
proto/dashboard.proto
Normal file
76
proto/dashboard.proto
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package proto;
|
||||||
|
|
||||||
|
option go_package = "go.unistack.org/unistack-org/pkgdash/proto/go_generate;go_generate";
|
||||||
|
|
||||||
|
import "validate/validate.proto";
|
||||||
|
|
||||||
|
service DashboardService {
|
||||||
|
rpc ListPackage(ListPackageReq) returns (ListPackageRsp) {};
|
||||||
|
rpc UpdateInfo(UpdateInfoPackageRsp) returns (UpdateInfoPackageReq) {};
|
||||||
|
rpc AddComment(CommentRsp) returns (CommentReq) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
message ErrorRsp {
|
||||||
|
Error error = 1 [json_name = "error"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message Error {
|
||||||
|
string code = 1 [json_name = "code"];
|
||||||
|
string title = 2 [json_name = "title"];
|
||||||
|
string uuid = 3 [json_name = "uuid"];
|
||||||
|
string details = 4 [json_name = "details"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message Package {
|
||||||
|
uint64 id = 1 [(validate.rules).uint64.gt = 0];
|
||||||
|
string name = 2 [(validate.rules).string.min_len = 1];
|
||||||
|
string url = 3 [(validate.rules).string.min_len = 1];
|
||||||
|
repeated Module modules = 4;
|
||||||
|
repeated Issue issues = 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
message Module {
|
||||||
|
uint64 id = 1 [(validate.rules).uint64.gt = 0];
|
||||||
|
string name = 2 [(validate.rules).string.min_len = 1];
|
||||||
|
string version = 3 [(validate.rules).string.min_len = 1];
|
||||||
|
uint64 package = 4 [(validate.rules).uint64.gt = 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
message Issue {
|
||||||
|
uint64 id = 1 [(validate.rules).uint64.gt = 0];
|
||||||
|
uint64 status = 2 [(validate.rules).uint64.gt = 0];
|
||||||
|
string desc = 3 [(validate.rules).string.min_len = 1];
|
||||||
|
uint64 package = 4 [(validate.rules).uint64.gt = 0];
|
||||||
|
repeated uint64 modules = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Comment {
|
||||||
|
uint64 id = 1 [(validate.rules).uint64.gt = 0];
|
||||||
|
uint64 package = 2 [(validate.rules).uint64.gt = 0];
|
||||||
|
string text = 3;
|
||||||
|
uint64 created = 4 [(validate.rules).uint64.gt = 0];
|
||||||
|
uint64 updated = 5 [(validate.rules).uint64.gt = 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListPackageReq {}
|
||||||
|
message ListPackageRsp{
|
||||||
|
repeated Package packages = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateInfoPackageRsp {
|
||||||
|
uint64 id = 1 [(validate.rules).uint64.gt = 0];
|
||||||
|
}
|
||||||
|
message UpdateInfoPackageReq {
|
||||||
|
uint64 id = 1 [(validate.rules).uint64.gt = 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommentRsp {
|
||||||
|
uint64 idPackage = 1 [(validate.rules).uint64.gt = 0];
|
||||||
|
string text = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommentReq {
|
||||||
|
uint64 id = 1 [(validate.rules).uint64.gt = 0];
|
||||||
|
}
|
9
proto/generate.go
Normal file
9
proto/generate.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//go:build tools
|
||||||
|
// +build tools
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/envoyproxy/protoc-gen-validate"
|
||||||
|
_ "go.unistack.org/micro-proto/v3"
|
||||||
|
)
|
14
proto/generate.sh
Executable file
14
proto/generate.sh
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh -ex
|
||||||
|
|
||||||
|
PROTO_ARGS=" \
|
||||||
|
--proto_path=$(go list -f '{{ .Dir }}' -m github.com/envoyproxy/protoc-gen-validate) \
|
||||||
|
--proto_path=$(go list -f '{{ .Dir }}' -m go.unistack.org/micro-proto/v3) \
|
||||||
|
--go_out=paths=source_relative:go_generate \
|
||||||
|
--go-micro_out=module=go.unistack.org/unistack-org/pkgdash/proto/go_generate,components=micro|http,standalone=true:./micro \
|
||||||
|
--validate_out=paths=source_relative,lang=go:go_generate
|
||||||
|
"
|
||||||
|
|
||||||
|
find . -not \( -name "*.sh" -or -name "*.proto" -or -name "generate.go" \) -delete
|
||||||
|
mkdir -p micro go_generate && \
|
||||||
|
protoc -I. $PROTO_ARGS ./*.proto || \
|
||||||
|
find . -not \( -name "*.sh" -or -name "*.proto" -or -name "generate.go" \) -delete
|
1038
proto/go_generate/dashboard.pb.go
Normal file
1038
proto/go_generate/dashboard.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
1579
proto/go_generate/dashboard.pb.validate.go
Normal file
1579
proto/go_generate/dashboard.pb.validate.go
Normal file
File diff suppressed because it is too large
Load Diff
33
proto/micro/dashboard_micro.pb.go
Normal file
33
proto/micro/dashboard_micro.pb.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-micro v3.10.3
|
||||||
|
// - protoc v4.23.4
|
||||||
|
// source: dashboard.proto
|
||||||
|
|
||||||
|
package go_generate
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
v3 "go.unistack.org/micro-server-http/v3"
|
||||||
|
client "go.unistack.org/micro/v3/client"
|
||||||
|
go_generate "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DashboardServiceName = "DashboardService"
|
||||||
|
)
|
||||||
|
var (
|
||||||
|
DashboardServiceServerEndpoints = []v3.EndpointMetadata{}
|
||||||
|
)
|
||||||
|
|
||||||
|
type DashboardServiceClient interface {
|
||||||
|
ListPackage(ctx context.Context, req *go_generate.ListPackageReq, opts ...client.CallOption) (*go_generate.ListPackageRsp, error)
|
||||||
|
UpdateInfo(ctx context.Context, req *go_generate.UpdateInfoPackageRsp, opts ...client.CallOption) (*go_generate.UpdateInfoPackageReq, error)
|
||||||
|
AddComment(ctx context.Context, req *go_generate.CommentRsp, opts ...client.CallOption) (*go_generate.CommentReq, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DashboardServiceServer interface {
|
||||||
|
ListPackage(ctx context.Context, req *go_generate.ListPackageReq, rsp *go_generate.ListPackageRsp) error
|
||||||
|
UpdateInfo(ctx context.Context, req *go_generate.UpdateInfoPackageRsp, rsp *go_generate.UpdateInfoPackageReq) error
|
||||||
|
AddComment(ctx context.Context, req *go_generate.CommentRsp, rsp *go_generate.CommentReq) error
|
||||||
|
}
|
81
proto/micro/dashboard_micro_http.pb.go
Normal file
81
proto/micro/dashboard_micro_http.pb.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||||
|
// protoc-gen-go-micro version: v3.10.3
|
||||||
|
// source: dashboard.proto
|
||||||
|
|
||||||
|
package go_generate
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
_ "go.unistack.org/micro-client-http/v3"
|
||||||
|
v3 "go.unistack.org/micro-server-http/v3"
|
||||||
|
client "go.unistack.org/micro/v3/client"
|
||||||
|
server "go.unistack.org/micro/v3/server"
|
||||||
|
go_generate "go.unistack.org/unistack-org/pkgdash/proto/go_generate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type dashboardServiceClient struct {
|
||||||
|
c client.Client
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDashboardServiceClient(name string, c client.Client) DashboardServiceClient {
|
||||||
|
return &dashboardServiceClient{c: c, name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dashboardServiceClient) ListPackage(ctx context.Context, req *go_generate.ListPackageReq, opts ...client.CallOption) (*go_generate.ListPackageRsp, error) {
|
||||||
|
rsp := &go_generate.ListPackageRsp{}
|
||||||
|
err := c.c.Call(ctx, c.c.NewRequest(c.name, "DashboardService.ListPackage", req), rsp, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rsp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dashboardServiceClient) UpdateInfo(ctx context.Context, req *go_generate.UpdateInfoPackageRsp, opts ...client.CallOption) (*go_generate.UpdateInfoPackageReq, error) {
|
||||||
|
rsp := &go_generate.UpdateInfoPackageReq{}
|
||||||
|
err := c.c.Call(ctx, c.c.NewRequest(c.name, "DashboardService.UpdateInfo", req), rsp, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rsp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *dashboardServiceClient) AddComment(ctx context.Context, req *go_generate.CommentRsp, opts ...client.CallOption) (*go_generate.CommentReq, error) {
|
||||||
|
rsp := &go_generate.CommentReq{}
|
||||||
|
err := c.c.Call(ctx, c.c.NewRequest(c.name, "DashboardService.AddComment", req), rsp, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rsp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type dashboardServiceServer struct {
|
||||||
|
DashboardServiceServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *dashboardServiceServer) ListPackage(ctx context.Context, req *go_generate.ListPackageReq, rsp *go_generate.ListPackageRsp) error {
|
||||||
|
return h.DashboardServiceServer.ListPackage(ctx, req, rsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *dashboardServiceServer) UpdateInfo(ctx context.Context, req *go_generate.UpdateInfoPackageRsp, rsp *go_generate.UpdateInfoPackageReq) error {
|
||||||
|
return h.DashboardServiceServer.UpdateInfo(ctx, req, rsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *dashboardServiceServer) AddComment(ctx context.Context, req *go_generate.CommentRsp, rsp *go_generate.CommentReq) error {
|
||||||
|
return h.DashboardServiceServer.AddComment(ctx, req, rsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterDashboardServiceServer(s server.Server, sh DashboardServiceServer, opts ...server.HandlerOption) error {
|
||||||
|
type dashboardService interface {
|
||||||
|
ListPackage(ctx context.Context, req *go_generate.ListPackageReq, rsp *go_generate.ListPackageRsp) error
|
||||||
|
UpdateInfo(ctx context.Context, req *go_generate.UpdateInfoPackageRsp, rsp *go_generate.UpdateInfoPackageReq) error
|
||||||
|
AddComment(ctx context.Context, req *go_generate.CommentRsp, rsp *go_generate.CommentReq) error
|
||||||
|
}
|
||||||
|
type DashboardService struct {
|
||||||
|
dashboardService
|
||||||
|
}
|
||||||
|
h := &dashboardServiceServer{sh}
|
||||||
|
var nopts []server.HandlerOption
|
||||||
|
nopts = append(nopts, v3.HandlerEndpoints(DashboardServiceServerEndpoints))
|
||||||
|
return s.Handle(s.NewHandler(&DashboardService{h}, append(nopts, opts...)...))
|
||||||
|
}
|
9
service/embed.go
Normal file
9
service/embed.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
service "go.unistack.org/cms-service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
service.RegisterService("pkgdash", NewService)
|
||||||
|
}
|
145
service/service.go
Normal file
145
service/service.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
cmsstorage "go.unistack.org/cms-service/storage"
|
||||||
|
intcfg "go.unistack.org/unistack-org/pkgdash/config"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/handler"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/handler/encoders"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
//pbmicro "go.unistack.org/unistack-org/pkgdash/proto/micro"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/storage"
|
||||||
|
|
||||||
|
cmsservice "go.unistack.org/cms-service"
|
||||||
|
grpcsrv "go.unistack.org/micro-server-grpc/v3"
|
||||||
|
"go.unistack.org/micro/v3"
|
||||||
|
"go.unistack.org/micro/v3/config"
|
||||||
|
"go.unistack.org/micro/v3/logger"
|
||||||
|
"go.unistack.org/micro/v3/register"
|
||||||
|
microuter "go.unistack.org/micro/v3/router"
|
||||||
|
"go.unistack.org/micro/v3/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewService(ctx context.Context) (micro.Service, error) {
|
||||||
|
var reg register.Register
|
||||||
|
var router microuter.Router
|
||||||
|
|
||||||
|
if ctx == nil {
|
||||||
|
ctx = context.Background()
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := intcfg.NewConfig()
|
||||||
|
cs := cmsservice.NewConfigLocal(cfg)
|
||||||
|
|
||||||
|
if r, ok := register.FromContext(ctx); ok && r != nil {
|
||||||
|
reg = r
|
||||||
|
} else {
|
||||||
|
reg = register.NewRegister()
|
||||||
|
}
|
||||||
|
if r, ok := microuter.FromContext(ctx); ok && r != nil {
|
||||||
|
router = r
|
||||||
|
} else {
|
||||||
|
router = microuter.NewRouter()
|
||||||
|
}
|
||||||
|
|
||||||
|
mgsrv := grpcsrv.NewServer(
|
||||||
|
server.Register(reg),
|
||||||
|
)
|
||||||
|
|
||||||
|
svc := micro.NewService(
|
||||||
|
micro.Server(mgsrv),
|
||||||
|
micro.Register(reg),
|
||||||
|
micro.Router(router),
|
||||||
|
micro.Config(cs...),
|
||||||
|
)
|
||||||
|
|
||||||
|
writer, err := handler.NewWriter(encoders.NewJSONProto())
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatalf(ctx, "failed init writer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h := handler.NewHandler(svc, writer)
|
||||||
|
|
||||||
|
if err := svc.Init(
|
||||||
|
micro.AfterStart(func(_ context.Context) error {
|
||||||
|
return h.Init(svc.Options().Context)
|
||||||
|
}),
|
||||||
|
micro.BeforeStart(func(ctx context.Context) error {
|
||||||
|
if err := config.Load(ctx, cs, config.LoadOverride(true)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := config.Validate(ctx, cfg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := svc.Init(
|
||||||
|
micro.Name(cfg.Service.Name),
|
||||||
|
micro.Version(cfg.Service.Version),
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := svc.Server("http").Init(
|
||||||
|
server.Address(cfg.App.Address),
|
||||||
|
server.Name(cfg.Service.Name),
|
||||||
|
server.Version(cfg.Service.Version),
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}),
|
||||||
|
micro.BeforeStart(func(_ context.Context) error {
|
||||||
|
level := logger.InfoLevel
|
||||||
|
if v, ok := cfg.Logger.Level[cfg.Service.Name]; ok {
|
||||||
|
level = logger.ParseLevel(v)
|
||||||
|
} else if v, ok = cfg.Logger.Level["all"]; ok {
|
||||||
|
level = logger.ParseLevel(v)
|
||||||
|
}
|
||||||
|
log := logger.NewLogger(
|
||||||
|
logger.WithLevel(level),
|
||||||
|
logger.WithCallerSkipCount(3),
|
||||||
|
)
|
||||||
|
return svc.Init(micro.Logger(log))
|
||||||
|
}),
|
||||||
|
micro.BeforeStart(func(_ context.Context) error {
|
||||||
|
var connstr string
|
||||||
|
if v, ok := cfg.Storage.DSN[cfg.Service.Name]; ok {
|
||||||
|
connstr = v
|
||||||
|
} else if v, ok = cfg.Storage.DSN["all"]; ok {
|
||||||
|
connstr = v
|
||||||
|
}
|
||||||
|
scheme, dsn, err := cmsstorage.StorageOptions(connstr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
db, dbok := cmsstorage.FromContext(svc.Options().Context)
|
||||||
|
if !dbok {
|
||||||
|
db, err = cmsstorage.NewStorage(scheme, dsn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store, err := storage.NewStorage(scheme, db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return svc.Init(micro.Context(cmsstorage.InterfaceNewContext(svc.Options().Context, store)))
|
||||||
|
}),
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
mux.HandleFunc("/listPackage", h.ListPackage)
|
||||||
|
mux.HandleFunc("/updateInfo", h.UpdateInfo)
|
||||||
|
mux.HandleFunc("/addComment", h.AddComment)
|
||||||
|
|
||||||
|
if err = svc.Server().Handle(svc.Server().NewHandler(mux)); err != nil {
|
||||||
|
logger.Fatalf(ctx, "failed to register handler: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return svc, nil
|
||||||
|
}
|
1
storage/migrations/postgres/000001_init_schema.down.sql
Normal file
1
storage/migrations/postgres/000001_init_schema.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
drop table if exists dashboard, package, module, issue, comment;
|
37
storage/migrations/postgres/000001_init_schema.up.sql
Normal file
37
storage/migrations/postgres/000001_init_schema.up.sql
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
create table if not exists dashboard (
|
||||||
|
id serial not null unique primary key ,
|
||||||
|
"uniq_id" uuid not null unique default gen_random_uuid() ,
|
||||||
|
package integer
|
||||||
|
);
|
||||||
|
|
||||||
|
create table if not exists comment (
|
||||||
|
id serial not null unique primary key ,
|
||||||
|
text text ,
|
||||||
|
created timestamp not null default current_timestamp ,
|
||||||
|
updated timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
create table if not exists module (
|
||||||
|
id serial not null unique primary key ,
|
||||||
|
name varchar not null ,
|
||||||
|
version varchar not null
|
||||||
|
);
|
||||||
|
|
||||||
|
create table if not exists issue (
|
||||||
|
id serial not null unique primary key ,
|
||||||
|
--package integer references package(id) ,
|
||||||
|
modules integer[] ,
|
||||||
|
status integer default 0 ,
|
||||||
|
"desc" varchar
|
||||||
|
);
|
||||||
|
|
||||||
|
create table if not exists package (
|
||||||
|
id serial not null unique primary key ,
|
||||||
|
name varchar not null ,
|
||||||
|
url varchar ,
|
||||||
|
modules integer[] ,
|
||||||
|
issues integer[] ,
|
||||||
|
comments integer[]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
7
storage/postgres/quries.go
Normal file
7
storage/postgres/quries.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package postgres
|
||||||
|
|
||||||
|
const (
|
||||||
|
queryListPackage = `
|
||||||
|
select * from package;
|
||||||
|
`
|
||||||
|
)
|
83
storage/postgres/storage.go
Normal file
83
storage/postgres/storage.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package postgres
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"embed"
|
||||||
|
"errors"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/config"
|
||||||
|
|
||||||
|
"github.com/golang-migrate/migrate/v4"
|
||||||
|
"github.com/golang-migrate/migrate/v4/database/pgx"
|
||||||
|
"github.com/golang-migrate/migrate/v4/source/iofs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
pathMigration = `migrations/postgres`
|
||||||
|
)
|
||||||
|
|
||||||
|
type Postgres struct {
|
||||||
|
db *sql.DB
|
||||||
|
fs embed.FS
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStorage(db *sql.DB) (interface{}, error) {
|
||||||
|
return &Postgres{db: db}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStorageFS(fs embed.FS) func(*sql.DB) (interface{}, error) {
|
||||||
|
return func(db *sql.DB) (interface{}, error) {
|
||||||
|
return &Postgres{db: db, fs: fs}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Postgres) MigrateUp() error {
|
||||||
|
driver, err := pgx.WithInstance(s.db, &pgx.Config{
|
||||||
|
MigrationsTable: pgx.DefaultMigrationsTable,
|
||||||
|
DatabaseName: config.ServiceName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
source, err := iofs.New(s.fs, pathMigration)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: pass own logger
|
||||||
|
m, err := migrate.NewWithInstance("fs", source, config.ServiceName, driver)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = m.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Postgres) MigrateDown() error {
|
||||||
|
driver, err := pgx.WithInstance(s.db, &pgx.Config{
|
||||||
|
MigrationsTable: pgx.DefaultMigrationsTable,
|
||||||
|
DatabaseName: config.ServiceName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
source, err := iofs.New(s.fs, pathMigration)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: pass own logger
|
||||||
|
m, err := migrate.NewWithInstance("fs", source, config.ServiceName, driver)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = m.Down(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
32
storage/storage.go
Normal file
32
storage/storage.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"embed"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/models"
|
||||||
|
"go.unistack.org/unistack-org/pkgdash/storage/postgres"
|
||||||
|
|
||||||
|
cmsstorage "go.unistack.org/cms-service/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed migrations
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
var (
|
||||||
|
storages = cmsstorage.NewStorageInterface()
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
storages.RegisterStorage("postgres", postgres.NewStorageFS(fs))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Storage interface {
|
||||||
|
cmsstorage.Migrator
|
||||||
|
|
||||||
|
List(ctx context.Context) ([]*models.Package, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStorage(name string, db *sql.DB) (interface{}, error) {
|
||||||
|
return storages.NewStorage(name, db)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user