private/apigen: Panic types defined in main package
The API generator was generating invalid code when types were defined in a main package because the generated Go code was defining in import from it. This commit update the Go generator to panic with a explicit error message if that situation happens. The commit also add a new endpoint to the example with a named types (i.e. no anonymous) to show that the Generator works fine with them. Change-Id: Ieddd89c67048de50516f7ac7787d602660dc4a54
This commit is contained in:
parent
7ab7ac49c8
commit
48d7be7eab
@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
"storj.io/common/uuid"
|
"storj.io/common/uuid"
|
||||||
"storj.io/storj/private/api"
|
"storj.io/storj/private/api"
|
||||||
|
"storj.io/storj/private/apigen/example/myapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dateLayout = "2006-01-02T15:04:05.999Z"
|
const dateLayout = "2006-01-02T15:04:05.999Z"
|
||||||
@ -23,6 +24,7 @@ const dateLayout = "2006-01-02T15:04:05.999Z"
|
|||||||
var ErrDocsAPI = errs.Class("example docs api")
|
var ErrDocsAPI = errs.Class("example docs api")
|
||||||
|
|
||||||
type DocumentsService interface {
|
type DocumentsService interface {
|
||||||
|
GetOne(ctx context.Context, path string) (*myapi.Document, api.HTTPError)
|
||||||
UpdateContent(ctx context.Context, path string, id uuid.UUID, date time.Time, request struct {
|
UpdateContent(ctx context.Context, path string, id uuid.UUID, date time.Time, request struct {
|
||||||
Content string "json:\"content\""
|
Content string "json:\"content\""
|
||||||
}) (*struct {
|
}) (*struct {
|
||||||
@ -50,11 +52,44 @@ func NewDocuments(log *zap.Logger, mon *monkit.Scope, service DocumentsService,
|
|||||||
}
|
}
|
||||||
|
|
||||||
docsRouter := router.PathPrefix("/api/v0/docs").Subrouter()
|
docsRouter := router.PathPrefix("/api/v0/docs").Subrouter()
|
||||||
|
docsRouter.HandleFunc("/{path}", handler.handleGetOne).Methods("GET")
|
||||||
docsRouter.HandleFunc("/{path}", handler.handleUpdateContent).Methods("POST")
|
docsRouter.HandleFunc("/{path}", handler.handleUpdateContent).Methods("POST")
|
||||||
|
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *DocumentsHandler) handleGetOne(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
var err error
|
||||||
|
defer h.mon.Task()(&ctx)(&err)
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
path, ok := mux.Vars(r)["path"]
|
||||||
|
if !ok {
|
||||||
|
api.ServeError(h.log, w, http.StatusBadRequest, errs.New("missing path route param"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, err = h.auth.IsAuthenticated(ctx, r, true, true)
|
||||||
|
if err != nil {
|
||||||
|
h.auth.RemoveAuthCookie(w)
|
||||||
|
api.ServeError(h.log, w, http.StatusUnauthorized, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal, httpErr := h.service.GetOne(ctx, path)
|
||||||
|
if httpErr.Err != nil {
|
||||||
|
api.ServeError(h.log, w, httpErr.Status, httpErr.Err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.NewEncoder(w).Encode(retVal)
|
||||||
|
if err != nil {
|
||||||
|
h.log.Debug("failed to write json GetOne response", zap.Error(ErrDocsAPI.Wrap(err)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (h *DocumentsHandler) handleUpdateContent(w http.ResponseWriter, r *http.Request) {
|
func (h *DocumentsHandler) handleUpdateContent(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
var err error
|
var err error
|
||||||
|
@ -7,8 +7,34 @@
|
|||||||
<h2 id='list-of-endpoints'>List of Endpoints</h2>
|
<h2 id='list-of-endpoints'>List of Endpoints</h2>
|
||||||
|
|
||||||
* Documents
|
* Documents
|
||||||
|
* [Get One](#documents-get-one)
|
||||||
* [Update Content](#documents-update-content)
|
* [Update Content](#documents-update-content)
|
||||||
|
|
||||||
|
<h3 id='documents-get-one'>Get One (<a href='#list-of-endpoints'>go to full list</a>)</h3>
|
||||||
|
|
||||||
|
Get one document with the specified version
|
||||||
|
|
||||||
|
`GET /api/v0/docs/{path}`
|
||||||
|
|
||||||
|
**Path Params:**
|
||||||
|
|
||||||
|
| name | type | elaboration |
|
||||||
|
|---|---|---|
|
||||||
|
| `path` | `string` | |
|
||||||
|
|
||||||
|
**Response body:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
id: string // UUID formatted as `00000000-0000-0000-0000-000000000000`
|
||||||
|
date: string // Date timestamp formatted as `2006-01-02T15:00:00Z`
|
||||||
|
pathParam: string
|
||||||
|
body: string
|
||||||
|
version: number
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
<h3 id='documents-update-content'>Update Content (<a href='#list-of-endpoints'>go to full list</a>)</h3>
|
<h3 id='documents-update-content'>Update Content (<a href='#list-of-endpoints'>go to full list</a>)</h3>
|
||||||
|
|
||||||
Update the content of the document with the specified path and ID if the last update is before the indicated date
|
Update the content of the document with the specified path and ID if the last update is before the indicated date
|
||||||
|
@ -4,6 +4,14 @@
|
|||||||
import { HttpClient } from '@/utils/httpClient';
|
import { HttpClient } from '@/utils/httpClient';
|
||||||
import { Time, UUID } from '@/types/common';
|
import { Time, UUID } from '@/types/common';
|
||||||
|
|
||||||
|
export class Document {
|
||||||
|
id: UUID;
|
||||||
|
date: Time;
|
||||||
|
pathParam: string;
|
||||||
|
body: string;
|
||||||
|
version: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class UpdateContentRequest {
|
export class UpdateContentRequest {
|
||||||
content: string;
|
content: string;
|
||||||
}
|
}
|
||||||
@ -19,6 +27,16 @@ export class docsHttpApiV0 {
|
|||||||
private readonly http: HttpClient = new HttpClient();
|
private readonly http: HttpClient = new HttpClient();
|
||||||
private readonly ROOT_PATH: string = '/api/v0/docs';
|
private readonly ROOT_PATH: string = '/api/v0/docs';
|
||||||
|
|
||||||
|
public async GetOne(path: string): Promise<Document> {
|
||||||
|
const fullPath = `${this.ROOT_PATH}/${path}`;
|
||||||
|
const response = await this.http.get(fullPath);
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json().then((body) => body as Document);
|
||||||
|
}
|
||||||
|
const err = await response.json();
|
||||||
|
throw new Error(err.error);
|
||||||
|
}
|
||||||
|
|
||||||
public async UpdateContent(request: UpdateContentRequest, path: string, id: UUID, date: Time): Promise<UpdateContentResponse> {
|
public async UpdateContent(request: UpdateContentRequest, path: string, id: UUID, date: Time): Promise<UpdateContentResponse> {
|
||||||
const u = new URL(`${this.ROOT_PATH}/${path}`);
|
const u = new URL(`${this.ROOT_PATH}/${path}`);
|
||||||
u.searchParams.set('id', id);
|
u.searchParams.set('id', id);
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"storj.io/common/uuid"
|
"storj.io/common/uuid"
|
||||||
"storj.io/storj/private/apigen"
|
"storj.io/storj/private/apigen"
|
||||||
|
"storj.io/storj/private/apigen/example/myapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -18,6 +19,16 @@ func main() {
|
|||||||
|
|
||||||
g := a.Group("Documents", "docs")
|
g := a.Group("Documents", "docs")
|
||||||
|
|
||||||
|
g.Get("/{path}", &apigen.Endpoint{
|
||||||
|
Name: "Get One",
|
||||||
|
Description: "Get one document with the specified version",
|
||||||
|
MethodName: "GetOne",
|
||||||
|
Response: myapi.Document{},
|
||||||
|
PathParams: []apigen.Param{
|
||||||
|
apigen.NewParam("path", ""),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
g.Post("/{path}", &apigen.Endpoint{
|
g.Post("/{path}", &apigen.Endpoint{
|
||||||
Name: "Update Content",
|
Name: "Update Content",
|
||||||
Description: "Update the content of the document with the specified path and ID if the last update is before the indicated date",
|
Description: "Update the content of the document with the specified path and ID if the last update is before the indicated date",
|
||||||
|
19
private/apigen/example/myapi/types.go
Normal file
19
private/apigen/example/myapi/types.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (C) 2023 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
package myapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"storj.io/common/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Document is a retrieved document.
|
||||||
|
type Document struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
Date time.Time `json:"date"`
|
||||||
|
PathParam string `json:"pathParam"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Version uint `json:"version"`
|
||||||
|
}
|
@ -42,7 +42,12 @@ func (a *API) generateGo() ([]byte, error) {
|
|||||||
|
|
||||||
getPackageName := func(path string) string {
|
getPackageName := func(path string) string {
|
||||||
pathPackages := strings.Split(path, "/")
|
pathPackages := strings.Split(path, "/")
|
||||||
return pathPackages[len(pathPackages)-1]
|
name := pathPackages[len(pathPackages)-1]
|
||||||
|
if name == "main" {
|
||||||
|
panic(errs.New(`invalid package name. Your types cannot be defined in a package named "main"`))
|
||||||
|
}
|
||||||
|
|
||||||
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
imports := struct {
|
imports := struct {
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"storj.io/storj/private/api"
|
"storj.io/storj/private/api"
|
||||||
"storj.io/storj/private/apigen"
|
"storj.io/storj/private/apigen"
|
||||||
"storj.io/storj/private/apigen/example"
|
"storj.io/storj/private/apigen/example"
|
||||||
|
"storj.io/storj/private/apigen/example/myapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -44,6 +45,13 @@ func (a auth) IsAuthenticated(ctx context.Context, r *http.Request, isCookieAuth
|
|||||||
|
|
||||||
func (a auth) RemoveAuthCookie(w http.ResponseWriter) {}
|
func (a auth) RemoveAuthCookie(w http.ResponseWriter) {}
|
||||||
|
|
||||||
|
func (s service) GetOne(
|
||||||
|
ctx context.Context,
|
||||||
|
pathParam string,
|
||||||
|
) (*myapi.Document, api.HTTPError) {
|
||||||
|
return &myapi.Document{}, api.HTTPError{}
|
||||||
|
}
|
||||||
|
|
||||||
func (s service) UpdateContent(
|
func (s service) UpdateContent(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
pathParam string,
|
pathParam string,
|
||||||
|
Loading…
Reference in New Issue
Block a user