mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-11 19:04:35 +00:00
Add Contact API (#340)
* feat: add basic files of contact * chore: code review 1. delete redundant suffix 2. use tab replace whitespace in pb file * chore: add some comments and check post data validation * chore: add some comments * chore: add publicapi.json and examples.json * chore: update README.md * fix: code review conversations
This commit is contained in:
2
contact/.gitignore
vendored
Normal file
2
contact/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
contact
|
||||
3
contact/Dockerfile
Normal file
3
contact/Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM alpine
|
||||
ADD contact /contact
|
||||
ENTRYPOINT [ "/contact" ]
|
||||
28
contact/Makefile
Normal file
28
contact/Makefile
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
GOPATH:=$(shell go env GOPATH)
|
||||
.PHONY: init
|
||||
init:
|
||||
go get -u github.com/golang/protobuf/proto
|
||||
go get -u github.com/golang/protobuf/protoc-gen-go
|
||||
go get github.com/micro/micro/v3/cmd/protoc-gen-micro
|
||||
go get github.com/micro/micro/v3/cmd/protoc-gen-openapi
|
||||
|
||||
.PHONY: api
|
||||
api:
|
||||
protoc --openapi_out=. --proto_path=. proto/contact.proto
|
||||
|
||||
.PHONY: proto
|
||||
proto:
|
||||
protoc --proto_path=. --micro_out=. --go_out=:. proto/contact.proto
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
go build -o contact *.go
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -v ./... -cover
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
docker build . -t contact:latest
|
||||
5
contact/README.md
Normal file
5
contact/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Store your contacts
|
||||
|
||||
# Contact Service
|
||||
|
||||
This is the Contact service
|
||||
119
contact/domain/contact.go
Normal file
119
contact/domain/contact.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/micro/micro/v3/service/store"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
pb "github.com/micro/services/contact/proto"
|
||||
)
|
||||
|
||||
type Contact interface {
|
||||
Create(ctx context.Context, info *pb.ContactInfo) error
|
||||
Update(ctx context.Context, id string, info *pb.ContactInfo) error
|
||||
Read(ctx context.Context, id string) (result *pb.ContactInfo, err error)
|
||||
Delete(ctx context.Context, id string) error
|
||||
List(ctx context.Context, offset, limit uint) (result []*pb.ContactInfo, err error)
|
||||
}
|
||||
|
||||
type contact struct {
|
||||
store store.Store
|
||||
}
|
||||
|
||||
func NewContactDomain(s store.Store) *contact {
|
||||
return &contact{
|
||||
store: s,
|
||||
}
|
||||
}
|
||||
|
||||
// contactIdPrefix return the contact prefix of the store key
|
||||
func contactIdPrefix() string {
|
||||
return "contact/id/"
|
||||
}
|
||||
|
||||
// contactIdPrefix return the store key of one contact
|
||||
func contactIdKey(id string) string {
|
||||
return fmt.Sprintf("%s%s", contactIdPrefix(), id)
|
||||
}
|
||||
|
||||
// Create a contact
|
||||
func (c *contact) Create(ctx context.Context, info *pb.ContactInfo) error {
|
||||
info.CreatedAt = time.Now().Format(time.RFC3339)
|
||||
info.UpdatedAt = time.Now().Format(time.RFC3339)
|
||||
|
||||
val, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return store.Write(&store.Record{
|
||||
Key: contactIdKey(info.Id),
|
||||
Value: val,
|
||||
})
|
||||
}
|
||||
|
||||
// Update contact information by id
|
||||
func (c *contact) Update(ctx context.Context, id string, info *pb.ContactInfo) error {
|
||||
info.UpdatedAt = time.Now().Format(time.RFC3339)
|
||||
|
||||
val, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return store.Write(&store.Record{
|
||||
Key: contactIdKey(id),
|
||||
Value: val,
|
||||
})
|
||||
}
|
||||
|
||||
// Read one contact by id
|
||||
func (c *contact) Read(ctx context.Context, id string) (*pb.ContactInfo, error) {
|
||||
records, err := c.store.Read(contactIdKey(id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(records) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
}
|
||||
|
||||
info := &pb.ContactInfo{}
|
||||
if err := json.Unmarshal(records[0].Value, info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return info, err
|
||||
}
|
||||
|
||||
// Delete one contact by id
|
||||
func (c *contact) Delete(ctx context.Context, id string) error {
|
||||
return c.store.Delete(contactIdKey(id))
|
||||
}
|
||||
|
||||
// List contacts by offset and limit
|
||||
func (c *contact) List(ctx context.Context, offset, limit uint) (result []*pb.ContactInfo, err error) {
|
||||
records, err := c.store.Read(contactIdPrefix(),
|
||||
store.ReadPrefix(),
|
||||
store.ReadOffset(offset),
|
||||
store.ReadLimit(limit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(records) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
}
|
||||
|
||||
for _, rec := range records {
|
||||
cinfo := &pb.ContactInfo{}
|
||||
json.Unmarshal(rec.Value, cinfo)
|
||||
result = append(result, cinfo)
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
387
contact/examples.json
Normal file
387
contact/examples.json
Normal file
@@ -0,0 +1,387 @@
|
||||
{
|
||||
"create": [
|
||||
{
|
||||
"title": "Create a contact",
|
||||
"run_check": false,
|
||||
"description": "Create a contact with post data",
|
||||
"request": {
|
||||
"name": "joe",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-12345678"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"number": "010-87654321"
|
||||
}
|
||||
],
|
||||
"emails": [
|
||||
{
|
||||
"label": "home",
|
||||
"address": "home@example.com"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"address": "work@example.com"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"label": "blog",
|
||||
"url": "https://blog.joe.me"
|
||||
}
|
||||
],
|
||||
"birthday": "1995-01-01",
|
||||
"addresses": [
|
||||
{
|
||||
"label": "company address",
|
||||
"address": "https://company.of.joe.com"
|
||||
}
|
||||
],
|
||||
"social_medias": [
|
||||
{
|
||||
"label": "twitter",
|
||||
"username": "joe-twitter"
|
||||
},
|
||||
{
|
||||
"label": "facebook",
|
||||
"username": "joe-facebook"
|
||||
}
|
||||
],
|
||||
"note": "this person is very important"
|
||||
},
|
||||
"response": {
|
||||
"contact": {
|
||||
"id": "42e48a3c-6221-11ec-96d2-acde48001122",
|
||||
"name": "joe",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-12345678"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"number": "010-87654321"
|
||||
}
|
||||
],
|
||||
"emails": [
|
||||
{
|
||||
"label": "home",
|
||||
"address": "home@example.com"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"address": "work@example.com"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"label": "blog",
|
||||
"url": "https://blog.joe.me"
|
||||
}
|
||||
],
|
||||
"birthday": "1995-01-01",
|
||||
"addresses": [
|
||||
{
|
||||
"label": "company address",
|
||||
"address": "https://company.of.joe.com"
|
||||
}
|
||||
],
|
||||
"social_medias": [
|
||||
{
|
||||
"label": "twitter",
|
||||
"username": "joe-twitter"
|
||||
},
|
||||
{
|
||||
"label": "facebook",
|
||||
"username": "joe-facebook"
|
||||
}
|
||||
],
|
||||
"note": "this person is very important",
|
||||
"created_at": "2021-12-21T17:28:15+08:00",
|
||||
"updated_at": "2021-12-21T17:31:21+08:00"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"update": [
|
||||
{
|
||||
"title": "Update a contact",
|
||||
"run_check": false,
|
||||
"description": "Update a contact with post data",
|
||||
"request": {
|
||||
"id": "42e48a3c-6221-11ec-96d2-acde48001122",
|
||||
"name": "joe",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-12345678"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"number": "010-87654321"
|
||||
}
|
||||
],
|
||||
"emails": [
|
||||
{
|
||||
"label": "home",
|
||||
"address": "home@example.com"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"address": "work@example.com"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"label": "blog",
|
||||
"url": "https://blog.joe.me"
|
||||
}
|
||||
],
|
||||
"birthday": "1995-01-01",
|
||||
"addresses": [
|
||||
{
|
||||
"label": "company address",
|
||||
"address": "https://company.of.joe.com"
|
||||
}
|
||||
],
|
||||
"social_medias": [
|
||||
{
|
||||
"label": "twitter",
|
||||
"username": "joe-twitter"
|
||||
},
|
||||
{
|
||||
"label": "facebook",
|
||||
"username": "joe-facebook"
|
||||
}
|
||||
],
|
||||
"note": "this person is very important"
|
||||
},
|
||||
"response": {
|
||||
"contact": {
|
||||
"id": "42e48a3c-6221-11ec-96d2-acde48001122",
|
||||
"name": "joe",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-12345678"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"number": "010-87654321"
|
||||
}
|
||||
],
|
||||
"emails": [
|
||||
{
|
||||
"label": "home",
|
||||
"address": "home@example.com"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"address": "work@example.com"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"label": "blog",
|
||||
"url": "https://blog.joe.me"
|
||||
}
|
||||
],
|
||||
"birthday": "1995-01-01",
|
||||
"addresses": [
|
||||
{
|
||||
"label": "company address",
|
||||
"address": "https://company.of.joe.com"
|
||||
}
|
||||
],
|
||||
"social_medias": [
|
||||
{
|
||||
"label": "twitter",
|
||||
"username": "joe-twitter"
|
||||
},
|
||||
{
|
||||
"label": "facebook",
|
||||
"username": "joe-facebook"
|
||||
}
|
||||
],
|
||||
"note": "this person is very important",
|
||||
"created_at": "2021-12-21T17:28:15+08:00",
|
||||
"updated_at": "2021-12-21T17:31:21+08:00"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"read": [
|
||||
{
|
||||
"title": "Get a contact",
|
||||
"run_check": false,
|
||||
"description": "Get a contact by id",
|
||||
"request": {
|
||||
"id": "42e48a3c-6221-11ec-96d2-acde48001122"
|
||||
},
|
||||
"response": {
|
||||
"contact": {
|
||||
"id": "42e48a3c-6221-11ec-96d2-acde48001122",
|
||||
"name": "joe",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-12345678"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"number": "010-87654321"
|
||||
}
|
||||
],
|
||||
"emails": [
|
||||
{
|
||||
"label": "home",
|
||||
"address": "home@example.com"
|
||||
},
|
||||
{
|
||||
"label": "work",
|
||||
"address": "work@example.com"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"label": "blog",
|
||||
"url": "https://blog.joe.me"
|
||||
}
|
||||
],
|
||||
"birthday": "1995-01-01",
|
||||
"addresses": [
|
||||
{
|
||||
"label": "company address",
|
||||
"address": "https://company.of.joe.com"
|
||||
}
|
||||
],
|
||||
"social_medias": [
|
||||
{
|
||||
"label": "twitter",
|
||||
"username": "joe-twitter"
|
||||
},
|
||||
{
|
||||
"label": "facebook",
|
||||
"username": "joe-facebook"
|
||||
}
|
||||
],
|
||||
"note": "this person is very important",
|
||||
"created_at": "2021-12-21T17:28:15+08:00",
|
||||
"updated_at": "2021-12-21T17:31:21+08:00"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"delete": [
|
||||
{
|
||||
"title": "Delete a contact",
|
||||
"run_check": false,
|
||||
"description": "Delete a contact by id",
|
||||
"request": {
|
||||
"id": "42e48a3c-6221-11ec-96d2-acde48001122"
|
||||
},
|
||||
"response": {
|
||||
}
|
||||
}
|
||||
],
|
||||
"list": [
|
||||
{
|
||||
"title": "List contacts with default offset and limit, default limit is 20",
|
||||
"run_check": false,
|
||||
"description": "List contacts",
|
||||
"request": {
|
||||
},
|
||||
"response": {
|
||||
"contacts": [
|
||||
{
|
||||
"id": "7765a308-6222-11ec-96d2-acde48001122",
|
||||
"name": "contact-1",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-1234567"
|
||||
}
|
||||
],
|
||||
"emails": [],
|
||||
"links": [],
|
||||
"birthday": "",
|
||||
"addresses": [],
|
||||
"social_medias": [],
|
||||
"note": "",
|
||||
"created_at": "2021-12-21T17:28:15+08:00",
|
||||
"updated_at": "2021-12-21T17:31:21+08:00"
|
||||
},
|
||||
{
|
||||
"id": "7a7c1806-6222-11ec-96d2-acde48001122",
|
||||
"name": "contact-2",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-1234567"
|
||||
}
|
||||
],
|
||||
"emails": [],
|
||||
"links": [],
|
||||
"birthday": "",
|
||||
"addresses": [],
|
||||
"social_medias": [],
|
||||
"note": "",
|
||||
"created_at": "2021-12-21T17:28:15+08:00",
|
||||
"updated_at": "2021-12-21T17:31:21+08:00"
|
||||
},
|
||||
{
|
||||
"id": "7d4a8e28-6222-11ec-96d2-acde48001122",
|
||||
"name": "contact-3",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-1234567"
|
||||
}
|
||||
],
|
||||
"emails": [],
|
||||
"links": [],
|
||||
"birthday": "",
|
||||
"addresses": [],
|
||||
"social_medias": [],
|
||||
"note": "",
|
||||
"created_at": "2021-12-21T17:28:15+08:00",
|
||||
"updated_at": "2021-12-21T17:31:21+08:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "List contacts with specific offset and limit",
|
||||
"run_check": false,
|
||||
"description": "List contacts",
|
||||
"request": {
|
||||
"offset": 1,
|
||||
"limit": 1
|
||||
},
|
||||
"response": {
|
||||
"contacts": [
|
||||
{
|
||||
"id": "7a7c1806-6222-11ec-96d2-acde48001122",
|
||||
"name": "contact-2",
|
||||
"phones": [
|
||||
{
|
||||
"label": "home",
|
||||
"number": "010-1234567"
|
||||
}
|
||||
],
|
||||
"emails": [],
|
||||
"links": [],
|
||||
"birthday": "",
|
||||
"addresses": [],
|
||||
"social_medias": [],
|
||||
"note": "",
|
||||
"created_at": "2021-12-21T17:28:15+08:00",
|
||||
"updated_at": "2021-12-21T17:31:21+08:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
3
contact/generate.go
Normal file
3
contact/generate.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
//go:generate make proto
|
||||
127
contact/handler/contact.go
Normal file
127
contact/handler/contact.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/micro/v3/service/errors"
|
||||
|
||||
"github.com/micro/services/contact/domain"
|
||||
pb "github.com/micro/services/contact/proto"
|
||||
)
|
||||
|
||||
type contact struct {
|
||||
contact domain.Contact
|
||||
}
|
||||
|
||||
func NewContact(c domain.Contact) *contact {
|
||||
return &contact{
|
||||
contact: c,
|
||||
}
|
||||
}
|
||||
|
||||
// Create a contact
|
||||
func (c *contact) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error {
|
||||
req.Name = strings.TrimSpace(req.Name)
|
||||
if len(req.Name) == 0 {
|
||||
return errors.BadRequest("contact.create", "contact name is required")
|
||||
}
|
||||
|
||||
uid, err := uuid.NewUUID()
|
||||
if err != nil {
|
||||
return errors.InternalServerError("contact.create", "generate contact id error: %v", err)
|
||||
}
|
||||
|
||||
info := &pb.ContactInfo{
|
||||
Id: uid.String(),
|
||||
Name: req.Name,
|
||||
Phones: req.Phones,
|
||||
Emails: req.Emails,
|
||||
Links: req.Links,
|
||||
Birthday: req.Birthday,
|
||||
Addresses: req.Addresses,
|
||||
SocialMedias: req.SocialMedias,
|
||||
Note: req.Note,
|
||||
}
|
||||
|
||||
if err := c.contact.Create(ctx, info); err != nil {
|
||||
return errors.InternalServerError("contact.create", "create contact error: %v", err)
|
||||
}
|
||||
|
||||
rsp.Contact = info
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update information of the contact submitted
|
||||
func (c *contact) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error {
|
||||
req.Name = strings.TrimSpace(req.Name)
|
||||
if len(req.Name) == 0 {
|
||||
return errors.BadRequest("contact.create", "contact name is required")
|
||||
}
|
||||
|
||||
old, err := c.contact.Read(ctx, req.Id)
|
||||
if err != nil {
|
||||
return errors.InternalServerError("contact.update", "get contact info error: %v", err)
|
||||
}
|
||||
|
||||
info := &pb.ContactInfo{
|
||||
Id: req.Id,
|
||||
Name: req.Name,
|
||||
Phones: req.Phones,
|
||||
Emails: req.Emails,
|
||||
Links: req.Links,
|
||||
Birthday: req.Birthday,
|
||||
Addresses: req.Addresses,
|
||||
SocialMedias: req.SocialMedias,
|
||||
Note: req.Note,
|
||||
CreatedAt: old.CreatedAt,
|
||||
}
|
||||
|
||||
if err := c.contact.Update(ctx, req.Id, info); err != nil {
|
||||
return errors.InternalServerError("contact.update", "update contact error: %v", err)
|
||||
}
|
||||
|
||||
rsp.Contact = info
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read a contact by id
|
||||
func (c *contact) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error {
|
||||
info, err := c.contact.Read(ctx, req.Id)
|
||||
if err != nil {
|
||||
return errors.InternalServerError("contact.read", "get contact info error: %v", err)
|
||||
}
|
||||
|
||||
rsp.Contact = info
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete contact by id
|
||||
func (c *contact) Delete(ctx context.Context, req *pb.DeleteRequest, _ *pb.DeleteResponse) error {
|
||||
err := c.contact.Delete(ctx, req.Id)
|
||||
if err != nil {
|
||||
return errors.InternalServerError("contact.delete", "delete contact error: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// List contacts with offset and limit
|
||||
func (c *contact) List(ctx context.Context, req *pb.ListRequest, rsp *pb.ListResponse) error {
|
||||
if req.Limit == 0 {
|
||||
req.Limit = 30
|
||||
}
|
||||
|
||||
list, err := c.contact.List(ctx, uint(req.Offset), uint(req.Limit))
|
||||
if err != nil {
|
||||
return errors.InternalServerError("contact.list", "get contact info error: %v", err)
|
||||
}
|
||||
|
||||
rsp.Contacts = list
|
||||
|
||||
return nil
|
||||
}
|
||||
30
contact/main.go
Normal file
30
contact/main.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/micro/micro/v3/service/store"
|
||||
|
||||
"github.com/micro/services/contact/domain"
|
||||
"github.com/micro/services/contact/handler"
|
||||
pb "github.com/micro/services/contact/proto"
|
||||
|
||||
"github.com/micro/micro/v3/service"
|
||||
"github.com/micro/micro/v3/service/logger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create service
|
||||
srv := service.New(
|
||||
service.Name("contact"),
|
||||
service.Version("latest"),
|
||||
)
|
||||
|
||||
contactDomain := domain.NewContactDomain(store.DefaultStore)
|
||||
|
||||
// Register handler
|
||||
pb.RegisterContactHandler(srv.Server(), handler.NewContact(contactDomain))
|
||||
|
||||
// Run service
|
||||
if err := srv.Run(); err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
}
|
||||
1
contact/micro.mu
Normal file
1
contact/micro.mu
Normal file
@@ -0,0 +1 @@
|
||||
service contact
|
||||
1475
contact/proto/contact.pb.go
Normal file
1475
contact/proto/contact.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
161
contact/proto/contact.pb.micro.go
Normal file
161
contact/proto/contact.pb.micro.go
Normal file
@@ -0,0 +1,161 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: proto/contact.proto
|
||||
|
||||
package contact
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
import (
|
||||
context "context"
|
||||
api "github.com/micro/micro/v3/service/api"
|
||||
client "github.com/micro/micro/v3/service/client"
|
||||
server "github.com/micro/micro/v3/service/server"
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ api.Endpoint
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Api Endpoints for Contact service
|
||||
|
||||
func NewContactEndpoints() []*api.Endpoint {
|
||||
return []*api.Endpoint{}
|
||||
}
|
||||
|
||||
// Client API for Contact service
|
||||
|
||||
type ContactService interface {
|
||||
Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error)
|
||||
Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error)
|
||||
Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error)
|
||||
Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error)
|
||||
List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error)
|
||||
}
|
||||
|
||||
type contactService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewContactService(name string, c client.Client) ContactService {
|
||||
return &contactService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *contactService) Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Contact.Create", in)
|
||||
out := new(CreateResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contactService) Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Contact.Read", in)
|
||||
out := new(ReadResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contactService) Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Contact.Update", in)
|
||||
out := new(UpdateResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contactService) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Contact.Delete", in)
|
||||
out := new(DeleteResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *contactService) List(ctx context.Context, in *ListRequest, opts ...client.CallOption) (*ListResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Contact.List", in)
|
||||
out := new(ListResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Contact service
|
||||
|
||||
type ContactHandler interface {
|
||||
Create(context.Context, *CreateRequest, *CreateResponse) error
|
||||
Read(context.Context, *ReadRequest, *ReadResponse) error
|
||||
Update(context.Context, *UpdateRequest, *UpdateResponse) error
|
||||
Delete(context.Context, *DeleteRequest, *DeleteResponse) error
|
||||
List(context.Context, *ListRequest, *ListResponse) error
|
||||
}
|
||||
|
||||
func RegisterContactHandler(s server.Server, hdlr ContactHandler, opts ...server.HandlerOption) error {
|
||||
type contact interface {
|
||||
Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error
|
||||
Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error
|
||||
Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error
|
||||
Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error
|
||||
List(ctx context.Context, in *ListRequest, out *ListResponse) error
|
||||
}
|
||||
type Contact struct {
|
||||
contact
|
||||
}
|
||||
h := &contactHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Contact{h}, opts...))
|
||||
}
|
||||
|
||||
type contactHandler struct {
|
||||
ContactHandler
|
||||
}
|
||||
|
||||
func (h *contactHandler) Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error {
|
||||
return h.ContactHandler.Create(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *contactHandler) Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error {
|
||||
return h.ContactHandler.Read(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *contactHandler) Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error {
|
||||
return h.ContactHandler.Update(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *contactHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error {
|
||||
return h.ContactHandler.Delete(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *contactHandler) List(ctx context.Context, in *ListRequest, out *ListResponse) error {
|
||||
return h.ContactHandler.List(ctx, in, out)
|
||||
}
|
||||
151
contact/proto/contact.proto
Normal file
151
contact/proto/contact.proto
Normal file
@@ -0,0 +1,151 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package contact;
|
||||
|
||||
option go_package = "./proto;contact";
|
||||
|
||||
service Contact {
|
||||
rpc Create(CreateRequest) returns (CreateResponse) {}
|
||||
rpc Read(ReadRequest) returns (ReadResponse) {}
|
||||
rpc Update(UpdateRequest) returns (UpdateResponse) {}
|
||||
rpc Delete(DeleteRequest) returns (DeleteResponse) {}
|
||||
rpc List(ListRequest) returns (ListResponse) {}
|
||||
// TODO: wait for the search API
|
||||
// rpc Search(Request) returns (Response) {}
|
||||
}
|
||||
|
||||
message Phone {
|
||||
// the label of the phone number
|
||||
string label = 1;
|
||||
// phone number
|
||||
string number = 2;
|
||||
}
|
||||
|
||||
message Email {
|
||||
// the label of the email
|
||||
string label = 1;
|
||||
// the email address
|
||||
string address = 2;
|
||||
}
|
||||
|
||||
message Link {
|
||||
// the label of the link
|
||||
string label = 1;
|
||||
// the url of the contact
|
||||
string url = 2;
|
||||
}
|
||||
|
||||
message Address {
|
||||
// the label of the address
|
||||
string label = 1;
|
||||
// the address
|
||||
string address = 2;
|
||||
}
|
||||
|
||||
message SocialMedia {
|
||||
// the label of the social
|
||||
string label = 1;
|
||||
// the username of social media
|
||||
string username = 2;
|
||||
}
|
||||
|
||||
message ContactInfo {
|
||||
// contact id
|
||||
string id = 1;
|
||||
// the contact name
|
||||
string name = 2;
|
||||
// the phone numbers
|
||||
repeated Phone phones = 3;
|
||||
// the emails
|
||||
repeated Email emails = 4;
|
||||
// the contact links
|
||||
repeated Link links = 5;
|
||||
// the birthday
|
||||
string birthday = 6;
|
||||
// the address
|
||||
repeated Address addresses = 7;
|
||||
// the social media username
|
||||
repeated SocialMedia social_medias = 8;
|
||||
// note of the contact
|
||||
string note = 9;
|
||||
// create date string in RFC3339
|
||||
string created_at = 10;
|
||||
// update date string in RFC3339
|
||||
string updated_at = 11;
|
||||
}
|
||||
|
||||
message CreateRequest {
|
||||
// required, the name of the contact
|
||||
string name = 1;
|
||||
// optional, phone numbers
|
||||
repeated Phone phones = 2;
|
||||
// optional, emails
|
||||
repeated Email emails = 3;
|
||||
// optional, links
|
||||
repeated Link links = 4;
|
||||
// optional, birthday
|
||||
string birthday = 5;
|
||||
// optional, address
|
||||
repeated Address addresses = 6;
|
||||
// optional, social media
|
||||
repeated SocialMedia social_medias = 7;
|
||||
// optional, note of the contact
|
||||
string note = 8;
|
||||
}
|
||||
|
||||
message CreateResponse {
|
||||
ContactInfo contact = 1;
|
||||
}
|
||||
|
||||
message ReadRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ReadResponse {
|
||||
ContactInfo contact = 1;
|
||||
}
|
||||
|
||||
message DeleteRequest {
|
||||
// the id of the contact
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message DeleteResponse {
|
||||
}
|
||||
|
||||
|
||||
message UpdateRequest {
|
||||
// required, the contact id
|
||||
string id = 1;
|
||||
// required, the name
|
||||
string name = 2;
|
||||
// optional, phone number
|
||||
repeated Phone phones = 3;
|
||||
// optional, emails
|
||||
repeated Email emails = 4;
|
||||
// optional, links
|
||||
repeated Link links = 5;
|
||||
// optional, birthday
|
||||
string birthday = 6;
|
||||
// optional, addresses
|
||||
repeated Address addresses = 7;
|
||||
// optional, social media
|
||||
repeated SocialMedia social_medias = 8;
|
||||
// optional, note
|
||||
string note = 9;
|
||||
}
|
||||
|
||||
message UpdateResponse {
|
||||
ContactInfo contact = 1;
|
||||
}
|
||||
|
||||
message ListRequest {
|
||||
// optional
|
||||
uint32 offset = 1;
|
||||
// optional, default is 30
|
||||
uint32 limit = 2;
|
||||
}
|
||||
|
||||
message ListResponse {
|
||||
repeated ContactInfo contacts = 1;
|
||||
}
|
||||
6
contact/publicapi.json
Normal file
6
contact/publicapi.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "contact",
|
||||
"icon": "👥",
|
||||
"category": "communication",
|
||||
"display_name": "Contacts"
|
||||
}
|
||||
1
go.mod
1
go.mod
@@ -64,7 +64,6 @@ require (
|
||||
googlemaps.github.io/maps v1.3.1
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
||||
gorm.io/datatypes v1.0.1
|
||||
gorm.io/driver/postgres v1.0.8
|
||||
|
||||
2
go.sum
2
go.sum
@@ -493,8 +493,6 @@ github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KK
|
||||
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/micro/micro/v3 v3.8.0 h1:RTH2835RJ4/aqLZGMjGCIf7HroCmYlJh2KRHHuSL/AE=
|
||||
github.com/micro/micro/v3 v3.8.0/go.mod h1:gjFa8T2ouD6BvorPTVPXLWtrRJwSKT5KxUNuu23Kkts=
|
||||
github.com/micro/micro/v3 v3.8.1-0.20211216122745-2e7245423520 h1:LtErHRofRQf5damrjb5AkpvmklaIhx3anLJ9sN4fMrI=
|
||||
github.com/micro/micro/v3 v3.8.1-0.20211216122745-2e7245423520/go.mod h1:gjFa8T2ouD6BvorPTVPXLWtrRJwSKT5KxUNuu23Kkts=
|
||||
github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
|
||||
Reference in New Issue
Block a user