mirror of
https://github.com/Fishwaldo/huma.git
synced 2025-07-09 06:18:47 +00:00
103 lines
2.8 KiB
Go
103 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/danielgtaylor/huma"
|
|
"github.com/danielgtaylor/huma/cli"
|
|
"github.com/danielgtaylor/huma/middleware"
|
|
"github.com/danielgtaylor/huma/responses"
|
|
)
|
|
|
|
// NoteSummary is used to list notes. It does not include the (potentially)
|
|
// large note content.
|
|
type NoteSummary struct {
|
|
ID string `json:"id" doc:"Note ID"`
|
|
Created time.Time `json:"created" doc:"Created date/time as ISO8601"`
|
|
}
|
|
|
|
// NoteIDParam gets the note ID from the URI path.
|
|
type NoteIDParam struct {
|
|
NoteID string `path:"note-id" pattern:"^[a-zA-Z0-9._-]{1,32}$"`
|
|
}
|
|
|
|
// Note records some content text for later reference.
|
|
type Note struct {
|
|
Created time.Time `json:"created" readOnly:"true" doc:"Created date/time as ISO8601"`
|
|
Content string `json:"content" doc:"Note content"`
|
|
}
|
|
|
|
// We'll use an in-memory DB (a goroutine-safe map). Don't do this in
|
|
// production code!
|
|
var memoryDB = sync.Map{}
|
|
|
|
func main() {
|
|
// Create a new router and give our API a title and version.
|
|
app := cli.NewRouter("Notes API", "1.0.0")
|
|
app.ServerLink("Development server", "http://localhost:8888")
|
|
|
|
notes := app.Resource("/v1/notes")
|
|
notes.Get("list-notes", "Returns a list of all notes",
|
|
responses.OK().Model([]*NoteSummary{}),
|
|
).Run(func(ctx huma.Context) {
|
|
// Create a list of summaries from all the notes.
|
|
summaries := make([]*NoteSummary, 0)
|
|
|
|
memoryDB.Range(func(k, v interface{}) bool {
|
|
summaries = append(summaries, &NoteSummary{
|
|
ID: k.(string),
|
|
Created: v.(Note).Created,
|
|
})
|
|
return true
|
|
})
|
|
|
|
ctx.WriteModel(http.StatusOK, summaries)
|
|
})
|
|
|
|
// Add an `id` path parameter to create a note resource.
|
|
note := notes.SubResource("/{note-id}")
|
|
|
|
note.Put("put-note", "Create or update a note",
|
|
responses.NoContent(),
|
|
).Run(func(ctx huma.Context, input struct {
|
|
NoteIDParam
|
|
Body Note
|
|
}) {
|
|
// Set the created time to now and then save the note in the DB.
|
|
input.Body.Created = time.Now()
|
|
middleware.GetLogger(ctx).Info("Creating a new note")
|
|
memoryDB.Store(input.NoteID, input.Body)
|
|
})
|
|
|
|
note.Get("get-note", "Get a note by its ID",
|
|
responses.OK().Model(Note{}),
|
|
responses.NotFound(),
|
|
).Run(func(ctx huma.Context, input NoteIDParam) {
|
|
if n, ok := memoryDB.Load(input.NoteID); ok {
|
|
// Note with that ID exists!
|
|
ctx.WriteModel(http.StatusOK, n.(Note))
|
|
return
|
|
}
|
|
|
|
ctx.WriteError(http.StatusNotFound, "Note "+input.NoteID+" not found")
|
|
})
|
|
|
|
note.Delete("delete-note", "Delete a note by its ID",
|
|
responses.NoContent(),
|
|
responses.NotFound(),
|
|
).Run(func(ctx huma.Context, input NoteIDParam) {
|
|
if _, ok := memoryDB.Load(input.NoteID); ok {
|
|
// Note with that ID exists!
|
|
memoryDB.Delete(input.NoteID)
|
|
ctx.WriteHeader(http.StatusNoContent)
|
|
return
|
|
}
|
|
|
|
ctx.WriteError(http.StatusNotFound, "Note "+input.NoteID+" not found")
|
|
})
|
|
|
|
// Run the app!
|
|
app.Run()
|
|
}
|